Skip to content

Commit 361459c

Browse files
Dmitry Bezrukovdavem330
authored andcommitted
net: usb: aqc111: Implement RX data path
Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 4a3576d commit 361459c

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

drivers/net/usb/aqc111.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
294294

295295
ether_addr_copy(dev->net->dev_addr, dev->net->perm_addr);
296296

297+
/* Set Rx urb size */
298+
dev->rx_urb_size = URB_SIZE;
299+
297300
/* Set TX needed headroom & tailroom */
298301
dev->net->needed_headroom += sizeof(u64);
299302
dev->net->needed_tailroom += sizeof(u64);
@@ -519,6 +522,8 @@ static int aqc111_reset(struct usbnet *dev)
519522
struct aqc111_data *aqc111_data = dev->driver_priv;
520523
u8 reg8 = 0;
521524

525+
dev->rx_urb_size = URB_SIZE;
526+
522527
if (usb_device_no_sg_constraint(dev->udev))
523528
dev->can_dma_sg = 1;
524529

@@ -578,6 +583,102 @@ static int aqc111_stop(struct usbnet *dev)
578583
return 0;
579584
}
580585

586+
static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
587+
{
588+
struct sk_buff *new_skb = NULL;
589+
u32 pkt_total_offset = 0;
590+
u64 *pkt_desc_ptr = NULL;
591+
u32 start_of_descs = 0;
592+
u32 desc_offset = 0; /*RX Header Offset*/
593+
u16 pkt_count = 0;
594+
u64 desc_hdr = 0;
595+
u32 skb_len = 0;
596+
597+
if (!skb)
598+
goto err;
599+
600+
if (skb->len == 0)
601+
goto err;
602+
603+
skb_len = skb->len;
604+
/* RX Descriptor Header */
605+
skb_trim(skb, skb->len - sizeof(desc_hdr));
606+
desc_hdr = le64_to_cpup((u64 *)skb_tail_pointer(skb));
607+
608+
/* Check these packets */
609+
desc_offset = (desc_hdr & AQ_RX_DH_DESC_OFFSET_MASK) >>
610+
AQ_RX_DH_DESC_OFFSET_SHIFT;
611+
pkt_count = desc_hdr & AQ_RX_DH_PKT_CNT_MASK;
612+
start_of_descs = skb_len - ((pkt_count + 1) * sizeof(desc_hdr));
613+
614+
/* self check descs position */
615+
if (start_of_descs != desc_offset)
616+
goto err;
617+
618+
/* self check desc_offset from header*/
619+
if (desc_offset >= skb_len)
620+
goto err;
621+
622+
if (pkt_count == 0)
623+
goto err;
624+
625+
/* Get the first RX packet descriptor */
626+
pkt_desc_ptr = (u64 *)(skb->data + desc_offset);
627+
628+
while (pkt_count--) {
629+
u64 pkt_desc = le64_to_cpup(pkt_desc_ptr);
630+
u32 pkt_len_with_padd = 0;
631+
u32 pkt_len = 0;
632+
633+
pkt_len = (u32)((pkt_desc & AQ_RX_PD_LEN_MASK) >>
634+
AQ_RX_PD_LEN_SHIFT);
635+
pkt_len_with_padd = ((pkt_len + 7) & 0x7FFF8);
636+
637+
pkt_total_offset += pkt_len_with_padd;
638+
if (pkt_total_offset > desc_offset ||
639+
(pkt_count == 0 && pkt_total_offset != desc_offset)) {
640+
goto err;
641+
}
642+
643+
if (pkt_desc & AQ_RX_PD_DROP ||
644+
!(pkt_desc & AQ_RX_PD_RX_OK) ||
645+
pkt_len > (dev->hard_mtu + AQ_RX_HW_PAD)) {
646+
skb_pull(skb, pkt_len_with_padd);
647+
/* Next RX Packet Descriptor */
648+
pkt_desc_ptr++;
649+
continue;
650+
}
651+
652+
/* Clone SKB */
653+
new_skb = skb_clone(skb, GFP_ATOMIC);
654+
655+
if (!new_skb)
656+
goto err;
657+
658+
new_skb->len = pkt_len;
659+
skb_pull(new_skb, AQ_RX_HW_PAD);
660+
skb_set_tail_pointer(new_skb, new_skb->len);
661+
662+
new_skb->truesize = SKB_TRUESIZE(new_skb->len);
663+
664+
usbnet_skb_return(dev, new_skb);
665+
if (pkt_count == 0)
666+
break;
667+
668+
skb_pull(skb, pkt_len_with_padd);
669+
670+
/* Next RX Packet Header */
671+
pkt_desc_ptr++;
672+
673+
new_skb = NULL;
674+
}
675+
676+
return 1;
677+
678+
err:
679+
return 0;
680+
}
681+
581682
static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
582683
gfp_t flags)
583684
{
@@ -637,6 +738,7 @@ static const struct driver_info aqc111_info = {
637738
.stop = aqc111_stop,
638739
.flags = FLAG_ETHER | FLAG_FRAMING_AX |
639740
FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
741+
.rx_fixup = aqc111_rx_fixup,
640742
.tx_fixup = aqc111_tx_fixup,
641743
};
642744

drivers/net/usb/aqc111.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#ifndef __LINUX_USBNET_AQC111_H
1111
#define __LINUX_USBNET_AQC111_H
1212

13+
#define URB_SIZE (1024 * 62)
14+
1315
#define AQ_ACCESS_MAC 0x01
1416
#define AQ_FLASH_PARAMETERS 0x20
1517
#define AQ_PHY_POWER 0x31
@@ -157,6 +159,19 @@ struct aqc111_data {
157159
#define AQ_TX_DESC_LEN_MASK 0x1FFFFF
158160
#define AQ_TX_DESC_DROP_PADD BIT(28)
159161

162+
#define AQ_RX_HW_PAD 0x02
163+
164+
/* RX Packet Descriptor */
165+
#define AQ_RX_PD_RX_OK BIT(11)
166+
#define AQ_RX_PD_DROP BIT(31)
167+
#define AQ_RX_PD_LEN_MASK 0x7FFF0000
168+
#define AQ_RX_PD_LEN_SHIFT 0x10
169+
170+
/* RX Descriptor header */
171+
#define AQ_RX_DH_PKT_CNT_MASK 0x1FFF
172+
#define AQ_RX_DH_DESC_OFFSET_MASK 0xFFFFE000
173+
#define AQ_RX_DH_DESC_OFFSET_SHIFT 0x0D
174+
160175
static struct {
161176
unsigned char ctrl;
162177
unsigned char timer_l;

0 commit comments

Comments
 (0)