From: Mika Westerberg <mika.westerb...@linux.intel.com> Date: Mon, 25 Sep 2017 14:07:38 +0300
> +struct thunderbolt_ip_header { > + u32 route_hi; > + u32 route_lo; > + u32 length_sn; > + uuid_t uuid; > + uuid_t initiator_uuid; > + uuid_t target_uuid; > + u32 type; > + u32 command_id; > +} __packed; Again, the __packed attribute should not be necessary and needs to be removed. > +static void tbnet_pull_tail(struct sk_buff *skb) > +{ > + skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; > + unsigned int pull_len; > + void *hdr; > + > + hdr = skb_frag_address(frag); > + pull_len = eth_get_headlen(hdr, TBNET_RX_HDR_SIZE); > + > + /* Align pull length to size of long to optimize memcpy performance */ > + skb_copy_to_linear_data(skb, hdr, ALIGN(pull_len, sizeof(long))); You do not need to copy here, instead you can build SKB's where the skb->data points directly at the head of your first frag page memory. See build_skb(). > + skb = net->skb; > + if (!skb) { > + skb = netdev_alloc_skb_ip_align(net->dev, > + TBNET_RX_HDR_SIZE); > + net->skb = skb; > + } > + if (!skb) > + break; > + > + /* Single small buffer we can copy directly to the > + * header part of the skb. > + */ > + if (hdr->frame_count == 1 && frame_size <= TBNET_RX_HDR_SIZE) { Here you would use build_skb() instead of netdev_alloc_skb*() for the first frag, and keep the existing code tacking on subsequent frags using skb_add_Rx_frag(). > + ret = register_netdev(dev); > + if (ret) { > + free_netdev(dev); > + return ret; > + } > + > + net->handler.uuid = &tbnet_svc_uuid; > + net->handler.callback = tbnet_handle_packet, > + net->handler.data = net; > + tb_register_protocol_handler(&net->handler); > + > + tb_service_set_drvdata(svc, net); There could be races here. At the exact moment you call register_netdev(), your device can be brought UP, packets transmitted, etc. You entire set of driver code paths can be executed. The rest of those initializations after register_netdev() probably are needed by the rest of the driver to function properly, so may need to happen before register_netdev() publishes the device to the entire world.