Re: [PATCH net-next 2/2] net: mctp: Add MCTP USB transport driver
From: Oliver Neukum <oneukum@suse.com>
Date: 2025-02-06 11:12:34
Also in:
linux-usb
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;
+}