[PATCH v3] net/can/gs_usb: increase max interface to U8_MAX

Celeste Liu posted 1 patch 1 day, 20 hours ago
There is a newer version of this series
drivers/net/can/usb/gs_usb.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
[PATCH v3] net/can/gs_usb: increase max interface to U8_MAX
Posted by Celeste Liu 1 day, 20 hours ago
This issue was found by Runcheng Lu when develop HSCanT USB to CAN FD
converter[1]. The original developers may have only 3 intefaces device to
test so they write 3 here and wait for future change.

During the HSCanT development, we actually used 4 interfaces, so the
limitation of 3 is not enough now. But just increase one is not
future-proofed. Since the channel type in gs_host_frame is u8, just
increase interface number limit to max size of u8 safely.

[1]: https://github.com/cherry-embedded/HSCanT-hardware

Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices")
Reported-by: Runcheng Lu <runcheng.lu@hpmicro.com>
Cc: stable@vger.kernel.org
Signed-off-by: Celeste Liu <uwu@coelacanthus.name>
---
Changes in v3:
- Cc stable should in patch instead of cover letter.
- Link to v2: https://lore.kernel.org/r/20250930-gs-usb-max-if-v2-1-2cf9a44e6861@coelacanthus.name

Changes in v2:
- Use flexible array member instead of fixed array.
- Link to v1: https://lore.kernel.org/r/20250929-gs-usb-max-if-v1-1-e41b5c09133a@coelacanthus.name
---
 drivers/net/can/usb/gs_usb.c | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index c9482d6e947b0c7b033dc4f0c35f5b111e1bfd92..69b068c8fa8fbab42337e2b0a3d0860ac678c792 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -289,11 +289,6 @@ struct gs_host_frame {
 #define GS_MAX_RX_URBS 30
 #define GS_NAPI_WEIGHT 32
 
-/* Maximum number of interfaces the driver supports per device.
- * Current hardware only supports 3 interfaces. The future may vary.
- */
-#define GS_MAX_INTF 3
-
 struct gs_tx_context {
 	struct gs_can *dev;
 	unsigned int echo_id;
@@ -324,7 +319,6 @@ struct gs_can {
 
 /* usb interface struct */
 struct gs_usb {
-	struct gs_can *canch[GS_MAX_INTF];
 	struct usb_anchor rx_submitted;
 	struct usb_device *udev;
 
@@ -336,9 +330,11 @@ struct gs_usb {
 
 	unsigned int hf_size_rx;
 	u8 active_channels;
+	u8 channel_cnt;
 
 	unsigned int pipe_in;
 	unsigned int pipe_out;
+	struct gs_can *canch[] __counted_by(channel_cnt);
 };
 
 /* 'allocate' a tx context.
@@ -599,7 +595,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
 	}
 
 	/* device reports out of range channel id */
-	if (hf->channel >= GS_MAX_INTF)
+	if (hf->channel >= parent->channel_cnt)
 		goto device_detach;
 
 	dev = parent->canch[hf->channel];
@@ -699,7 +695,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
 	/* USB failure take down all interfaces */
 	if (rc == -ENODEV) {
 device_detach:
-		for (rc = 0; rc < GS_MAX_INTF; rc++) {
+		for (rc = 0; rc < parent->channel_cnt; rc++) {
 			if (parent->canch[rc])
 				netif_device_detach(parent->canch[rc]->netdev);
 		}
@@ -1460,17 +1456,19 @@ static int gs_usb_probe(struct usb_interface *intf,
 	icount = dconf.icount + 1;
 	dev_info(&intf->dev, "Configuring for %u interfaces\n", icount);
 
-	if (icount > GS_MAX_INTF) {
+	if (icount > type_max(typeof(parent->channel_cnt))) {
 		dev_err(&intf->dev,
 			"Driver cannot handle more that %u CAN interfaces\n",
-			GS_MAX_INTF);
+			type_max(typeof(parent->channel_cnt)));
 		return -EINVAL;
 	}
 
-	parent = kzalloc(sizeof(*parent), GFP_KERNEL);
+	parent = kzalloc(struct_size(parent, canch, icount), GFP_KERNEL);
 	if (!parent)
 		return -ENOMEM;
 
+	parent->channel_cnt = icount;
+
 	init_usb_anchor(&parent->rx_submitted);
 
 	usb_set_intfdata(intf, parent);
@@ -1531,7 +1529,7 @@ static void gs_usb_disconnect(struct usb_interface *intf)
 		return;
 	}
 
-	for (i = 0; i < GS_MAX_INTF; i++)
+	for (i = 0; i < parent->channel_cnt; i++)
 		if (parent->canch[i])
 			gs_destroy_candev(parent->canch[i]);
 

---
base-commit: e5f0a698b34ed76002dc5cff3804a61c80233a7a
change-id: 20250929-gs-usb-max-if-a304c83243e5

Best regards,
-- 
Celeste Liu <uwu@coelacanthus.name>
Re: [PATCH v3] net/can/gs_usb: increase max interface to U8_MAX
Posted by Vincent Mailhol 1 day, 17 hours ago
Hi Celeste,

Sorry, one last minute comment which I forgot in my previous message.

On 9/30/25 12:06 PM, Celeste Liu wrote:
> This issue was found by Runcheng Lu when develop HSCanT USB to CAN FD
> converter[1]. The original developers may have only 3 intefaces device to
> test so they write 3 here and wait for future change.
> 
> During the HSCanT development, we actually used 4 interfaces, so the
> limitation of 3 is not enough now. But just increase one is not
> future-proofed. Since the channel type in gs_host_frame is u8, just
> increase interface number limit to max size of u8 safely.
> 
> [1]: https://github.com/cherry-embedded/HSCanT-hardware
> 
> Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices")
> Reported-by: Runcheng Lu <runcheng.lu@hpmicro.com>
> Cc: stable@vger.kernel.org
> Signed-off-by: Celeste Liu <uwu@coelacanthus.name>
> ---
> Changes in v3:
> - Cc stable should in patch instead of cover letter.
> - Link to v2: https://lore.kernel.org/r/20250930-gs-usb-max-if-v2-1-2cf9a44e6861@coelacanthus.name
> 
> Changes in v2:
> - Use flexible array member instead of fixed array.
> - Link to v1: https://lore.kernel.org/r/20250929-gs-usb-max-if-v1-1-e41b5c09133a@coelacanthus.name
> ---
>  drivers/net/can/usb/gs_usb.c | 22 ++++++++++------------
>  1 file changed, 10 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
> index c9482d6e947b0c7b033dc4f0c35f5b111e1bfd92..69b068c8fa8fbab42337e2b0a3d0860ac678c792 100644
> --- a/drivers/net/can/usb/gs_usb.c
> +++ b/drivers/net/can/usb/gs_usb.c
> @@ -289,11 +289,6 @@ struct gs_host_frame {
>  #define GS_MAX_RX_URBS 30
>  #define GS_NAPI_WEIGHT 32
>  
> -/* Maximum number of interfaces the driver supports per device.
> - * Current hardware only supports 3 interfaces. The future may vary.
> - */
> -#define GS_MAX_INTF 3
> -
>  struct gs_tx_context {
>  	struct gs_can *dev;
>  	unsigned int echo_id;
> @@ -324,7 +319,6 @@ struct gs_can {
>  
>  /* usb interface struct */
>  struct gs_usb {
> -	struct gs_can *canch[GS_MAX_INTF];
>  	struct usb_anchor rx_submitted;
>  	struct usb_device *udev;
>  
> @@ -336,9 +330,11 @@ struct gs_usb {
>  
>  	unsigned int hf_size_rx;
>  	u8 active_channels;
> +	u8 channel_cnt;
>  
>  	unsigned int pipe_in;
>  	unsigned int pipe_out;
> +	struct gs_can *canch[] __counted_by(channel_cnt);
>  };
>  
>  /* 'allocate' a tx context.
> @@ -599,7 +595,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
>  	}
>  
>  	/* device reports out of range channel id */
> -	if (hf->channel >= GS_MAX_INTF)
> +	if (hf->channel >= parent->channel_cnt)
>  		goto device_detach;
>  
>  	dev = parent->canch[hf->channel];
> @@ -699,7 +695,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
>  	/* USB failure take down all interfaces */
>  	if (rc == -ENODEV) {
>  device_detach:
> -		for (rc = 0; rc < GS_MAX_INTF; rc++) {
> +		for (rc = 0; rc < parent->channel_cnt; rc++) {
>  			if (parent->canch[rc])
>  				netif_device_detach(parent->canch[rc]->netdev);
>  		}
> @@ -1460,17 +1456,19 @@ static int gs_usb_probe(struct usb_interface *intf,
>  	icount = dconf.icount + 1;
>  	dev_info(&intf->dev, "Configuring for %u interfaces\n", icount);
>  
> -	if (icount > GS_MAX_INTF) {
> +	if (icount > type_max(typeof(parent->channel_cnt))) {
                              ^^^^^^
If you send a v4 to fix the typo, can you also remove this typeof()?

It used to be required, but this is not the case anymore since commit
bd1ebf2467f9 ("overflow: Allow non-type arg to type_max() and type_min()").

(my Reviewed-by tag is still valid).

>  		dev_err(&intf->dev,
>  			"Driver cannot handle more that %u CAN interfaces\n",
> -			GS_MAX_INTF);
> +			type_max(typeof(parent->channel_cnt)));
                                 ^^^^^^
same

>  		return -EINVAL;
>  	}
>  
> -	parent = kzalloc(sizeof(*parent), GFP_KERNEL);
> +	parent = kzalloc(struct_size(parent, canch, icount), GFP_KERNEL);
>  	if (!parent)
>  		return -ENOMEM;
>  
> +	parent->channel_cnt = icount;
> +
>  	init_usb_anchor(&parent->rx_submitted);
>  
>  	usb_set_intfdata(intf, parent);
> @@ -1531,7 +1529,7 @@ static void gs_usb_disconnect(struct usb_interface *intf)
>  		return;
>  	}
>  
> -	for (i = 0; i < GS_MAX_INTF; i++)
> +	for (i = 0; i < parent->channel_cnt; i++)
>  		if (parent->canch[i])
>  			gs_destroy_candev(parent->canch[i]);


-- 
Yours sincerely,
Vincent Mailhol
Re: [PATCH v3] net/can/gs_usb: increase max interface to U8_MAX
Posted by Vincent Mailhol 1 day, 17 hours ago
On 9/30/25 12:06 PM, Celeste Liu wrote:
> This issue was found by Runcheng Lu when develop HSCanT USB to CAN FD
> converter[1]. The original developers may have only 3 intefaces device to
                                                        ^^^^^^^^^
interfaces (missing "r")

> test so they write 3 here and wait for future change.
> 
> During the HSCanT development, we actually used 4 interfaces, so the
> limitation of 3 is not enough now. But just increase one is not
> future-proofed. Since the channel type in gs_host_frame is u8, just
> increase interface number limit to max size of u8 safely.
> 
> [1]: https://github.com/cherry-embedded/HSCanT-hardware
> 
> Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices")
> Reported-by: Runcheng Lu <runcheng.lu@hpmicro.com>
> Cc: stable@vger.kernel.org
> Signed-off-by: Celeste Liu <uwu@coelacanthus.name>

Reviewed-by: Vincent Mailhol <mailhol@kernel.org>

The patch is good as-is. However, speaking of the interface numbers, there is
another issue in this gs_usb driver: net_device->dev_port is not populated, and
according to the documentation, this is a bug.


See the description here:



  https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-net



  What:		/sys/class/net/<iface>/dev_port

  Date:		February 2014

  KernelVersion:	3.15

  Contact:	netdev@vger.kernel.org

  Description:

  		Indicates the port number of this network device, formatted

  		as a decimal value. Some NICs have multiple independent ports

  		on the same PCI bus, device and function. This attribute allows

  		userspace to distinguish the respective interfaces.



  		Note: some device drivers started to use 'dev_id' for this

  		purpose since long before 3.15 and have not adopted the new

  		attribute ever since. To query the port number, some tools look

  		exclusively at 'dev_port', while others only consult 'dev_id'.

  		If a network device has multiple client adapter ports as

  		described in the previous paragraph and does not set this

  		attribute to its port number, it's a kernel bug.



Would you mind sending a separate patch (with a Fixes: tag) to resolve this?


Yours sincerely,
Vincent Mailhol
Re: [PATCH v3] net/can/gs_usb: increase max interface to U8_MAX
Posted by Celeste Liu 1 day, 17 hours ago
On 2025-09-30 13:44, Vincent Mailhol wrote:
> On 9/30/25 12:06 PM, Celeste Liu wrote:
>> This issue was found by Runcheng Lu when develop HSCanT USB to CAN FD
>> converter[1]. The original developers may have only 3 intefaces device to
>                                                         ^^^^^^^^^
> interfaces (missing "r")

Fixed in v4. Redundant typeof() was removed as well.

> 
>> test so they write 3 here and wait for future change.
>>
>> During the HSCanT development, we actually used 4 interfaces, so the
>> limitation of 3 is not enough now. But just increase one is not
>> future-proofed. Since the channel type in gs_host_frame is u8, just
>> increase interface number limit to max size of u8 safely.
>>
>> [1]: https://github.com/cherry-embedded/HSCanT-hardware
>>
>> Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices")
>> Reported-by: Runcheng Lu <runcheng.lu@hpmicro.com>
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Celeste Liu <uwu@coelacanthus.name>
> 
> Reviewed-by: Vincent Mailhol <mailhol@kernel.org>
> 
> The patch is good as-is. However, speaking of the interface numbers, there is
> another issue in this gs_usb driver: net_device->dev_port is not populated, and
> according to the documentation, this is a bug.
> 
> 
> See the description here:
> 
> 
> 
>   https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-net
> 
> 
> 
>   What:		/sys/class/net/<iface>/dev_port
> 
>   Date:		February 2014
> 
>   KernelVersion:	3.15
> 
>   Contact:	netdev@vger.kernel.org
> 
>   Description:
> 
>   		Indicates the port number of this network device, formatted
> 
>   		as a decimal value. Some NICs have multiple independent ports
> 
>   		on the same PCI bus, device and function. This attribute allows
> 
>   		userspace to distinguish the respective interfaces.
> 
> 
> 
>   		Note: some device drivers started to use 'dev_id' for this
> 
>   		purpose since long before 3.15 and have not adopted the new
> 
>   		attribute ever since. To query the port number, some tools look
> 
>   		exclusively at 'dev_port', while others only consult 'dev_id'.
> 
>   		If a network device has multiple client adapter ports as
> 
>   		described in the previous paragraph and does not set this
> 
>   		attribute to its port number, it's a kernel bug.
> 
> 
> 
> Would you mind sending a separate patch (with a Fixes: tag) to resolve this?

Ok. I will send a patch for it later.

> 
> 
> Yours sincerely,
> Vincent Mailhol
>