diff options
| author | Damien Broka <git@damien.sh> | 2023-09-13 08:23:47 +0000 |
|---|---|---|
| committer | Ed Maste <emaste@FreeBSD.org> | 2023-09-13 14:08:11 +0000 |
| commit | 70fbcd451b68b7f6038d8a602cd8d5e1bb890f1d (patch) | |
| tree | 729f066bc05c3c8a5b072d12ad18a9bf0ae4dd2d /sys/dev/usb/net | |
| parent | bb56b36d7188e004840294d0bd5dfdf7f3392a05 (diff) | |
Diffstat (limited to 'sys/dev/usb/net')
| -rw-r--r-- | sys/dev/usb/net/if_axge.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/sys/dev/usb/net/if_axge.c b/sys/dev/usb/net/if_axge.c index a3b459a553e0..385a982afd9d 100644 --- a/sys/dev/usb/net/if_axge.c +++ b/sys/dev/usb/net/if_axge.c @@ -959,8 +959,16 @@ axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen) hdr_off = pkt_end = (rxhdr >> 16) & 0xFFFF; /* + * On older firmware: * <----------------------- actlen ------------------------> * [frame #0]...[frame #N][pkt_hdr #0]...[pkt_hdr #N][rxhdr] + * + * On newer firmware: + * <----------------------- actlen ----------------- + * [frame #0]...[frame #N][pkt_hdr #0][dummy_hdr]... + * --------------------------------> + * ...[pkt_hdr #N][dummy_hdr][rxhdr] + * * Each RX frame would be aligned on 8 bytes boundary. If * RCR_IPE bit is set in AXGE_RCR register, there would be 2 * padding bytes and 6 dummy bytes(as the padding also should @@ -968,6 +976,10 @@ axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen) * IP header on 32bits boundary. Driver don't set RCR_IPE bit * of AXGE_RCR register, so there should be no padding bytes * which simplifies RX logic a lot. + * + * Further, newer firmware interweaves dummy headers that have + * pktlen == 0 and should be skipped without being seen as + * dropped frames. */ while (pkt_cnt--) { /* verify the header offset */ @@ -978,6 +990,12 @@ axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen) usbd_copy_out(pc, hdr_off, &pkt_hdr, sizeof(pkt_hdr)); pkt_hdr.status = le32toh(pkt_hdr.status); pktlen = AXGE_RXBYTES(pkt_hdr.status); + hdr_off += sizeof(pkt_hdr); + + /* Skip dummy packet header. */ + if (pktlen == 0) + continue; + if (pos + pktlen > pkt_end) { DPRINTF("Data position reached end\n"); break; @@ -989,7 +1007,6 @@ axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen) } else axge_rxeof(ue, pc, pos, pktlen, pkt_hdr.status); pos += (pktlen + 7) & ~7; - hdr_off += sizeof(pkt_hdr); } } |
