The driver core supports the ability to handle the creation and removal of device-specific sysfs files in a race-free manner. Moreover, it can guarantee the success of creation. Therefore, it should be better to convert to use dev_groups. Signed-off-by: Jiasheng Jiang <jiasheng@xxxxxxxxxxx> --- Changelog: v4 -> v5: 1. Use a forward declaration for ftdi_sio_groups. 2. Correct ftdi_sio_attr_is_visible() implementation. v3 -> v4: 1. Move the code and remove the pre-definitions. v2 -> v3: 1. Add is_visible to filter the unneeded files. v1 -> v2: 1. Change the title. 2. Switch to use an attribute group. --- drivers/usb/serial/ftdi_sio.c | 60 +++++++++++++++++------------------ 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d5a3986dfee7..660181064cda 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1108,10 +1108,13 @@ static u32 ftdi_232bm_baud_to_divisor(int baud); static u32 ftdi_2232h_baud_base_to_divisor(int baud, int base); static u32 ftdi_2232h_baud_to_divisor(int baud); +extern const struct attribute_group *ftdi_sio_groups[]; + static struct usb_serial_driver ftdi_sio_device = { .driver = { .owner = THIS_MODULE, .name = "ftdi_sio", + .dev_groups = ftdi_sio_groups, }, .description = "FTDI USB Serial Device", .id_table = id_table_combined, @@ -1729,38 +1732,19 @@ static ssize_t event_char_store(struct device *dev, } static DEVICE_ATTR_WO(event_char); -static int create_sysfs_attrs(struct usb_serial_port *port) +static umode_t ftdi_sio_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int idx) { + struct device *dev = kobj_to_dev(kobj); + struct usb_serial_port *port = container_of(dev, struct usb_serial_port, dev); struct ftdi_private *priv = usb_get_serial_port_data(port); - int retval = 0; + umode_t mode = attr->mode; /* XXX I've no idea if the original SIO supports the event_char * sysfs parameter, so I'm playing it safe. */ if (priv->chip_type != SIO) { - dev_dbg(&port->dev, "sysfs attributes for %s\n", ftdi_chip_name[priv->chip_type]); - retval = device_create_file(&port->dev, &dev_attr_event_char); - if ((!retval) && - (priv->chip_type == FT232BM || - priv->chip_type == FT2232C || - priv->chip_type == FT232RL || - priv->chip_type == FT2232H || - priv->chip_type == FT4232H || - priv->chip_type == FT232H || - priv->chip_type == FTX)) { - retval = device_create_file(&port->dev, - &dev_attr_latency_timer); - } - } - return retval; -} - -static void remove_sysfs_attrs(struct usb_serial_port *port) -{ - struct ftdi_private *priv = usb_get_serial_port_data(port); - - /* XXX see create_sysfs_attrs */ - if (priv->chip_type != SIO) { - device_remove_file(&port->dev, &dev_attr_event_char); + if (attr == &dev_attr_event_char.attr) + return mode; if (priv->chip_type == FT232BM || priv->chip_type == FT2232C || priv->chip_type == FT232RL || @@ -1768,12 +1752,29 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) priv->chip_type == FT4232H || priv->chip_type == FT232H || priv->chip_type == FTX) { - device_remove_file(&port->dev, &dev_attr_latency_timer); + if (attr == &dev_attr_latency_timer.attr) + return mode; } } - + return 0; } +static struct attribute *ftdi_sio_attrs[] = { + &dev_attr_event_char.attr, + &dev_attr_latency_timer.attr, + NULL, +}; + +static const struct attribute_group ftdi_sio_group = { + .attrs = ftdi_sio_attrs, + .is_visible = ftdi_sio_attr_is_visible, +}; + +const struct attribute_group *ftdi_sio_groups[] = { + &ftdi_sio_group, + NULL +}; + #ifdef CONFIG_GPIOLIB static int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode) @@ -2251,7 +2252,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) if (read_latency_timer(port) < 0) priv->latency = 16; write_latency_timer(port); - create_sysfs_attrs(port); result = ftdi_gpio_init(port); if (result < 0) { @@ -2377,8 +2377,6 @@ static void ftdi_sio_port_remove(struct usb_serial_port *port) ftdi_gpio_remove(port); - remove_sysfs_attrs(port); - kfree(priv); } -- 2.25.1