[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <b78d0e25-f8cc-43af-90d8-2c7344895d55@suse.com>
Date: Thu, 6 Feb 2025 12:12:31 +0100
From: Oliver Neukum <oneukum@...e.com>
To: Jeremy Kerr <jk@...econstruct.com.au>,
Matt Johnston <matt@...econstruct.com.au>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Andrew Lunn <andrew+netdev@...n.ch>, "David S. Miller"
<davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>
Cc: netdev@...r.kernel.org, linux-usb@...r.kernel.org,
Santosh Puranik <spuranik@...dia.com>
Subject: Re: [PATCH net-next 2/2] net: mctp: Add MCTP USB transport driver
On 06.02.25 07:48, Jeremy Kerr wrote:
Hi,
remarks inline.
Regards
Oliver
> +static void mctp_usb_in_complete(struct urb *urb)
> +{
> + struct sk_buff *skb = urb->context;
> + struct net_device *netdev = skb->dev;
> + struct pcpu_dstats *dstats = this_cpu_ptr(netdev->dstats);
> + struct mctp_usb *mctp_usb = netdev_priv(netdev);
> + struct mctp_skb_cb *cb;
> + unsigned int len;
> + int status;
> +
> + status = urb->status;
> +
> + switch (status) {
> + case -ENOENT:
> + case -ECONNRESET:
> + case -ESHUTDOWN:
> + case -EPROTO:
> + kfree_skb(skb);
> + return;
> + case 0:
> + break;
> + default:
> + dev_err(&mctp_usb->usbdev->dev, "%s: urb status: %d\n",
> + __func__, status);
> + kfree_skb(skb);
> + return;
> + }
> +
> + len = urb->actual_length;
> + __skb_put(skb, len);
> +
> + while (skb) {
> + struct sk_buff *skb2 = NULL;
> + struct mctp_usb_hdr *hdr;
> + u8 pkt_len; /* length of MCTP packet, no USB header */
> +
> + hdr = skb_pull_data(skb, sizeof(*hdr));
> + if (!hdr)
> + break;
> +
> + if (be16_to_cpu(hdr->id) != MCTP_USB_DMTF_ID) {
It would be more efficient to do the conversion on the constant
> + dev_dbg(&mctp_usb->usbdev->dev, "%s: invalid id %04x\n",
> + __func__, be16_to_cpu(hdr->id));
> + break;
> + }
> +
> + if (hdr->len <
> + sizeof(struct mctp_hdr) + sizeof(struct mctp_usb_hdr)) {
> + dev_dbg(&mctp_usb->usbdev->dev,
> + "%s: short packet (hdr) %d\n",
> + __func__, hdr->len);
> + break;
> + }
> +
> + /* we know we have at least sizeof(struct mctp_usb_hdr) here */
> + pkt_len = hdr->len - sizeof(struct mctp_usb_hdr);
> + if (pkt_len > skb->len) {
> + dev_dbg(&mctp_usb->usbdev->dev,
> + "%s: short packet (xfer) %d, actual %d\n",
> + __func__, hdr->len, skb->len);
> + break;
> + }
> +
> + if (pkt_len < skb->len) {
> + /* more packets may follow - clone to a new
> + * skb to use on the next iteration
> + */
> + skb2 = skb_clone(skb, GFP_ATOMIC);
> + if (skb2) {
> + if (!skb_pull(skb2, pkt_len)) {
> + kfree_skb(skb2);
> + skb2 = NULL;
> + }
> + }
> + skb_trim(skb, pkt_len);
This is functional. Though in terms of algorithm you are copying
the same data multiple times.
> + }
> +
> + skb->protocol = htons(ETH_P_MCTP);
> + skb_reset_network_header(skb);
> + cb = __mctp_cb(skb);
> + cb->halen = 0;
> + netif_rx(skb);
> +
> + u64_stats_update_begin(&dstats->syncp);
> + u64_stats_inc(&dstats->rx_packets);
> + u64_stats_add(&dstats->rx_bytes, skb->len);
> + u64_stats_update_end(&dstats->syncp);
> +
> + skb = skb2;
> + }
> +
> + if (skb)
> + kfree_skb(skb);
> +
> + mctp_usb_rx_queue(mctp_usb);
> +}
> +
> +static int mctp_usb_open(struct net_device *dev)
> +{
> + struct mctp_usb *mctp_usb = netdev_priv(dev);
> +
> + return mctp_usb_rx_queue(mctp_usb);
This will needlessly use GFP_ATOMIC
> +}
[..]
> +static int mctp_usb_probe(struct usb_interface *intf,
> + const struct usb_device_id *id)
> +{
> + struct usb_endpoint_descriptor *ep_in, *ep_out;
> + struct usb_host_interface *iface_desc;
> + struct net_device *netdev;
> + struct mctp_usb *dev;
> + int rc;
> +
> + /* only one alternate */
> + iface_desc = intf->cur_altsetting;
> +
> + rc = usb_find_common_endpoints(iface_desc, &ep_in, &ep_out, NULL, NULL);
> + if (rc) {
> + dev_err(&intf->dev, "invalid endpoints on device?\n");
> + return rc;
> + }
> +
> + netdev = alloc_netdev(sizeof(*dev), "mctpusb%d", NET_NAME_ENUM,
> + mctp_usb_netdev_setup);
> + if (!netdev)
> + return -ENOMEM;
> +
> + SET_NETDEV_DEV(netdev, &intf->dev);
> + dev = netdev_priv(netdev);
> + dev->netdev = netdev;
> + dev->usbdev = usb_get_dev(interface_to_usbdev(intf));
Taking a reference.
Where is the corresponding put?
> + dev->intf = intf;
> + usb_set_intfdata(intf, dev);
> +
> + dev->ep_in = ep_in->bEndpointAddress;
> + dev->ep_out = ep_out->bEndpointAddress;
> +
> + dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
> + dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
> + if (!dev->tx_urb || !dev->rx_urb) {
> + rc = -ENOMEM;
> + goto err_free_urbs;
> + }
> +
> + rc = register_netdev(netdev);
> + if (rc)
> + goto err_free_urbs;
> +
> + return 0;
> +
> +err_free_urbs:
> + usb_free_urb(dev->tx_urb);
> + usb_free_urb(dev->rx_urb);
> + free_netdev(netdev);
> + return rc;
> +}
Powered by blists - more mailing lists