diff mbox series

[v5] USB: serial: ftdi_sio: Convert to use dev_groups

Message ID 20220914071334.2820756-1-jiasheng@iscas.ac.cn (mailing list archive)
State New, archived
Headers show
Series [v5] USB: serial: ftdi_sio: Convert to use dev_groups | expand

Commit Message

Jiasheng Jiang Sept. 14, 2022, 7:13 a.m. UTC
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@iscas.ac.cn>
---
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(-)

Comments

Johan Hovold Sept. 19, 2022, 1:21 p.m. UTC | #1
On Wed, Sep 14, 2022 at 03:13:34PM +0800, Jiasheng Jiang wrote:
> 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.

I don't believe this is true, driver core just handles the errors.

> Therefore, it should be better to
> convert to use dev_groups.
> Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
> ---
> 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[];

Why did you use extern here? Should be static.

> +
>  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)

I'd drop the "sio" infix from all of these new symbols and just call
this one ftdi_is_visible().

>  {
> +	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,

nit: no need for comma after 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[] = {

Missing static.

> +	&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);
>  }

But in general this looks good now.

There has been some recent changes to how this driver handles device
types so I rebased this patch on top, fixed up the above and amended the
commit message. The result is here:

	https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial.git/commit/?h=usb-next&id=0f6632e2e8beb6a1e0895c1309dd0b84b805c202

Thanks.

Johan
diff mbox series

Patch

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);
 }