* [PATCH 0/1] can: esd_usb: Fix device probe routine @ 2025-02-03 14:58 Stefan Mätje 2025-02-03 14:58 ` [PATCH 1/1] can: esd_usb: Fix not detecting version reply in " Stefan Mätje 0 siblings, 1 reply; 6+ messages in thread From: Stefan Mätje @ 2025-02-03 14:58 UTC (permalink / raw) To: Marc Kleine-Budde, Vincent Mailhol, Frank Jungclaus, linux-can Cc: Simon Horman, netdev The included patch fixes a possible failure to detect the CAN-USB/* device after a reboot. The patch has been published as RFC already but I didn't get any comments. See https://lore.kernel.org/linux-can/20241204160640.884578-1-stefan.maetje@esd.eu/ The patch carries a Fixes: tag for the commit where the support for the CAN-USB/3-FD hit the 6.6 mainline kernel even if the erroneous code was present in previous releases. This is done this way because with the new hardware the problem became more visible. Stefan Mätje (1): can: esd_usb: Fix not detecting version reply in probe routine drivers/net/can/usb/esd_usb.c | 122 +++++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 30 deletions(-) base-commit: c1a6911485b022e093c589c295a953ff744112b9 -- 2.34.1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/1] can: esd_usb: Fix not detecting version reply in probe routine 2025-02-03 14:58 [PATCH 0/1] can: esd_usb: Fix device probe routine Stefan Mätje @ 2025-02-03 14:58 ` Stefan Mätje 2025-02-06 12:45 ` Marc Kleine-Budde 0 siblings, 1 reply; 6+ messages in thread From: Stefan Mätje @ 2025-02-03 14:58 UTC (permalink / raw) To: Marc Kleine-Budde, Vincent Mailhol, Frank Jungclaus, linux-can Cc: Simon Horman, netdev This patch fixes some problems in the esd_usb_probe routine that render the CAN interface unusable. The probe routine sends a version request message to the USB device to receive a version reply with the number of CAN ports and the hard- & firmware versions. Then for each CAN port a CAN netdev is registered. The previous code assumed that the version reply would be received immediately. But if the driver was reloaded without power cycling the USB device (i. e. on a reboot) there could already be other incoming messages in the USB buffers. These would be in front of the version reply and need to be skipped. In the previous code these problems were present: - Only one usb_bulk_msg() read was done into a buffer of sizeof(union esd_usb_msg) which is smaller than ESD_USB_RX_BUFFER_SIZE which could lead to an overflow error from the USB stack. - The first bytes of the received data were taken without checking for the message type. This could lead to zero detected CAN interfaces. - On kmalloc() fail for the "union esd_usb_msg msg" (i. e. msg == NULL) kfree() would be called with this NULL pointer. To mitigate these problems: - Use a transfer buffer "buf" with ESD_USB_RX_BUFFER_SIZE. - Fix the error exit path taken after allocation failure for the transfer buffer. - Added a function esd_usb_recv_version() that reads and skips incoming "esd_usb_msg" messages until a version reply message is found. This is evaluated to return the count of CAN ports and version information. Fixes: 80662d943075 ("can: esd_usb: Add support for esd CAN-USB/3") Signed-off-by: Stefan Mätje <stefan.maetje@esd.eu> --- drivers/net/can/usb/esd_usb.c | 122 +++++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 30 deletions(-) diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c index 03ad10b01867..a6b3b100f8ac 100644 --- a/drivers/net/can/usb/esd_usb.c +++ b/drivers/net/can/usb/esd_usb.c @@ -625,17 +625,86 @@ static int esd_usb_send_msg(struct esd_usb *dev, union esd_usb_msg *msg) 1000); } -static int esd_usb_wait_msg(struct esd_usb *dev, - union esd_usb_msg *msg) +static int esd_usb_req_version(struct esd_usb *dev, void *buf) +{ + union esd_usb_msg *msg = buf; + + msg->hdr.cmd = ESD_USB_CMD_VERSION; + msg->hdr.len = sizeof(struct esd_usb_version_msg) / sizeof(u32); /* # of 32bit words */ + msg->version.rsvd = 0; + msg->version.flags = 0; + msg->version.drv_version = 0; + + return esd_usb_send_msg(dev, msg); +} + +static int esd_usb_recv_version(struct esd_usb *dev, + void *rx_buf, + u32 *version, + int *net_count) { int actual_length; + int cnt_other = 0; + int cnt_ts = 0; + int cnt_vs = 0; + int attempt; + int pos; + int err; - return usb_bulk_msg(dev->udev, - usb_rcvbulkpipe(dev->udev, 1), - msg, - sizeof(*msg), - &actual_length, - 1000); + for (attempt = 0; attempt < 8 && cnt_vs == 0; ++attempt) { + err = usb_bulk_msg(dev->udev, + usb_rcvbulkpipe(dev->udev, 1), + rx_buf, + ESD_USB_RX_BUFFER_SIZE, + &actual_length, + 1000); + if (err) + break; + + err = -ENOENT; + pos = 0; + while (pos < actual_length) { + union esd_usb_msg *p_msg; + + p_msg = (union esd_usb_msg *)(rx_buf + pos); + + switch (p_msg->hdr.cmd) { + case ESD_USB_CMD_VERSION: + ++cnt_vs; + *net_count = (int)p_msg->version_reply.nets; + *version = le32_to_cpu(p_msg->version_reply.version); + err = 0; + dev_dbg(&dev->udev->dev, "TS 0x%08x, V 0x%08x, N %u, F 0x%02x, %.16s\n", + le32_to_cpu(p_msg->version_reply.ts), + le32_to_cpu(p_msg->version_reply.version), + p_msg->version_reply.nets, + p_msg->version_reply.features, + (char *)p_msg->version_reply.name + ); + break; + case ESD_USB_CMD_TS: + ++cnt_ts; + dev_dbg(&dev->udev->dev, "TS 0x%08x\n", + le32_to_cpu(p_msg->rx.ts)); + break; + default: + ++cnt_other; + dev_dbg(&dev->udev->dev, "HDR %d\n", p_msg->hdr.cmd); + break; + } + pos += p_msg->hdr.len * sizeof(u32); /* convert to # of bytes */ + + if (pos > actual_length) { + dev_err(&dev->udev->dev, "format error\n"); + err = -EPROTO; + goto bail; + } + } + } +bail: + dev_dbg(&dev->udev->dev, "%s()->%d; ATT=%d, TS=%d, VS=%d, O=%d\n", + __func__, err, attempt, cnt_ts, cnt_vs, cnt_other); + return err; } static int esd_usb_setup_rx_urbs(struct esd_usb *dev) @@ -1258,7 +1327,7 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) } dev->nets[index] = priv; - netdev_info(netdev, "device %s registered\n", netdev->name); + netdev_info(netdev, "registered\n"); done: return err; @@ -1273,13 +1342,13 @@ static int esd_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct esd_usb *dev; - union esd_usb_msg *msg; + void *buf; int i, err; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { err = -ENOMEM; - goto done; + goto bail; } dev->udev = interface_to_usbdev(intf); @@ -1288,34 +1357,25 @@ static int esd_usb_probe(struct usb_interface *intf, usb_set_intfdata(intf, dev); - msg = kmalloc(sizeof(*msg), GFP_KERNEL); - if (!msg) { + buf = kmalloc(ESD_USB_RX_BUFFER_SIZE, GFP_KERNEL); + if (!buf) { err = -ENOMEM; - goto free_msg; + goto free_dev; } /* query number of CAN interfaces (nets) */ - msg->hdr.cmd = ESD_USB_CMD_VERSION; - msg->hdr.len = sizeof(struct esd_usb_version_msg) / sizeof(u32); /* # of 32bit words */ - msg->version.rsvd = 0; - msg->version.flags = 0; - msg->version.drv_version = 0; - - err = esd_usb_send_msg(dev, msg); + err = esd_usb_req_version(dev, buf); if (err < 0) { dev_err(&intf->dev, "sending version message failed\n"); - goto free_msg; + goto free_buf; } - err = esd_usb_wait_msg(dev, msg); + err = esd_usb_recv_version(dev, buf, &dev->version, &dev->net_count); if (err < 0) { dev_err(&intf->dev, "no version message answer\n"); - goto free_msg; + goto free_buf; } - dev->net_count = (int)msg->version_reply.nets; - dev->version = le32_to_cpu(msg->version_reply.version); - if (device_create_file(&intf->dev, &dev_attr_firmware)) dev_err(&intf->dev, "Couldn't create device file for firmware\n"); @@ -1332,11 +1392,12 @@ static int esd_usb_probe(struct usb_interface *intf, for (i = 0; i < dev->net_count; i++) esd_usb_probe_one_net(intf, i); -free_msg: - kfree(msg); +free_buf: + kfree(buf); +free_dev: if (err) kfree(dev); -done: +bail: return err; } @@ -1357,6 +1418,7 @@ static void esd_usb_disconnect(struct usb_interface *intf) for (i = 0; i < dev->net_count; i++) { if (dev->nets[i]) { netdev = dev->nets[i]->netdev; + netdev_info(netdev, "unregister\n"); unregister_netdev(netdev); free_candev(netdev); } -- 2.34.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/1] can: esd_usb: Fix not detecting version reply in probe routine 2025-02-03 14:58 ` [PATCH 1/1] can: esd_usb: Fix not detecting version reply in " Stefan Mätje @ 2025-02-06 12:45 ` Marc Kleine-Budde 2025-02-09 18:53 ` Stefan Mätje 0 siblings, 1 reply; 6+ messages in thread From: Marc Kleine-Budde @ 2025-02-06 12:45 UTC (permalink / raw) To: Stefan Mätje Cc: Vincent Mailhol, Frank Jungclaus, linux-can, Simon Horman, netdev [-- Attachment #1: Type: text/plain, Size: 8603 bytes --] On 03.02.2025 15:58:10, Stefan Mätje wrote: > This patch fixes some problems in the esd_usb_probe routine that render > the CAN interface unusable. > > The probe routine sends a version request message to the USB device to > receive a version reply with the number of CAN ports and the hard- > & firmware versions. Then for each CAN port a CAN netdev is registered. > > The previous code assumed that the version reply would be received > immediately. But if the driver was reloaded without power cycling the > USB device (i. e. on a reboot) there could already be other incoming > messages in the USB buffers. These would be in front of the version > reply and need to be skipped. > > In the previous code these problems were present: > - Only one usb_bulk_msg() read was done into a buffer of > sizeof(union esd_usb_msg) which is smaller than ESD_USB_RX_BUFFER_SIZE > which could lead to an overflow error from the USB stack. > - The first bytes of the received data were taken without checking for > the message type. This could lead to zero detected CAN interfaces. > - On kmalloc() fail for the "union esd_usb_msg msg" (i. e. msg == NULL) > kfree() would be called with this NULL pointer. > > To mitigate these problems: > - Use a transfer buffer "buf" with ESD_USB_RX_BUFFER_SIZE. > - Fix the error exit path taken after allocation failure for the > transfer buffer. > - Added a function esd_usb_recv_version() that reads and skips incoming > "esd_usb_msg" messages until a version reply message is found. This > is evaluated to return the count of CAN ports and version information. > > Fixes: 80662d943075 ("can: esd_usb: Add support for esd CAN-USB/3") > Signed-off-by: Stefan Mätje <stefan.maetje@esd.eu> > --- > drivers/net/can/usb/esd_usb.c | 122 +++++++++++++++++++++++++--------- > 1 file changed, 92 insertions(+), 30 deletions(-) > > diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c > index 03ad10b01867..a6b3b100f8ac 100644 > --- a/drivers/net/can/usb/esd_usb.c > +++ b/drivers/net/can/usb/esd_usb.c > @@ -625,17 +625,86 @@ static int esd_usb_send_msg(struct esd_usb *dev, union esd_usb_msg *msg) > 1000); > } > > -static int esd_usb_wait_msg(struct esd_usb *dev, > - union esd_usb_msg *msg) > +static int esd_usb_req_version(struct esd_usb *dev, void *buf) > +{ > + union esd_usb_msg *msg = buf; > + > + msg->hdr.cmd = ESD_USB_CMD_VERSION; > + msg->hdr.len = sizeof(struct esd_usb_version_msg) / sizeof(u32); /* # of 32bit words */ > + msg->version.rsvd = 0; > + msg->version.flags = 0; > + msg->version.drv_version = 0; > + > + return esd_usb_send_msg(dev, msg); > +} > + > +static int esd_usb_recv_version(struct esd_usb *dev, > + void *rx_buf, > + u32 *version, > + int *net_count) static int esd_usb_recv_version(struct esd_usb *dev, void *rx_buf, u32 *version, int *net_count) > { > int actual_length; > + int cnt_other = 0; > + int cnt_ts = 0; > + int cnt_vs = 0; > + int attempt; > + int pos; > + int err; Try to reduce the scope of the variables and move them into the for-loop. > > - return usb_bulk_msg(dev->udev, > - usb_rcvbulkpipe(dev->udev, 1), > - msg, > - sizeof(*msg), > - &actual_length, > - 1000); > + for (attempt = 0; attempt < 8 && cnt_vs == 0; ++attempt) { Can you create a #define for the "8" to avoid a magic number here? > + err = usb_bulk_msg(dev->udev, > + usb_rcvbulkpipe(dev->udev, 1), > + rx_buf, > + ESD_USB_RX_BUFFER_SIZE, > + &actual_length, > + 1000); > + if (err) > + break; nitpick: I would make it explicit with "goto bail", should be the same? > + > + err = -ENOENT; > + pos = 0; > + while (pos < actual_length) { > + union esd_usb_msg *p_msg; > + > + p_msg = (union esd_usb_msg *)(rx_buf + pos); > + > + switch (p_msg->hdr.cmd) { > + case ESD_USB_CMD_VERSION: > + ++cnt_vs; > + *net_count = (int)p_msg->version_reply.nets; Cast not needed. What happens if nets is > 2? Please sanitize input from outside against ESD_USB_MAX_NETS. > + *version = le32_to_cpu(p_msg->version_reply.version); > + err = 0; > + dev_dbg(&dev->udev->dev, "TS 0x%08x, V 0x%08x, N %u, F 0x%02x, %.16s\n", > + le32_to_cpu(p_msg->version_reply.ts), > + le32_to_cpu(p_msg->version_reply.version), > + p_msg->version_reply.nets, > + p_msg->version_reply.features, > + (char *)p_msg->version_reply.name Is this cast needed? What about using '"%.*s", sizeof(p_msg->version_reply.name)'? > + ); Please move the closing ")" into the previous line. > + break; Why keep parsing after you've found the version? > + case ESD_USB_CMD_TS: > + ++cnt_ts; > + dev_dbg(&dev->udev->dev, "TS 0x%08x\n", > + le32_to_cpu(p_msg->rx.ts)); > + break; > + default: > + ++cnt_other; > + dev_dbg(&dev->udev->dev, "HDR %d\n", p_msg->hdr.cmd); > + break; > + } > + pos += p_msg->hdr.len * sizeof(u32); /* convert to # of bytes */ > + > + if (pos > actual_length) { > + dev_err(&dev->udev->dev, "format error\n"); > + err = -EPROTO; > + goto bail; > + } > + } > + } > +bail: > + dev_dbg(&dev->udev->dev, "%s()->%d; ATT=%d, TS=%d, VS=%d, O=%d\n", > + __func__, err, attempt, cnt_ts, cnt_vs, cnt_other); > + return err; > } > > static int esd_usb_setup_rx_urbs(struct esd_usb *dev) > @@ -1258,7 +1327,7 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) > } > > dev->nets[index] = priv; > - netdev_info(netdev, "device %s registered\n", netdev->name); > + netdev_info(netdev, "registered\n"); > > done: > return err; > @@ -1273,13 +1342,13 @@ static int esd_usb_probe(struct usb_interface *intf, > const struct usb_device_id *id) > { > struct esd_usb *dev; > - union esd_usb_msg *msg; > + void *buf; > int i, err; > > dev = kzalloc(sizeof(*dev), GFP_KERNEL); > if (!dev) { > err = -ENOMEM; > - goto done; > + goto bail; > } > > dev->udev = interface_to_usbdev(intf); > @@ -1288,34 +1357,25 @@ static int esd_usb_probe(struct usb_interface *intf, > > usb_set_intfdata(intf, dev); > > - msg = kmalloc(sizeof(*msg), GFP_KERNEL); > - if (!msg) { > + buf = kmalloc(ESD_USB_RX_BUFFER_SIZE, GFP_KERNEL); > + if (!buf) { > err = -ENOMEM; > - goto free_msg; > + goto free_dev; > } > > /* query number of CAN interfaces (nets) */ > - msg->hdr.cmd = ESD_USB_CMD_VERSION; > - msg->hdr.len = sizeof(struct esd_usb_version_msg) / sizeof(u32); /* # of 32bit words */ > - msg->version.rsvd = 0; > - msg->version.flags = 0; > - msg->version.drv_version = 0; > - > - err = esd_usb_send_msg(dev, msg); > + err = esd_usb_req_version(dev, buf); > if (err < 0) { > dev_err(&intf->dev, "sending version message failed\n"); > - goto free_msg; > + goto free_buf; > } > > - err = esd_usb_wait_msg(dev, msg); > + err = esd_usb_recv_version(dev, buf, &dev->version, &dev->net_count); Why pass the "&dev->version, &dev->net_count" pointers, if you already pass dev? > if (err < 0) { > dev_err(&intf->dev, "no version message answer\n"); > - goto free_msg; > + goto free_buf; > } > > - dev->net_count = (int)msg->version_reply.nets; > - dev->version = le32_to_cpu(msg->version_reply.version); > - > if (device_create_file(&intf->dev, &dev_attr_firmware)) > dev_err(&intf->dev, > "Couldn't create device file for firmware\n"); > @@ -1332,11 +1392,12 @@ static int esd_usb_probe(struct usb_interface *intf, > for (i = 0; i < dev->net_count; i++) > esd_usb_probe_one_net(intf, i); Return values are not checked here. :/ > > -free_msg: > - kfree(msg); > +free_buf: > + kfree(buf); > +free_dev: > if (err) > kfree(dev); > -done: > +bail: > return err; > } > > @@ -1357,6 +1418,7 @@ static void esd_usb_disconnect(struct usb_interface *intf) > for (i = 0; i < dev->net_count; i++) { > if (dev->nets[i]) { > netdev = dev->nets[i]->netdev; > + netdev_info(netdev, "unregister\n"); > unregister_netdev(netdev); > free_candev(netdev); > } > -- > 2.34.1 > > > regards, Marc -- Pengutronix e.K. | Marc Kleine-Budde | Embedded Linux | https://www.pengutronix.de | Vertretung Nürnberg | Phone: +49-5121-206917-129 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 | [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/1] can: esd_usb: Fix not detecting version reply in probe routine 2025-02-06 12:45 ` Marc Kleine-Budde @ 2025-02-09 18:53 ` Stefan Mätje 2025-02-09 19:40 ` Marc Kleine-Budde 2025-02-09 19:45 ` Marc Kleine-Budde 0 siblings, 2 replies; 6+ messages in thread From: Stefan Mätje @ 2025-02-09 18:53 UTC (permalink / raw) To: mkl@pengutronix.de Cc: horms@kernel.org, linux-can@vger.kernel.org, Frank Jungclaus, netdev@vger.kernel.org, mailhol.vincent@wanadoo.fr Am Donnerstag, dem 06.02.2025 um 13:45 +0100 schrieb Marc Kleine-Budde: > > On 03.02.2025 15:58:10, Stefan Mätje wrote: > > > > This patch fixes some problems in the esd_usb_probe routine that render > > > > the CAN interface unusable. > > > > > > > > The probe routine sends a version request message to the USB device to > > > > receive a version reply with the number of CAN ports and the hard- > > > > & firmware versions. Then for each CAN port a CAN netdev is registered. > > > > > > > > The previous code assumed that the version reply would be received > > > > immediately. But if the driver was reloaded without power cycling the > > > > USB device (i. e. on a reboot) there could already be other incoming > > > > messages in the USB buffers. These would be in front of the version > > > > reply and need to be skipped. > > > > > > > > In the previous code these problems were present: > > > > - Only one usb_bulk_msg() read was done into a buffer of > > > > sizeof(union esd_usb_msg) which is smaller than ESD_USB_RX_BUFFER_SIZE > > > > which could lead to an overflow error from the USB stack. > > > > - The first bytes of the received data were taken without checking for > > > > the message type. This could lead to zero detected CAN interfaces. > > > > - On kmalloc() fail for the "union esd_usb_msg msg" (i. e. msg == NULL) > > > > kfree() would be called with this NULL pointer. > > > > > > > > To mitigate these problems: > > > > - Use a transfer buffer "buf" with ESD_USB_RX_BUFFER_SIZE. > > > > - Fix the error exit path taken after allocation failure for the > > > > transfer buffer. > > > > - Added a function esd_usb_recv_version() that reads and skips incoming > > > > "esd_usb_msg" messages until a version reply message is found. This > > > > is evaluated to return the count of CAN ports and version information. > > > > > > > > Fixes: 80662d943075 ("can: esd_usb: Add support for esd CAN-USB/3") > > > > Signed-off-by: Stefan Mätje <stefan.maetje@esd.eu> > > > > --- > > > > drivers/net/can/usb/esd_usb.c | 122 +++++++++++++++++++++++++--------- > > > > 1 file changed, 92 insertions(+), 30 deletions(-) > > > > > > > > diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c > > > > index 03ad10b01867..a6b3b100f8ac 100644 > > > > --- a/drivers/net/can/usb/esd_usb.c > > > > +++ b/drivers/net/can/usb/esd_usb.c > > > > @@ -625,17 +625,86 @@ static int esd_usb_send_msg(struct esd_usb *dev, union esd_usb_msg *msg) > > > > 1000); > > > > } > > > > > > > > -static int esd_usb_wait_msg(struct esd_usb *dev, > > > > - union esd_usb_msg *msg) > > > > +static int esd_usb_req_version(struct esd_usb *dev, void *buf) > > > > +{ > > > > + union esd_usb_msg *msg = buf; > > > > + > > > > + msg->hdr.cmd = ESD_USB_CMD_VERSION; > > > > + msg->hdr.len = sizeof(struct esd_usb_version_msg) / sizeof(u32); /* # of 32bit words */ > > > > + msg->version.rsvd = 0; > > > > + msg->version.flags = 0; > > > > + msg->version.drv_version = 0; > > > > + > > > > + return esd_usb_send_msg(dev, msg); > > > > +} > > > > + > > > > +static int esd_usb_recv_version(struct esd_usb *dev, > > > > + void *rx_buf, > > > > + u32 *version, > > > > + int *net_count) > > > > static int esd_usb_recv_version(struct esd_usb *dev, void *rx_buf, > > u32 *version, int *net_count) > > > > > > { > > > > int actual_length; > > > > + int cnt_other = 0; > > > > + int cnt_ts = 0; > > > > + int cnt_vs = 0; > > > > + int attempt; > > > > + int pos; > > > > + int err; > > > > Try to reduce the scope of the variables and move them into the for-loop. Changed this in V2. > > > > > > > > - return usb_bulk_msg(dev->udev, > > > > - usb_rcvbulkpipe(dev->udev, 1), > > > > - msg, > > > > - sizeof(*msg), > > > > - &actual_length, > > > > - 1000); > > > > + for (attempt = 0; attempt < 8 && cnt_vs == 0; ++attempt) { > > > > Can you create a #define for the "8" to avoid a magic number here? This value was found empirically. But I think I have to reconsider the style of handling here and may need to adapt the solution. > > > > + err = usb_bulk_msg(dev->udev, > > > > + usb_rcvbulkpipe(dev->udev, 1), > > > > + rx_buf, > > > > + ESD_USB_RX_BUFFER_SIZE, > > > > + &actual_length, > > > > + 1000); > > > > + if (err) > > > > + break; > > > > nitpick: I would make it explicit with "goto bail", should be the same? Changed this in V2. > > > > + > > > > + err = -ENOENT; > > > > + pos = 0; > > > > + while (pos < actual_length) { > > > > + union esd_usb_msg *p_msg; > > > > + > > > > + p_msg = (union esd_usb_msg *)(rx_buf + pos); > > > > + > > > > + switch (p_msg->hdr.cmd) { > > > > + case ESD_USB_CMD_VERSION: > > > > + ++cnt_vs; > > > > + *net_count = (int)p_msg->version_reply.nets; > > > > Cast not needed. Changed this in V2. > > What happens if nets is > 2? Please sanitize input from outside against > > ESD_USB_MAX_NETS. Will limit the net_count using min() macro in V2. > > > > + *version = le32_to_cpu(p_msg->version_reply.version); > > > > + err = 0; > > > > + dev_dbg(&dev->udev->dev, "TS 0x%08x, V 0x%08x, N %u, F 0x%02x, %.16s\n", > > > > + le32_to_cpu(p_msg->version_reply.ts), > > > > + le32_to_cpu(p_msg->version_reply.version), > > > > + p_msg->version_reply.nets, > > > > + p_msg->version_reply.features, > > > > + (char *)p_msg->version_reply.name > > > > Is this cast needed? > > What about using '"%.*s", sizeof(p_msg->version_reply.name)'? Added a #define for the name attribute size that is also used in the structure declaration and here as field precision. > > > > + ); > > > > Please move the closing ")" into the previous line. Changed in V2. > > > > + break; > > > > Why keep parsing after you've found the version? The version message is assumed to be the last in the block of messages, so actual_length should be exhausted and the while (pos < actual_length) loop should stop anyway. If the unexpected happens that there is more data left after the version message the loop continues to check at least that the rest of the data forms valid message blocks and bails out if not. > > > > + case ESD_USB_CMD_TS: > > > > + ++cnt_ts; > > > > + dev_dbg(&dev->udev->dev, "TS 0x%08x\n", > > > > + le32_to_cpu(p_msg->rx.ts)); > > > > + break; > > > > + default: > > > > + ++cnt_other; > > > > + dev_dbg(&dev->udev->dev, "HDR %d\n", p_msg->hdr.cmd); > > > > + break; > > > > + } > > > > + pos += p_msg->hdr.len * sizeof(u32); /* convert to # of bytes */ > > > > + > > > > + if (pos > actual_length) { > > > > + dev_err(&dev->udev->dev, "format error\n"); > > > > + err = -EPROTO; > > > > + goto bail; > > > > + } > > > > + } > > > > + } > > > > +bail: > > > > + dev_dbg(&dev->udev->dev, "%s()->%d; ATT=%d, TS=%d, VS=%d, O=%d\n", > > > > + __func__, err, attempt, cnt_ts, cnt_vs, cnt_other); > > > > + return err; > > > > } > > > > > > > > static int esd_usb_setup_rx_urbs(struct esd_usb *dev) > > > > @@ -1258,7 +1327,7 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) > > > > } > > > > > > > > dev->nets[index] = priv; > > > > - netdev_info(netdev, "device %s registered\n", netdev->name); > > > > + netdev_info(netdev, "registered\n"); > > > > > > > > done: > > > > return err; > > > > @@ -1273,13 +1342,13 @@ static int esd_usb_probe(struct usb_interface *intf, > > > > const struct usb_device_id *id) > > > > { > > > > struct esd_usb *dev; > > > > - union esd_usb_msg *msg; > > > > + void *buf; > > > > int i, err; > > > > > > > > dev = kzalloc(sizeof(*dev), GFP_KERNEL); > > > > if (!dev) { > > > > err = -ENOMEM; > > > > - goto done; > > > > + goto bail; > > > > } > > > > > > > > dev->udev = interface_to_usbdev(intf); > > > > @@ -1288,34 +1357,25 @@ static int esd_usb_probe(struct usb_interface *intf, > > > > > > > > usb_set_intfdata(intf, dev); > > > > > > > > - msg = kmalloc(sizeof(*msg), GFP_KERNEL); > > > > - if (!msg) { > > > > + buf = kmalloc(ESD_USB_RX_BUFFER_SIZE, GFP_KERNEL); > > > > + if (!buf) { > > > > err = -ENOMEM; > > > > - goto free_msg; > > > > + goto free_dev; > > > > } > > > > > > > > /* query number of CAN interfaces (nets) */ > > > > - msg->hdr.cmd = ESD_USB_CMD_VERSION; > > > > - msg->hdr.len = sizeof(struct esd_usb_version_msg) / sizeof(u32); /* # of 32bit words */ > > > > - msg->version.rsvd = 0; > > > > - msg->version.flags = 0; > > > > - msg->version.drv_version = 0; > > > > - > > > > - err = esd_usb_send_msg(dev, msg); > > > > + err = esd_usb_req_version(dev, buf); > > > > if (err < 0) { > > > > dev_err(&intf->dev, "sending version message failed\n"); > > > > - goto free_msg; > > > > + goto free_buf; > > > > } > > > > > > > > - err = esd_usb_wait_msg(dev, msg); > > > > + err = esd_usb_recv_version(dev, buf, &dev->version, &dev->net_count); > > > > Why pass the "&dev->version, &dev->net_count" pointers, if you already > > pass dev? Good point. Changed in V2. > > > > if (err < 0) { > > > > dev_err(&intf->dev, "no version message answer\n"); > > > > - goto free_msg; > > > > + goto free_buf; > > > > } > > > > > > > > - dev->net_count = (int)msg->version_reply.nets; > > > > - dev->version = le32_to_cpu(msg->version_reply.version); > > > > - > > > > if (device_create_file(&intf->dev, &dev_attr_firmware)) > > > > dev_err(&intf->dev, > > > > "Couldn't create device file for firmware\n"); > > > > @@ -1332,11 +1392,12 @@ static int esd_usb_probe(struct usb_interface *intf, > > > > for (i = 0; i < dev->net_count; i++) > > > > esd_usb_probe_one_net(intf, i); > > > > Return values are not checked here. :/ Yes, that is another flaw. This needs to be tackled in another patch. > > > > > > > > -free_msg: > > > > - kfree(msg); > > > > +free_buf: > > > > + kfree(buf); > > > > +free_dev: > > > > if (err) > > > > kfree(dev); > > > > -done: > > > > +bail: > > > > return err; > > > > } > > > > > > > > @@ -1357,6 +1418,7 @@ static void esd_usb_disconnect(struct usb_interface *intf) > > > > for (i = 0; i < dev->net_count; i++) { > > > > if (dev->nets[i]) { > > > > netdev = dev->nets[i]->netdev; > > > > + netdev_info(netdev, "unregister\n"); > > > > unregister_netdev(netdev); > > > > free_candev(netdev); > > > > } > > > > -- > > > > 2.34.1 > > > > > > > > > > > > > > > > regards, > > Marc > > Thanks for looking at the patch. Best regards, Stefan ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/1] can: esd_usb: Fix not detecting version reply in probe routine 2025-02-09 18:53 ` Stefan Mätje @ 2025-02-09 19:40 ` Marc Kleine-Budde 2025-02-09 19:45 ` Marc Kleine-Budde 1 sibling, 0 replies; 6+ messages in thread From: Marc Kleine-Budde @ 2025-02-09 19:40 UTC (permalink / raw) To: Stefan Mätje Cc: horms@kernel.org, linux-can@vger.kernel.org, Frank Jungclaus, netdev@vger.kernel.org, mailhol.vincent@wanadoo.fr [-- Attachment #1: Type: text/plain, Size: 1150 bytes --] On 09.02.2025 18:53:43, Stefan Mätje wrote: > > > > > if (err < 0) { > > > > > dev_err(&intf->dev, "no version message answer\n"); > > > > > - goto free_msg; > > > > > + goto free_buf; > > > > > } > > > > > > > > > > - dev->net_count = (int)msg->version_reply.nets; > > > > > - dev->version = le32_to_cpu(msg->version_reply.version); > > > > > - > > > > > if (device_create_file(&intf->dev, &dev_attr_firmware)) > > > > > dev_err(&intf->dev, > > > > > "Couldn't create device file for firmware\n"); > > > > > @@ -1332,11 +1392,12 @@ static int esd_usb_probe(struct usb_interface *intf, > > > > > for (i = 0; i < dev->net_count; i++) > > > > > esd_usb_probe_one_net(intf, i); > > > > > > Return values are not checked here. :/ > > Yes, that is another flaw. This needs to be tackled in another patch. ACK regards, Marc -- Pengutronix e.K. | Marc Kleine-Budde | Embedded Linux | https://www.pengutronix.de | Vertretung Nürnberg | Phone: +49-5121-206917-129 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 | [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/1] can: esd_usb: Fix not detecting version reply in probe routine 2025-02-09 18:53 ` Stefan Mätje 2025-02-09 19:40 ` Marc Kleine-Budde @ 2025-02-09 19:45 ` Marc Kleine-Budde 1 sibling, 0 replies; 6+ messages in thread From: Marc Kleine-Budde @ 2025-02-09 19:45 UTC (permalink / raw) To: Stefan Mätje Cc: horms@kernel.org, linux-can@vger.kernel.org, Frank Jungclaus, netdev@vger.kernel.org, mailhol.vincent@wanadoo.fr [-- Attachment #1: Type: text/plain, Size: 1067 bytes --] On 09.02.2025 18:53:43, Stefan Mätje wrote: > > > > > - return usb_bulk_msg(dev->udev, > > > > > - usb_rcvbulkpipe(dev->udev, 1), > > > > > - msg, > > > > > - sizeof(*msg), > > > > > - &actual_length, > > > > > - 1000); > > > > > + for (attempt = 0; attempt < 8 && cnt_vs == 0; ++attempt) { > > > > > > Can you create a #define for the "8" to avoid a magic number here? > > This value was found empirically. But I think I have to reconsider > the style of handling here and may need to adapt the solution. You're the expert, change it as needed. I can only comment on the coding style and its best to avoid numbers in the code. Create a define and if you think it's worth, document that it's an empirically found value. Marc -- Pengutronix e.K. | Marc Kleine-Budde | Embedded Linux | https://www.pengutronix.de | Vertretung Nürnberg | Phone: +49-5121-206917-129 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 | [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-02-09 19:45 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-02-03 14:58 [PATCH 0/1] can: esd_usb: Fix device probe routine Stefan Mätje 2025-02-03 14:58 ` [PATCH 1/1] can: esd_usb: Fix not detecting version reply in " Stefan Mätje 2025-02-06 12:45 ` Marc Kleine-Budde 2025-02-09 18:53 ` Stefan Mätje 2025-02-09 19:40 ` Marc Kleine-Budde 2025-02-09 19:45 ` Marc Kleine-Budde
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox