On Sun, Aug 19, 2018 at 09:56:33AM +0200, Remi Locherer wrote: > It would help if you could send a clean version that applies to -current.
One of the attachments was in fact clean but yes, this thread has been much too noisy to follow easily. Try this. Index: if_axen.c =================================================================== RCS file: /cvs/src/sys/dev/usb/if_axen.c,v retrieving revision 1.25 diff -u -p -r1.25 if_axen.c --- if_axen.c 12 Jun 2018 06:59:27 -0000 1.25 +++ if_axen.c 18 Aug 2018 08:06:02 -0000 @@ -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 * 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, struc 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, struc 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 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,6 +932,15 @@ axen_rxeof(struct usbd_xfer *xfer, void 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; } @@ -928,16 +955,10 @@ axen_rxeof(struct usbd_xfer *xfer, void 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 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 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,11 +1029,22 @@ axen_rxeof(struct usbd_xfer *xfer, void 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); @@ -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 */ @@ -1260,6 +1290,14 @@ axen_init(void *xsc) * Cancel pending I/O and free all RX/TX buffers. */ axen_reset(sc); + +#define AXEN_CONFIG_NO 1 +#define AXEN_IFACE_IDX 0 + if (usbd_set_config_no(sc->axen_udev, AXEN_CONFIG_NO, 1) || + usbd_device2interface_handle(sc->axen_udev, AXEN_IFACE_IDX, + &sc->axen_iface)) + printf("%s: set_config failed\n", sc->axen_dev.dv_xname); + usbd_delay_ms(sc->axen_udev, 10); /* XXX: ? */ bval = 0x01; Index: if_axenreg.h =================================================================== RCS file: /cvs/src/sys/dev/usb/if_axenreg.h,v retrieving revision 1.6 diff -u -p -r1.6 if_axenreg.h --- if_axenreg.h 14 Sep 2016 12:41:09 -0000 1.6 +++ if_axenreg.h 18 Aug 2018 08:06:02 -0000 @@ -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