I have 6.3 kernel compiled with option XHCI_debug and axen2.diff implemented.
I'm using lladdr option for /etc/hostname.axen0 to have the same IP addr each session for different Ehternet adapters. Here is debug output when axen is connected: xhci0: port=2 change=0x04 xhci0: port=2 change=0x04 xhci0: xhci_cmd_slot_control xhci0: dev 1, input=0xffffff0001988000 slot=0xffffff0001988020 ep0=0xffffff0001988040 xhci0: dev 1, setting DCBAA to 0x0000000001989000 xhci_pipe_init: pipe=0xffff800000a8d000 addr=0 depth=1 port=2 speed=4 dev 1 dci 1 (epAddr=0x0) xhci0: xhci_cmd_set_address BSR=1 xhci0: xhci_cmd_set_address BSR=0 xhci0: dev 1 addr 1 axen0 at uhub0 port 2 configuration 1 interface 0 "ASIX Elec. Corp. AX88179" rev 3.00/1.00 addr 2 axen0: AX88179, address xx:xx:xx:xx:xx:xx ukphy0 at axen0 phy 3: Generic IEEE 802.3u media interface, rev. 5: OUI 0x000732, model 0x0011 xhci_pipe_init: pipe=0xffff800000b38000 addr=2 depth=1 port=2 speed=4 dev 1 dci 5 (epAddr=0x82) xhci0: xhci_cmd_configure_ep dev 1 xhci_pipe_init: pipe=0xffff800000bfc000 addr=2 depth=1 port=2 speed=4 dev 1 dci 6 (epAddr=0x3) xhci0: xhci_cmd_configure_ep dev 1 xhci_abort_xfer: xfer=0xffffff044e6aee10 status=IN_PROGRESS err=CANCELLED actlen=0 len=65536 idx=0 xhci0: xhci_cmd_stop_ep dev 1 dci 5 xhci_event_xfer: stopped xfer=0xffffff044e6aee10 xhci0: xhci_cmd_set_tr_deq_async dev 1 dci 5 xhci0: xhci_cmd_configure_ep dev 1 xhci0: xhci_cmd_configure_ep dev 1 xhci_pipe_init: pipe=0xffff800000b3a000 addr=2 depth=1 port=2 speed=4 dev 1 dci 5 (epAddr=0x82) xhci0: xhci_cmd_configure_ep dev 1 xhci_pipe_init: pipe=0xffff800000b3e000 addr=2 depth=1 port=2 speed=4 dev 1 dci 6 (epAddr=0x3) xhci0: xhci_cmd_configure_ep dev 1 xhci_abort_xfer: xfer=0xffffff044e6aed20 status=IN_PROGRESS err=CANCELLED actlen=0 len=65536 idx=42 xhci0: xhci_cmd_stop_ep dev 1 dci 5 xhci_event_xfer: stopped xfer=0xffffff044e6aed20 xhci0: xhci_cmd_set_tr_deq_async dev 1 dci 5 xhci0: xhci_cmd_configure_ep dev 1 xhci0: xhci_cmd_configure_ep dev 1 xhci_pipe_init: pipe=0xffff800000790000 addr=2 depth=1 port=2 speed=4 dev 1 dci 5 (epAddr=0x82) xhci0: xhci_cmd_configure_ep dev 1 xhci_pipe_init: pipe=0xffff800000791000 addr=2 depth=1 port=2 speed=4 dev 1 dci 6 (epAddr=0x3) xhci0: xhci_cmd_configure_ep dev 1 xhci0: txerr? code 4 axen0: usb errors on rx: IOERROR xhci_abort_xfer: xfer=0xffffff044e6aee10 status=NOT_STARTED err=CANCELLED actlen=0 len=65536 idx=-1 xhci0: xhci_cmd_configure_ep dev 1 xhci0: xhci_cmd_configure_ep dev 1 xhci_pipe_init: pipe=0xffff8000007a9000 addr=2 depth=1 port=2 speed=4 dev 1 dci 5 (epAddr=0x82) xhci0: xhci_cmd_configure_ep dev 1 xhci_pipe_init: pipe=0xffff8000007aa000 addr=2 depth=1 port=2 speed=4 dev 1 dci 6 (epAddr=0x3) xhci0: xhci_cmd_configure_ep dev 1 xhci0: txerr? code 4 axen0: usb errors on rx: IOERROR xhci0: txerr? code 4 axen0: usb error on tx: IOERROR axen0: watchdog timeout axen0: usb error on tx: IOERROR xhci_abort_xfer: xfer=0xffffff044e6aed20 status=NOT_STARTED err=CANCELLED actlen=0 len=65536 idx=-1 xhci0: xhci_cmd_configure_ep dev 1 xhci0: xhci_cmd_configure_ep dev 1 xhci_pipe_init: pipe=0xffff800000865000 addr=2 depth=1 port=2 speed=4 dev 1 dci 5 (epAddr=0x82) xhci0: xhci_cmd_configure_ep dev 1 xhci_pipe_init: pipe=0xffff800000866000 addr=2 depth=1 port=2 speed=4 dev 1 dci 6 (epAddr=0x3) xhci0: xhci_cmd_configure_ep dev 1 xhci0: txerr? code 4 axen0: usb errors on rx: IOERROR xhci0: txerr? code 4 axen0: usb error on tx: IOERROR xhci_abort_xfer: xfer=0xffffff044e6aee10 status=NOT_STARTED err=CANCELLED actlen=0 len=65536 idx=-1 xhci0: xhci_cmd_configure_ep dev 1 xhci0: xhci_cmd_configure_ep dev 1 xhci_pipe_init: pipe=0xffff80000087e000 addr=2 depth=1 port=2 speed=4 dev 1 dci 5 (epAddr=0x82) xhci0: xhci_cmd_configure_ep dev 1 xhci_pipe_init: pipe=0xffff80000087f000 addr=2 depth=1 port=2 speed=4 dev 1 dci 6 (epAddr=0x3) xhci0: xhci_cmd_configure_ep dev 1 xhci0: txerr? code 4 axen0: usb errors on rx: IOERROR xhci0: txerr? code 4 axen0: usb error on tx: IOERROR axen0: watchdog timeout On 7/31/2018 11:08 AM, Denis wrote: > Hello, > > Thank you for patch. I can apply it a bit later in the trip currently. > > > > On 7/30/2018 3:11 AM, [email protected] wrote: >> Hi, >> >> On 2018/07/27 09:14, Denis wrote: >>> Every time (after 2-3 minutes of work) ASIX Electronics USB-Ethernet >>> device reports: >>> >>> axen0: usb errors on rx: IOERROR >>> axen0: usb errors on rx: IOERROR >>> axen0: usb errors on tx: IOERROR >>> axen0: watchdog timeout >>> axen0: usb errors on tx: IOERROR >>> >>> The device hangs and must be reattached to have it working again for 2-3 >>> minutes. >> >> Do you want to try this patch? >> >> ----- >> - header: fix comments >> - header: fix unused L3 type mask definition >> - rxeof: Avoid allocating mbuf if checksum errors are detected. >> - rxeof: Avoid loop to extract packets if pkt_count is 0. >> - rxeof: Add more sanity checks. >> - rxeof: Increament if_ierror in some error paths. >> - qctrl: Apply queuing control parameters from FreeBSD axge(4). >> - qctrl: Set qctrl in miireg_statchg dynamically, not statically. >> - Use DMA buffer aligned at 64KB boundary to avoid xhci bug. >> >> >> --- sys/dev/usb/if_axenreg.h Fri Sep 16 22:17:07 2016 >> +++ sys/dev/usb/if_axenreg.h Mon Jun 19 10:54:28 2017 >> @@ -26,8 +26,8 @@ >> * | | ++-----L3_type (1:ipv4, 0/2:ipv6) >> * pkt_len(13) | | ||+ ++-L4_type(0: icmp, 1: UDP, 4: TCP) >> * |765|43210 76543210|7654 3210 7654 3210| >> - * ||+-crc_err |+-L4_err |+-L4_CSUM_ERR >> - * |+-mii_err +--L3_err +--L3_CSUM_ERR >> + * ||+-crc_err |+-L4_err |+-L4_CSUM_ERR >> + * |+-mii_err +--L3_err +--L3_CSUM_ERR >> * +-drop_err >> * >> * ex) pkt_hdr 0x00680820 >> @@ -70,7 +70,7 @@ >> #define AXEN_RXHDR_L4_TYPE_TCP 0x4 >> >> /* L3 packet type (2bit) */ >> -#define AXEN_RXHDR_L3_TYPE_MASK 0x00000600 >> +#define AXEN_RXHDR_L3_TYPE_MASK 0x00000060 >> #define AXEN_RXHDR_L3_TYPE_OFFSET 5 >> #define AXEN_RXHDR_L3_TYPE_UNDEF 0x0 >> #define AXEN_RXHDR_L3_TYPE_IPV4 0x1 >> --- sys/dev/usb/if_axen.c.orig Tue Jun 12 15:36:59 2018 >> +++ sys/dev/usb/if_axen.c Sun Jul 29 01:53:43 2018 >> @@ -53,6 +53,7 @@ >> #include <dev/usb/usbdi_util.h> >> #include <dev/usb/usbdivar.h> >> #include <dev/usb/usbdevs.h> >> +#include <dev/usb/usb_mem.h> >> >> #include <dev/usb/if_axenreg.h> >> >> @@ -121,6 +122,13 @@ void axen_unlock_mii(struct axen_softc *sc); >> >> void axen_ax88179_init(struct axen_softc *); >> >> +struct axen_qctrl axen_bulk_size[] = { >> + { 7, 0x4f, 0x00, 0x12, 0xff }, >> + { 7, 0x20, 0x03, 0x16, 0xff }, >> + { 7, 0xae, 0x07, 0x18, 0xff }, >> + { 7, 0xcc, 0x4c, 0x18, 0x08 } >> +}; >> + >> /* Get exclusive access to the MII registers */ >> void >> axen_lock_mii(struct axen_softc *sc) >> @@ -238,6 +246,8 @@ axen_miibus_statchg(struct device *dev) >> int err; >> uint16_t val; >> uWord wval; >> + uint8_t linkstat = 0; >> + int qctrl; >> >> ifp = GET_IFP(sc); >> if (mii == NULL || ifp == NULL || >> @@ -265,27 +275,49 @@ axen_miibus_statchg(struct device *dev) >> return; >> >> val = 0; >> - if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) >> + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) { >> val |= AXEN_MEDIUM_FDX; >> + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0) >> + val |= AXEN_MEDIUM_TXFLOW_CTRL_EN; >> + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0) >> + val |= AXEN_MEDIUM_RXFLOW_CTRL_EN; >> + } >> >> - val |= (AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE); >> - val |= (AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN); >> + val |= AXEN_MEDIUM_RECV_EN; >> >> + /* bulkin queue setting */ >> + axen_lock_mii(sc); >> + axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_USB_UPLINK, &linkstat); >> + axen_unlock_mii(sc); >> + >> switch (IFM_SUBTYPE(mii->mii_media_active)) { >> case IFM_1000_T: >> val |= AXEN_MEDIUM_GIGA | AXEN_MEDIUM_EN_125MHZ; >> + if (linkstat & AXEN_USB_SS) >> + qctrl = 0; >> + else if (linkstat & AXEN_USB_HS) >> + qctrl = 1; >> + else >> + qctrl = 3; >> break; >> case IFM_100_TX: >> val |= AXEN_MEDIUM_PS; >> + if (linkstat & (AXEN_USB_SS | AXEN_USB_HS)) >> + qctrl = 2; >> + else >> + qctrl = 3; >> break; >> case IFM_10_T: >> - /* doesn't need to be handled */ >> + default: >> + qctrl = 3; >> break; >> } >> >> DPRINTF(("axen_miibus_statchg: val=0x%x\n", val)); >> USETW(wval, val); >> axen_lock_mii(sc); >> + axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL, >> + &axen_bulk_size[qctrl]); >> err = axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval); >> axen_unlock_mii(sc); >> if (err) { >> @@ -408,7 +440,6 @@ axen_ax88179_init(struct axen_softc *sc) >> uWord wval; >> uByte val; >> u_int16_t ctl, temp; >> - struct axen_qctrl qctrl; >> >> axen_lock_mii(sc); >> >> @@ -471,27 +502,12 @@ axen_ax88179_init(struct axen_softc *sc) >> switch (val) { >> case AXEN_USB_FS: >> DPRINTF(("uplink: USB1.1\n")); >> - qctrl.ctrl = 0x07; >> - qctrl.timer_low = 0xcc; >> - qctrl.timer_high= 0x4c; >> - qctrl.bufsize = AXEN_BUFSZ_LS - 1; >> - qctrl.ifg = 0x08; >> break; >> case AXEN_USB_HS: >> DPRINTF(("uplink: USB2.0\n")); >> - qctrl.ctrl = 0x07; >> - qctrl.timer_low = 0x02; >> - qctrl.timer_high= 0xa0; >> - qctrl.bufsize = AXEN_BUFSZ_HS - 1; >> - qctrl.ifg = 0xff; >> break; >> case AXEN_USB_SS: >> DPRINTF(("uplink: USB3.0\n")); >> - qctrl.ctrl = 0x07; >> - qctrl.timer_low = 0x4f; >> - qctrl.timer_high= 0x00; >> - qctrl.bufsize = AXEN_BUFSZ_SS - 1; >> - qctrl.ifg = 0xff; >> break; >> default: >> printf("%s: unknown uplink bus:0x%02x\n", >> @@ -499,7 +515,6 @@ axen_ax88179_init(struct axen_softc *sc) >> axen_unlock_mii(sc); >> return; >> } >> - axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL, &qctrl); >> >> /* Set MAC address. */ >> axen_cmd(sc, AXEN_CMD_MAC_WRITE_ETHER, ETHER_ADDR_LEN, >> @@ -622,22 +637,8 @@ axen_attach(struct device *parent, struct device *self >> >> id = usbd_get_interface_descriptor(sc->axen_iface); >> >> - /* decide on what our bufsize will be */ >> - switch (sc->axen_udev->speed) { >> - case USB_SPEED_FULL: >> - sc->axen_bufsz = AXEN_BUFSZ_LS * 1024; >> - break; >> - case USB_SPEED_HIGH: >> - sc->axen_bufsz = AXEN_BUFSZ_HS * 1024; >> - break; >> - case USB_SPEED_SUPER: >> - sc->axen_bufsz = AXEN_BUFSZ_SS * 1024; >> - break; >> - default: >> - printf("%s: not supported usb bus type", sc->axen_dev.dv_xname); >> - return; >> - } >> - >> + sc->axen_bufsz = 64 * 1024; >> + >> /* Find endpoints. */ >> for (i = 0; i < id->bNumEndpoints; i++) { >> ed = usbd_interface2endpoint_descriptor(sc->axen_iface, i); >> @@ -710,7 +711,8 @@ axen_attach(struct device *parent, struct device *self >> mii->mii_flags = MIIF_AUTOTSLEEP; >> >> ifmedia_init(&mii->mii_media, 0, axen_ifmedia_upd, axen_ifmedia_sts); >> - mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); >> + mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, >> + MIIF_DOPAUSE); >> >> if (LIST_FIRST(&mii->mii_phys) == NULL) { >> ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); >> @@ -808,6 +810,23 @@ axen_newbuf(void) >> return m; >> } >> >> +static void * >> +axen_alloc_buffer(struct usbd_xfer *xfer, u_int32_t size) >> +{ >> + struct usbd_bus *bus = xfer->device->bus; >> + usbd_status err; >> + >> +#ifdef DIAGNOSTIC >> + if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) >> + printf("axen_alloc_buffer: xfer already has a buffer\n"); >> +#endif >> + err = usb_allocmem(bus, size, 65536, &xfer->dmabuf); >> + if (err) >> + return (NULL); >> + xfer->rqflags |= URQ_DEV_DMABUF; >> + return (KERNADDR(&xfer->dmabuf, 0)); >> +} >> + >> int >> axen_rx_list_init(struct axen_softc *sc) >> { >> @@ -827,7 +846,7 @@ axen_rx_list_init(struct axen_softc *sc) >> c->axen_xfer = usbd_alloc_xfer(sc->axen_udev); >> if (c->axen_xfer == NULL) >> return ENOBUFS; >> - c->axen_buf = usbd_alloc_buffer(c->axen_xfer, >> + c->axen_buf = axen_alloc_buffer(c->axen_xfer, >> sc->axen_bufsz); >> if (c->axen_buf == NULL) { >> usbd_free_xfer(c->axen_xfer); >> @@ -858,7 +877,7 @@ axen_tx_list_init(struct axen_softc *sc) >> c->axen_xfer = usbd_alloc_xfer(sc->axen_udev); >> if (c->axen_xfer == NULL) >> return ENOBUFS; >> - c->axen_buf = usbd_alloc_buffer(c->axen_xfer, >> + c->axen_buf = axen_alloc_buffer(c->axen_xfer, >> sc->axen_bufsz); >> if (c->axen_buf == NULL) { >> usbd_free_xfer(c->axen_xfer); >> @@ -888,7 +907,6 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_st >> u_int32_t *hdr_p; >> u_int16_t hdr_offset, pkt_count; >> size_t pkt_len; >> - size_t temp; >> int s; >> >> DPRINTFN(10,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__)); >> @@ -914,10 +932,19 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, >> usbd_st >> usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); >> >> if (total_len < sizeof(pkt_hdr)) { >> + printf("%s: rxeof: too short transfer\n", >> + sc->axen_dev.dv_xname); >> ifp->if_ierrors++; >> goto done; >> } >> >> + if (total_len > sc->axen_bufsz) { >> + printf("%s: rxeof: too large transfer\n", >> + sc->axen_dev.dv_xname); >> + ifp->if_ierrors++; >> + goto done; >> + } >> + >> /* >> * buffer map >> * [packet #0]...[packet #n][pkt hdr#0]..[pkt hdr#n][recv_hdr] >> @@ -928,16 +955,10 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, >> usbd_st >> hdr_offset = (u_int16_t)(rx_hdr >> 16); >> pkt_count = (u_int16_t)(rx_hdr & 0xffff); >> >> - if (total_len > sc->axen_bufsz) { >> - printf("%s: rxeof: too large transfer\n", >> - sc->axen_dev.dv_xname); >> - goto done; >> - } >> - >> /* sanity check */ >> if (hdr_offset > total_len) { >> - ifp->if_ierrors++; >> usbd_delay_ms(sc->axen_udev, 100); >> + ifp->if_ierrors++; >> goto done; >> } >> >> @@ -954,11 +975,14 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, >> usbd_st >> if (pkt_count > AXEN_MAX_PACKED_PACKET) { >> DPRINTF(("Too many packets (%d) in a transaction, discard.\n", >> pkt_count)); >> + ifp->if_ierrors++; >> goto done; >> } >> #endif >> >> - do { >> + for (; pkt_count > 0; pkt_count--) { >> + uint16_t csum_flags = 0; >> + >> if ((buf[0] != 0xee) || (buf[1] != 0xee)){ >> printf("%s: invalid buffer(pkt#%d), continue\n", >> sc->axen_dev.dv_xname, pkt_count); >> @@ -972,34 +996,31 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, >> usbd_st >> DPRINTFN(10,("rxeof: packet#%d, pkt_hdr 0x%08x, pkt_len %zu\n", >> pkt_count, pkt_hdr, pkt_len)); >> >> + if (pkt_len > MCLBYTES || pkt_len < ETHER_MIN_LEN) { >> + printf("%s: invalid pkt_len %zu\n", >> + sc->axen_dev.dv_xname,pkt_len); >> + ifp->if_ierrors++; >> + goto nextpkt; >> + } >> + >> if ((pkt_hdr & AXEN_RXHDR_CRC_ERR) || >> (pkt_hdr & AXEN_RXHDR_DROP_ERR)) { >> - ifp->if_ierrors++; >> /* move to next pkt header */ >> DPRINTF(("crc err(pkt#%d)\n", pkt_count)); >> + ifp->if_ierrors++; >> goto nextpkt; >> } >> >> - /* process each packet */ >> - /* allocate mbuf */ >> - m = axen_newbuf(); >> - if (m == NULL) { >> - ifp->if_ierrors++; >> - goto nextpkt; >> - } >> - >> - /* skip pseudo header (2byte) and trailer padding (4Byte) */ >> - m->m_pkthdr.len = m->m_len = pkt_len - 6; >> - >> #ifdef AXEN_TOE >> /* cheksum err */ >> if ((pkt_hdr & AXEN_RXHDR_L3CSUM_ERR) || >> (pkt_hdr & AXEN_RXHDR_L4CSUM_ERR)) { >> printf("%s: checksum err (pkt#%d)\n", >> sc->axen_dev.dv_xname, pkt_count); >> + ifp->if_ierrors++; >> goto nextpkt; >> } else { >> - m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; >> + csum_flags |= M_IPV4_CSUM_IN_OK; >> } >> >> int l4_type; >> @@ -1008,12 +1029,23 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, >> usbd_st >> >> if ((l4_type == AXEN_RXHDR_L4_TYPE_TCP) || >> (l4_type == AXEN_RXHDR_L4_TYPE_UDP)) >> - m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK | >> - M_UDP_CSUM_IN_OK; >> + csum_flags |= M_TCP_CSUM_IN_OK | M_UDP_CSUM_IN_OK; >> #endif >> >> - memcpy(mtod(m, char *), buf + 2, pkt_len - 6); >> + /* process each packet */ >> + /* allocate mbuf */ >> + m = axen_newbuf(); >> + if (m == NULL) { >> + ifp->if_ierrors++; >> + goto nextpkt; >> + } >> >> + /* skip pseudo header (2byte) and trailer padding (4Byte) */ >> + m->m_pkthdr.len = m->m_len = pkt_len - 6; >> + m->m_pkthdr.csum_flags |= csum_flags; >> + >> + memcpy(mtod(m, char *), buf + 2, m->m_len); >> + >> ml_enqueue(&ml, m); >> >> nextpkt: >> @@ -1022,11 +1054,9 @@ nextpkt: >> * as each packet will be aligned 8byte boundary, >> * need to fix up the start point of the buffer. >> */ >> - temp = ((pkt_len + 7) & 0xfff8); >> - buf = buf + temp; >> + buf += roundup(pkt_len, 8); >> hdr_p++; >> - pkt_count--; >> - } while( pkt_count > 0); >> + } >> >> done: >> /* push the packet up */ >> >
