Skip to content

Commit 68eeb08

Browse files
Hans de Goedehdeller
authored andcommitted
fbdev: Use device_create_with_groups() to fix sysfs groups registration race
The fbdev sysfs attributes are registered after sending the uevent for the device creation, leaving a race window where e.g. udev rules may not be able to access the sysfs attributes because the registration is not done yet. Fix this by switching to device_create_with_groups(). This also results in a nice cleanup. After switching to device_create_with_groups() all that is left of fb_init_device() is setting the drvdata and that can be passed to device_create[_with_groups]() too. After which fb_init_device() can be completely removed. Dropping fb_init_device() + fb_cleanup_device() in turn allows removing fb_info.class_flag as they were the only user of this field. Fixes: 5fc830d ("fbdev: Register sysfs groups through device_add_group") Cc: stable@vger.kernel.org Cc: Shixiong Ou <oushixiong@kylinos.cn> Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com> Signed-off-by: Helge Deller <deller@gmx.de>
1 parent 120adae commit 68eeb08

2 files changed

Lines changed: 3 additions & 34 deletions

File tree

drivers/video/fbdev/core/fbsysfs.c

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212

1313
#include "fb_internal.h"
1414

15-
#define FB_SYSFS_FLAG_ATTR 1
16-
1715
static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
1816
{
1917
int err;
@@ -451,48 +449,21 @@ static struct attribute *fb_device_attrs[] = {
451449
NULL,
452450
};
453451

454-
static const struct attribute_group fb_device_attr_group = {
455-
.attrs = fb_device_attrs,
456-
};
457-
458-
static int fb_init_device(struct fb_info *fb_info)
459-
{
460-
int ret;
461-
462-
dev_set_drvdata(fb_info->dev, fb_info);
463-
464-
fb_info->class_flag |= FB_SYSFS_FLAG_ATTR;
465-
466-
ret = device_add_group(fb_info->dev, &fb_device_attr_group);
467-
if (ret)
468-
fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
469-
470-
return 0;
471-
}
472-
473-
static void fb_cleanup_device(struct fb_info *fb_info)
474-
{
475-
if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) {
476-
device_remove_group(fb_info->dev, &fb_device_attr_group);
477-
478-
fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
479-
}
480-
}
452+
ATTRIBUTE_GROUPS(fb_device);
481453

482454
int fb_device_create(struct fb_info *fb_info)
483455
{
484456
int node = fb_info->node;
485457
dev_t devt = MKDEV(FB_MAJOR, node);
486458
int ret;
487459

488-
fb_info->dev = device_create(fb_class, fb_info->device, devt, NULL, "fb%d", node);
460+
fb_info->dev = device_create_with_groups(fb_class, fb_info->device, devt, fb_info,
461+
fb_device_groups, "fb%d", node);
489462
if (IS_ERR(fb_info->dev)) {
490463
/* Not fatal */
491464
ret = PTR_ERR(fb_info->dev);
492465
pr_warn("Unable to create device for framebuffer %d; error %d\n", node, ret);
493466
fb_info->dev = NULL;
494-
} else {
495-
fb_init_device(fb_info);
496467
}
497468

498469
return 0;
@@ -505,7 +476,6 @@ void fb_device_destroy(struct fb_info *fb_info)
505476
if (!fb_info->dev)
506477
return;
507478

508-
fb_cleanup_device(fb_info);
509479
device_destroy(fb_class, devt);
510480
fb_info->dev = NULL;
511481
}

include/linux/fb.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,6 @@ struct fb_info {
493493
#if defined(CONFIG_FB_DEVICE)
494494
struct device *dev; /* This is this fb device */
495495
#endif
496-
int class_flag; /* private sysfs flags */
497496
#ifdef CONFIG_FB_TILEBLITTING
498497
struct fb_tile_ops *tileops; /* Tile Blitting */
499498
#endif

0 commit comments

Comments
 (0)