Loading drivers/net/usb/aqc111.c +102 −0 Original line number Diff line number Diff line Loading @@ -294,6 +294,9 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf) ether_addr_copy(dev->net->dev_addr, dev->net->perm_addr); /* Set Rx urb size */ dev->rx_urb_size = URB_SIZE; /* Set TX needed headroom & tailroom */ dev->net->needed_headroom += sizeof(u64); dev->net->needed_tailroom += sizeof(u64); Loading Loading @@ -519,6 +522,8 @@ static int aqc111_reset(struct usbnet *dev) struct aqc111_data *aqc111_data = dev->driver_priv; u8 reg8 = 0; dev->rx_urb_size = URB_SIZE; if (usb_device_no_sg_constraint(dev->udev)) dev->can_dma_sg = 1; Loading Loading @@ -578,6 +583,102 @@ static int aqc111_stop(struct usbnet *dev) return 0; } static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { struct sk_buff *new_skb = NULL; u32 pkt_total_offset = 0; u64 *pkt_desc_ptr = NULL; u32 start_of_descs = 0; u32 desc_offset = 0; /*RX Header Offset*/ u16 pkt_count = 0; u64 desc_hdr = 0; u32 skb_len = 0; if (!skb) goto err; if (skb->len == 0) goto err; skb_len = skb->len; /* RX Descriptor Header */ skb_trim(skb, skb->len - sizeof(desc_hdr)); desc_hdr = le64_to_cpup((u64 *)skb_tail_pointer(skb)); /* Check these packets */ desc_offset = (desc_hdr & AQ_RX_DH_DESC_OFFSET_MASK) >> AQ_RX_DH_DESC_OFFSET_SHIFT; pkt_count = desc_hdr & AQ_RX_DH_PKT_CNT_MASK; start_of_descs = skb_len - ((pkt_count + 1) * sizeof(desc_hdr)); /* self check descs position */ if (start_of_descs != desc_offset) goto err; /* self check desc_offset from header*/ if (desc_offset >= skb_len) goto err; if (pkt_count == 0) goto err; /* Get the first RX packet descriptor */ pkt_desc_ptr = (u64 *)(skb->data + desc_offset); while (pkt_count--) { u64 pkt_desc = le64_to_cpup(pkt_desc_ptr); u32 pkt_len_with_padd = 0; u32 pkt_len = 0; pkt_len = (u32)((pkt_desc & AQ_RX_PD_LEN_MASK) >> AQ_RX_PD_LEN_SHIFT); pkt_len_with_padd = ((pkt_len + 7) & 0x7FFF8); pkt_total_offset += pkt_len_with_padd; if (pkt_total_offset > desc_offset || (pkt_count == 0 && pkt_total_offset != desc_offset)) { goto err; } if (pkt_desc & AQ_RX_PD_DROP || !(pkt_desc & AQ_RX_PD_RX_OK) || pkt_len > (dev->hard_mtu + AQ_RX_HW_PAD)) { skb_pull(skb, pkt_len_with_padd); /* Next RX Packet Descriptor */ pkt_desc_ptr++; continue; } /* Clone SKB */ new_skb = skb_clone(skb, GFP_ATOMIC); if (!new_skb) goto err; new_skb->len = pkt_len; skb_pull(new_skb, AQ_RX_HW_PAD); skb_set_tail_pointer(new_skb, new_skb->len); new_skb->truesize = SKB_TRUESIZE(new_skb->len); usbnet_skb_return(dev, new_skb); if (pkt_count == 0) break; skb_pull(skb, pkt_len_with_padd); /* Next RX Packet Header */ pkt_desc_ptr++; new_skb = NULL; } return 1; err: return 0; } static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { Loading Loading @@ -637,6 +738,7 @@ static const struct driver_info aqc111_info = { .stop = aqc111_stop, .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET, .rx_fixup = aqc111_rx_fixup, .tx_fixup = aqc111_tx_fixup, }; Loading drivers/net/usb/aqc111.h +15 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ #ifndef __LINUX_USBNET_AQC111_H #define __LINUX_USBNET_AQC111_H #define URB_SIZE (1024 * 62) #define AQ_ACCESS_MAC 0x01 #define AQ_FLASH_PARAMETERS 0x20 #define AQ_PHY_POWER 0x31 Loading Loading @@ -157,6 +159,19 @@ struct aqc111_data { #define AQ_TX_DESC_LEN_MASK 0x1FFFFF #define AQ_TX_DESC_DROP_PADD BIT(28) #define AQ_RX_HW_PAD 0x02 /* RX Packet Descriptor */ #define AQ_RX_PD_RX_OK BIT(11) #define AQ_RX_PD_DROP BIT(31) #define AQ_RX_PD_LEN_MASK 0x7FFF0000 #define AQ_RX_PD_LEN_SHIFT 0x10 /* RX Descriptor header */ #define AQ_RX_DH_PKT_CNT_MASK 0x1FFF #define AQ_RX_DH_DESC_OFFSET_MASK 0xFFFFE000 #define AQ_RX_DH_DESC_OFFSET_SHIFT 0x0D static struct { unsigned char ctrl; unsigned char timer_l; Loading Loading
drivers/net/usb/aqc111.c +102 −0 Original line number Diff line number Diff line Loading @@ -294,6 +294,9 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf) ether_addr_copy(dev->net->dev_addr, dev->net->perm_addr); /* Set Rx urb size */ dev->rx_urb_size = URB_SIZE; /* Set TX needed headroom & tailroom */ dev->net->needed_headroom += sizeof(u64); dev->net->needed_tailroom += sizeof(u64); Loading Loading @@ -519,6 +522,8 @@ static int aqc111_reset(struct usbnet *dev) struct aqc111_data *aqc111_data = dev->driver_priv; u8 reg8 = 0; dev->rx_urb_size = URB_SIZE; if (usb_device_no_sg_constraint(dev->udev)) dev->can_dma_sg = 1; Loading Loading @@ -578,6 +583,102 @@ static int aqc111_stop(struct usbnet *dev) return 0; } static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { struct sk_buff *new_skb = NULL; u32 pkt_total_offset = 0; u64 *pkt_desc_ptr = NULL; u32 start_of_descs = 0; u32 desc_offset = 0; /*RX Header Offset*/ u16 pkt_count = 0; u64 desc_hdr = 0; u32 skb_len = 0; if (!skb) goto err; if (skb->len == 0) goto err; skb_len = skb->len; /* RX Descriptor Header */ skb_trim(skb, skb->len - sizeof(desc_hdr)); desc_hdr = le64_to_cpup((u64 *)skb_tail_pointer(skb)); /* Check these packets */ desc_offset = (desc_hdr & AQ_RX_DH_DESC_OFFSET_MASK) >> AQ_RX_DH_DESC_OFFSET_SHIFT; pkt_count = desc_hdr & AQ_RX_DH_PKT_CNT_MASK; start_of_descs = skb_len - ((pkt_count + 1) * sizeof(desc_hdr)); /* self check descs position */ if (start_of_descs != desc_offset) goto err; /* self check desc_offset from header*/ if (desc_offset >= skb_len) goto err; if (pkt_count == 0) goto err; /* Get the first RX packet descriptor */ pkt_desc_ptr = (u64 *)(skb->data + desc_offset); while (pkt_count--) { u64 pkt_desc = le64_to_cpup(pkt_desc_ptr); u32 pkt_len_with_padd = 0; u32 pkt_len = 0; pkt_len = (u32)((pkt_desc & AQ_RX_PD_LEN_MASK) >> AQ_RX_PD_LEN_SHIFT); pkt_len_with_padd = ((pkt_len + 7) & 0x7FFF8); pkt_total_offset += pkt_len_with_padd; if (pkt_total_offset > desc_offset || (pkt_count == 0 && pkt_total_offset != desc_offset)) { goto err; } if (pkt_desc & AQ_RX_PD_DROP || !(pkt_desc & AQ_RX_PD_RX_OK) || pkt_len > (dev->hard_mtu + AQ_RX_HW_PAD)) { skb_pull(skb, pkt_len_with_padd); /* Next RX Packet Descriptor */ pkt_desc_ptr++; continue; } /* Clone SKB */ new_skb = skb_clone(skb, GFP_ATOMIC); if (!new_skb) goto err; new_skb->len = pkt_len; skb_pull(new_skb, AQ_RX_HW_PAD); skb_set_tail_pointer(new_skb, new_skb->len); new_skb->truesize = SKB_TRUESIZE(new_skb->len); usbnet_skb_return(dev, new_skb); if (pkt_count == 0) break; skb_pull(skb, pkt_len_with_padd); /* Next RX Packet Header */ pkt_desc_ptr++; new_skb = NULL; } return 1; err: return 0; } static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { Loading Loading @@ -637,6 +738,7 @@ static const struct driver_info aqc111_info = { .stop = aqc111_stop, .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET, .rx_fixup = aqc111_rx_fixup, .tx_fixup = aqc111_tx_fixup, }; Loading
drivers/net/usb/aqc111.h +15 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ #ifndef __LINUX_USBNET_AQC111_H #define __LINUX_USBNET_AQC111_H #define URB_SIZE (1024 * 62) #define AQ_ACCESS_MAC 0x01 #define AQ_FLASH_PARAMETERS 0x20 #define AQ_PHY_POWER 0x31 Loading Loading @@ -157,6 +159,19 @@ struct aqc111_data { #define AQ_TX_DESC_LEN_MASK 0x1FFFFF #define AQ_TX_DESC_DROP_PADD BIT(28) #define AQ_RX_HW_PAD 0x02 /* RX Packet Descriptor */ #define AQ_RX_PD_RX_OK BIT(11) #define AQ_RX_PD_DROP BIT(31) #define AQ_RX_PD_LEN_MASK 0x7FFF0000 #define AQ_RX_PD_LEN_SHIFT 0x10 /* RX Descriptor header */ #define AQ_RX_DH_PKT_CNT_MASK 0x1FFF #define AQ_RX_DH_DESC_OFFSET_MASK 0xFFFFE000 #define AQ_RX_DH_DESC_OFFSET_SHIFT 0x0D static struct { unsigned char ctrl; unsigned char timer_l; Loading