patch axen(4) (WIP)

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

patch axen(4) (WIP)

Nils Frohberg
Hi,

as mentioned previously, I'm looking into axen(4). While searching
for the cause of a panic (fixed since, thanks mpi@) I started to
rewrite parts of the driver. References were mainly the FreeBSD and
Linux drivers.

I didn't get around to much testing/debugging lately, therefore I
wanted to share the current state (diff below).

The current state works a lot better than previously (for me). I
used to have a huge amount of ierrs (aprrox. 1 ierr per ipkt) and
often no packets would be transferred at all (or stop being transferred
after some time).

This box hosts backups (rsync and TimeMachine), so it gets its fair
share of traffic. I could reduce the ierrs to ~2100 with 5d uptime,
and the packets keep flowing:

$ netstat -niI axen0
Name    Mtu   Network     Address              Ipkts Ierrs    Opkts Oerrs Colls
axen0   1500  <Link>      94:c6:91:1f:85:a5 141199356  2099 112289969     0     0
$ uptime
 7:15PM  up 5 days,  9:57, 3 users, load averages: 0.11, 0.13, 0.14
$

But there a still a few problems:

1) There are still ierrs. These happen when the rx path can't
allocate mbufs (cf. diff below for DPRINTF):
axen0: could not allocate rx mbuf (2 total, 2 remaining)
axen0: could not allocate rx mbuf (3 total, 3 remaining)
axen0: could not allocate rx mbuf (2 total, 2 remaining)
axen0: could not allocate rx mbuf (1 total, 1 remaining)

2) If the adapter is plugged into a USB 3 port at boot, it will
return 0x42 when aked for AXEN_PHYSICAL_LINK_STATUS, ie.
(AXEN_EPHY_1000|AXEN_USB_HS). The adapter most often then simply
doesn't receive packets. If I plug in the adapter after boot is
complete, 0x44 is returned (AXEN_EPHY_1000|AXEN_USB_SS), as expected.
I'm not sure if I'm still missing something in init (probably) or
if this results from something higher in the stack (xhci?).
(Didn't test USB 2 or lower.)

3) Transfer speed

Here's the diff:

Index: dev/usb/if_axen.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_axen.c,v
retrieving revision 1.26
diff -u -p -r1.26 if_axen.c
--- dev/usb/if_axen.c 5 Dec 2018 15:54:58 -0000 1.26
+++ dev/usb/if_axen.c 12 Feb 2019 18:26:48 -0000
@@ -97,7 +97,7 @@ const struct cfattach axen_ca = {
 
 int axen_tx_list_init(struct axen_softc *);
 int axen_rx_list_init(struct axen_softc *);
-struct mbuf *axen_newbuf(void);
+struct mbuf *axen_newbuf(struct axen_softc *);
 int axen_encap(struct axen_softc *, struct mbuf *, int);
 void axen_rxeof(struct usbd_xfer *, void *, usbd_status);
 void axen_txeof(struct usbd_xfer *, void *, usbd_status);
@@ -121,6 +121,13 @@ void axen_unlock_mii(struct axen_softc *
 
 void axen_ax88179_init(struct axen_softc *);
 
+struct axen_qctrl axen_bulk_size[] = {
+ { 7, 0x4f, 0x00, AXEN_BUFSZ_SS, 0xff },
+ { 7, 0x20, 0x03, AXEN_BUFSZ_HS, 0xff },
+ { 7, 0xae, 0x07, AXEN_BUFSZ_LS, 0xff },
+ { 7, 0xcc, 0x4c, AXEN_BUFSZ_LS, 0x08 }
+};
+
 /* Get exclusive access to the MII registers */
 void
 axen_lock_mii(struct axen_softc *sc)
@@ -156,7 +163,7 @@ axen_cmd(struct axen_softc *sc, int cmd,
  USETW(req.wLength, AXEN_CMD_LEN(cmd));
 
  err = usbd_do_request(sc->axen_udev, &req, buf);
- DPRINTFN(5, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n",
+ DPRINTFN(15, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n",
     cmd, val, AXEN_CMD_LEN(cmd)));
 
  if (err) {
@@ -193,7 +200,7 @@ axen_miibus_readreg(struct device *dev,
  }
 
  ival = UGETW(val);
- DPRINTFN(2,("axen_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n",
+ DPRINTFN(12,("axen_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n",
     phy, reg, ival));
 
  if (reg == MII_BMSR) {
@@ -220,7 +227,7 @@ axen_miibus_writereg(struct device *dev,
  axen_lock_mii(sc);
  err = axen_cmd(sc, AXEN_CMD_MII_WRITE_REG, reg, phy, &uval);
  axen_unlock_mii(sc);
- DPRINTFN(2, ("axen_miibus_writereg: phy 0x%x reg 0x%x val 0x%0x\n",
+ DPRINTFN(12, ("axen_miibus_writereg: phy 0x%x reg 0x%x val 0x%0x\n",
     phy, reg, val));
 
  if (err) {
@@ -236,13 +243,17 @@ axen_miibus_statchg(struct device *dev)
  struct mii_data *mii = GET_MII(sc);
  struct ifnet *ifp;
  int err;
+ uint8_t link_status;
  uint16_t val;
  uWord wval;
+ struct axen_qctrl *qctrl;
+
+ axen_lock_mii(sc);
 
  ifp = GET_IFP(sc);
  if (mii == NULL || ifp == NULL ||
     (ifp->if_flags & IFF_RUNNING) == 0)
- return;
+ goto done;
 
  sc->axen_link = 0;
  if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
@@ -250,10 +261,8 @@ axen_miibus_statchg(struct device *dev)
  switch (IFM_SUBTYPE(mii->mii_media_active)) {
     case IFM_10_T:
     case IFM_100_TX:
- sc->axen_link++;
- break;
     case IFM_1000_T:
- sc->axen_link++;
+ sc->axen_link = 1;
  break;
     default:
  break;
@@ -261,37 +270,97 @@ axen_miibus_statchg(struct device *dev)
  }
 
  /* Lost link, do nothing. */
- if (sc->axen_link == 0)
- return;
+ if (sc->axen_link == 0) {
+ DPRINTF(("%s: %s: lost link\n", sc->axen_dev.dv_xname,
+    __func__));
+ goto done;
+ }
 
- val = 0;
- if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
- val |= AXEN_MEDIUM_FDX;
+ err = axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_PHYSICAL_LINK_STATUS,
+    &link_status);
+ if (err)
+ goto error;
+ DPRINTF(("%s: %s: link status: 0x%x\n", sc->axen_dev.dv_xname,
+    __func__, link_status));
+
+ /* both freebsd and linux don't define/set AXEN_MEDIUM_ALWAYS_ONE,
+ * but 6.2.2.10 of the datasheet (p40) sets it to 1 */
+ val = AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE;
 
- val |= (AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE);
- val |= (AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN);
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
+ val |= AXEN_MEDIUM_FDX;
+#if 0
+ 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;
+#else
+ val |= AXEN_MEDIUM_TXFLOW_CTRL_EN | AXEN_MEDIUM_RXFLOW_CTRL_EN;
+#endif
+ }
 
  switch (IFM_SUBTYPE(mii->mii_media_active)) {
  case IFM_1000_T:
- val |= AXEN_MEDIUM_GIGA | AXEN_MEDIUM_EN_125MHZ;
+ if (!(link_status & AXEN_EPHY_1000)) {
+ printf("%s: wrong phy link (want 1000)\n",
+    sc->axen_dev.dv_xname);
+ }
+ val |= AXEN_MEDIUM_GIGA;
+ if (link_status & AXEN_USB_SS)
+ qctrl = &axen_bulk_size[0];
+ else if (link_status & AXEN_USB_HS)
+ qctrl = &axen_bulk_size[1];
+ else
+ qctrl = &axen_bulk_size[3];
  break;
  case IFM_100_TX:
- val |= AXEN_MEDIUM_PS;
+ if (!(link_status & AXEN_EPHY_100)) {
+ printf("%s: wrong phy link (want 100)\n",
+    sc->axen_dev.dv_xname);
+ }
+ val |= AXEN_MEDIUM_PORTSPEED_100;
+ if (link_status & (AXEN_USB_SS | AXEN_USB_HS))
+ qctrl = &axen_bulk_size[2];
+ else
+ qctrl = &axen_bulk_size[3];
  break;
  case IFM_10_T:
- /* doesn't need to be handled */
+ if (!(link_status & AXEN_EPHY_10)) {
+ printf("%s: wrong phy link (want 10)\n",
+    sc->axen_dev.dv_xname);
+ }
+ qctrl = &axen_bulk_size[3];
  break;
+ default:
+ printf("%s: unknown uplink bus: 0x%02x\n",
+    sc->axen_dev.dv_xname, link_status);
+ axen_unlock_mii(sc);
+ goto error;
  }
+ /* XXX change buffer size here */
+
+ /* RX bulk configuration. */
+ DPRINTF(("%s: %s: qtrl bufsize = 0x%x, ifg = 0x%x\n",
+    sc->axen_dev.dv_xname, __func__,
+    qctrl->bufsize, qctrl->ifg));
+ err = axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL,
+    qctrl);
+ if (err)
+ goto error;
 
- DPRINTF(("axen_miibus_statchg: val=0x%x\n", val));
+ DPRINTF(("%s: %s: val=0x%x\n", sc->axen_dev.dv_xname, __func__,val));
  USETW(wval, val);
- axen_lock_mii(sc);
  err = axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
+ if (err)
+ goto error;
+
+ goto done;
+
+error:
+ printf("%s: media change failed (err: 0x%x)\n", sc->axen_dev.dv_xname,
+    err);
+done:
  axen_unlock_mii(sc);
- if (err) {
- printf("%s: media change failed\n", sc->axen_dev.dv_xname);
- return;
- }
 }
 
 /*
@@ -345,6 +414,8 @@ axen_iff(struct axen_softc *sc)
  u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  uWord wval;
 
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
+
  if (usbd_is_dying(sc->axen_udev))
  return;
 
@@ -352,27 +423,27 @@ axen_iff(struct axen_softc *sc)
 
  /* Enable receiver, set RX mode */
  axen_lock_mii(sc);
- axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
- rxmode = UGETW(wval);
- rxmode &= ~(AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST |
-  AXEN_RXCTL_PROMISC);
+ rxmode = AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_START;
  ifp->if_flags &= ~IFF_ALLMULTI;
 
  /*
- * Always accept broadcast frames.
  * Always accept frames destined to our station address.
  */
- rxmode |= AXEN_RXCTL_ACPT_BCAST;
+ rxmode |= AXEN_RXCTL_ACPT_PHY_MCAST;
+ /*
+ * Accept broadcast frames iff interface has IFF_BROADCAST set.
+ */
+ if (ifp->if_flags & IFF_BROADCAST)
+ rxmode |= AXEN_RXCTL_ACPT_BCAST;
 
  if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
  ifp->if_flags |= IFF_ALLMULTI;
- rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST;
+ rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST;
  if (ifp->if_flags & IFF_PROMISC)
  rxmode |= AXEN_RXCTL_PROMISC;
  } else {
- rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST;
-
- /* now program new ones */
+ rxmode |= AXEN_RXCTL_ACPT_MCAST;
+ /* compute multicast filter array */
  ETHER_FIRST_MULTI(step, ac, enm);
  while (enm != NULL) {
  h = ether_crc32_be(enm->enm_addrlo,
@@ -382,8 +453,15 @@ axen_iff(struct axen_softc *sc)
  }
  }
 
- axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI,
+ DPRINTFN(5,("%s: %s: hashtbl: %x %x %x %x %x %x %x %x\n",
+    sc->axen_dev.dv_xname,__func__,
+    hashtbl[0], hashtbl[1], hashtbl[2], hashtbl[3],
+    hashtbl[4], hashtbl[5], hashtbl[6], hashtbl[7]));
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI,
     (void *)&hashtbl);
+
+ DPRINTFN(2,("%s: %s: rxmode: 0x%x\n",
+    sc->axen_dev.dv_xname,__func__,rxmode));
  USETW(wval, rxmode);
  axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
  axen_unlock_mii(sc);
@@ -392,13 +470,16 @@ axen_iff(struct axen_softc *sc)
 void
 axen_reset(struct axen_softc *sc)
 {
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
+
  if (usbd_is_dying(sc->axen_udev))
  return;
-
- axen_ax88179_init(sc);
 
  /* Wait a little while for the chip to get its brains in order. */
  DELAY(1000);
+
+ axen_ax88179_init(sc);
+
  return;
 }
 
@@ -408,7 +489,8 @@ axen_ax88179_init(struct axen_softc *sc)
  uWord wval;
  uByte val;
  u_int16_t ctl, temp;
- struct axen_qctrl qctrl;
+
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
 
  axen_lock_mii(sc);
 
@@ -440,6 +522,10 @@ axen_ax88179_init(struct axen_softc *sc)
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val);
  usbd_delay_ms(sc->axen_udev, 100);
 
+ /* RX bulk configuration */
+ axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL,
+    &axen_bulk_size[0]);
+
  /* set monitor mode (disable) */
  val = AXEN_MONITOR_NONE;
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
@@ -466,60 +552,25 @@ axen_ax88179_init(struct axen_softc *sc)
     sc->axen_dev.dv_xname, ctl);
  }
 
- /* bulkin queue setting */
- axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_USB_UPLINK, &val);
- 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",
-    sc->axen_dev.dv_xname, val);
- 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,
-    AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr);
-
  /*
  * set buffer high/low watermark to pause/resume.
  * write 2byte will set high/log simultaneous with AXEN_PAUSE_HIGH.
- * XXX: what is the best value? OSX driver uses 0x3c-0x4c as LOW-HIGH
- * watermark parameters.
+ * XXX: what is the best value?
+ * - defaults (datasheet): 0x24-0x42 as LOW-HIGH watermark parameters.
+ * - OSX driver uses 0x3c-0x4c as LOW-HIGH watermark parameters.(?)
+ * - FreeBSD driver uses 0x34-0x52 as LOW-HIGH watermark parameters.
+ * - Linux driver uses 0x34-0x52 as LOW-HIGH watermark parameters.
  */
- val = 0x34;
+ val = 0x24;
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_LOW_WATERMARK, &val);
- val = 0x52;
+ val = 0x42;
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_HIGH_WATERMARK, &val);
 
  /* Set RX/TX configuration. */
- /* Offloadng enable */
 #ifdef AXEN_TOE
+ /* enable offloading */
  val = AXEN_RXCOE_IPv4 | AXEN_RXCOE_TCPv4 | AXEN_RXCOE_UDPv4 |
+      AXEN_RXCOE_ICMP | AXEN_RXCOE_IGMP |
       AXEN_RXCOE_TCPv6 | AXEN_RXCOE_UDPv6;
 #else
  val = AXEN_RXCOE_OFF;
@@ -528,36 +579,36 @@ axen_ax88179_init(struct axen_softc *sc)
 
 #ifdef AXEN_TOE
  val = AXEN_TXCOE_IPv4 | AXEN_TXCOE_TCPv4 | AXEN_TXCOE_UDPv4 |
+      AXEN_TXCOE_ICMP | AXEN_TXCOE_IGMP |
       AXEN_TXCOE_TCPv6 | AXEN_TXCOE_UDPv6;
 #else
  val = AXEN_TXCOE_OFF;
 #endif
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val);
 
- /* Set RX control register */
- ctl = AXEN_RXCTL_IPE | AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_AUTOB;
- ctl |= AXEN_RXCTL_ACPT_PHY_MCAST | AXEN_RXCTL_ACPT_ALL_MCAST;
- ctl |= AXEN_RXCTL_START;
- USETW(wval, ctl);
- axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
-
- /* set monitor mode (enable) */
- val = AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP;
+ /* set monitor mode (XXX enable) */
+ /* AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP; */
+ val = 0;
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
+#ifdef AXEN_DEBUG
  axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_MONITOR_MODE, &val);
  DPRINTF(("axen: Monitor mode = 0x%02x\n", val));
+#endif
 
  /* set medium type */
- ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX | AXEN_MEDIUM_ALWAYS_ONE |
-      AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN;
- ctl |= AXEN_MEDIUM_RECV_EN;
+ ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX |
+      AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN |
+      AXEN_MEDIUM_RECV_EN;
  USETW(wval, ctl);
  DPRINTF(("axen: set to medium mode: 0x%04x\n", UGETW(wval)));
  axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
- usbd_delay_ms(sc->axen_udev, 100);
 
+#ifdef AXEN_DEBUG
+ usbd_delay_ms(sc->axen_udev, 100);
  axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval);
  DPRINTF(("axen: current medium mode: 0x%04x\n", UGETW(wval)));
+#endif
+
  axen_unlock_mii(sc);
 
 #if 0 /* XXX: TBD.... */
@@ -571,7 +622,16 @@ axen_ax88179_init(struct axen_softc *sc)
     0x002c);
 #endif
 
-#if 1 /* XXX: phy hack ? */
+#if 1 /* disable eee */
+ axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
+    AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE3);
+ axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
+    AXEN_MII_PHYADDR, 0x3246);
+ axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
+    AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE0);
+#endif
+
+#if 0 /* XXX: phy hack ? */
  axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x1F, 0x0005);
  axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x0C, 0x0000);
  val = axen_miibus_readreg(&sc->axen_dev, sc->axen_phyno, 0x0001);
@@ -606,6 +666,8 @@ axen_attach(struct device *parent, struc
  struct ifnet *ifp;
  int i, s;
 
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
+
  sc->axen_unit = self->dv_unit; /*device_get_unit(self);*/
  sc->axen_udev = uaa->device;
  sc->axen_iface = uaa->iface;
@@ -622,22 +684,23 @@ axen_attach(struct device *parent, struc
 
  id = usbd_get_interface_descriptor(sc->axen_iface);
 
- /* decide on what our bufsize will be */
+ /*
+ * our bufsize is determined by the usb speed and link speed
+ * so set it to the biggest buffer (slowest speed) available
+ * this will be updated once the link state changes
+ */
  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;
+ /* linux adds 2 to the buffer size (why?) */
+ sc->axen_bufsz = (AXEN_BUFSZ_MAX + 2) * 1024;
  break;
  default:
  printf("%s: not supported usb bus type", sc->axen_dev.dv_xname);
  return;
  }
-
+
  /* Find endpoints. */
  for (i = 0; i < id->bNumEndpoints; i++) {
  ed = usbd_interface2endpoint_descriptor(sc->axen_iface, i);
@@ -733,6 +796,8 @@ axen_detach(struct device *self, int fla
  struct axen_softc *sc = (struct axen_softc *)self;
  int s;
  struct ifnet *ifp = GET_IFP(sc);
+ uWord wval;
+ u_int16_t ctl;
 
  DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
 
@@ -760,9 +825,26 @@ axen_detach(struct device *self, int fla
  usb_detach_wait(&sc->axen_dev);
  }
 
- if (ifp->if_flags & IFF_RUNNING)
+ if (ifp->if_flags & IFF_RUNNING) {
  axen_stop(sc);
 
+ /* force bulk-in to return a zero-length USB packet */
+ axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_PHYPWR_RSTCTL, &wval);
+ ctl = UGETW(wval);
+ ctl |= AXEN_PHYPWR_RSTCTL_BZ | AXEN_PHYPWR_RSTCTL_IPRL;
+ ctl &= ~AXEN_PHYPWR_RSTCTL_BZ_AUTOCLEAR_DIS;
+ USETW(wval, ctl);
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval);
+
+ /* set clock to zero */
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, 0);
+
+ /* disable MAC */
+ ctl = AXEN_RXCTL_STOP;
+ USETW(wval, ctl);
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
+ }
+
  mii_detach(&sc->axen_mii, MII_PHY_ANY, MII_OFFSET_ANY);
  ifmedia_delete_instance(&sc->axen_mii.mii_media, IFM_INST_ANY);
  if (ifp->if_softc != NULL) {
@@ -788,16 +870,21 @@ axen_detach(struct device *self, int fla
 }
 
 struct mbuf *
-axen_newbuf(void)
+axen_newbuf(struct axen_softc *sc)
 {
  struct mbuf *m;
 
  MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
+ if (m == NULL) {
+ printf("%s: could not allocate mbuf\n",
+    sc->axen_dev.dv_xname);
  return NULL;
+ }
 
  MCLGET(m, M_DONTWAIT);
  if (!(m->m_flags & M_EXT)) {
+ printf("%s: could not allocate mbuf cluster\n",
+    sc->axen_dev.dv_xname);
  m_freem(m);
  return NULL;
  }
@@ -815,7 +902,8 @@ axen_rx_list_init(struct axen_softc *sc)
  struct axen_chain *c;
  int i;
 
- DPRINTF(("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
+ DPRINTF(("%s: %s: %d rx list entries of size %u\n",
+    sc->axen_dev.dv_xname, __func__,AXEN_RX_LIST_CNT,sc->axen_bufsz));
 
  cd = &sc->axen_cdata;
  for (i = 0; i < AXEN_RX_LIST_CNT; i++) {
@@ -846,7 +934,8 @@ axen_tx_list_init(struct axen_softc *sc)
  struct axen_chain *c;
  int i;
 
- DPRINTF(("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
+ DPRINTF(("%s: %s: %d tx list entries of size %u\n",
+    sc->axen_dev.dv_xname, __func__,AXEN_TX_LIST_CNT,sc->axen_bufsz));
 
  cd = &sc->axen_cdata;
  for (i = 0; i < AXEN_TX_LIST_CNT; i++) {
@@ -885,154 +974,244 @@ axen_rxeof(struct usbd_xfer *xfer, void
  struct mbuf *m;
  u_int32_t total_len;
  u_int32_t rx_hdr, pkt_hdr;
- u_int32_t *hdr_p;
+ u_int32_t *hdr_p, *pkt_end, *hdr_end;
  u_int16_t hdr_offset, pkt_count;
  size_t pkt_len;
- size_t temp;
  int s;
+#ifdef AXEN_DEBUG
+ u_int16_t total_pkt_count;
+#endif
 
  DPRINTFN(10,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
 
- if (usbd_is_dying(sc->axen_udev))
+ if (usbd_is_dying(sc->axen_udev)) {
+ DPRINTFN(15,("%s: %s: usbd_is_dying\n",
+    sc->axen_dev.dv_xname,__func__));
  return;
+ }
 
- if (!(ifp->if_flags & IFF_RUNNING))
+ if (!(ifp->if_flags & IFF_RUNNING)) {
+ DPRINTFN(15,("%s: %s: ! IFF_RUNNING\n",
+    sc->axen_dev.dv_xname,__func__));
  return;
+ }
 
  if (status != USBD_NORMAL_COMPLETION) {
+ DPRINTFN(9,("%s: %s: ! USBD_NORMAL_COMPLETION: 0x%x\n",
+    sc->axen_dev.dv_xname,__func__,status));
  if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
  return;
  if (usbd_ratecheck(&sc->axen_rx_notice)) {
  printf("%s: usb errors on rx: %s\n",
     sc->axen_dev.dv_xname, usbd_errstr(status));
  }
- if (status == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_RX]);
+ if (status == USBD_STALLED) {
+ DPRINTFN(9,("%s: %s: USBD_STALLED\n",
+    sc->axen_dev.dv_xname,__func__));
+ usbd_clear_endpoint_stall_async(
+    sc->axen_ep[AXEN_ENDPT_RX]);
+ }
+ DPRINTFN(10,("%s: %s: ! USBD_NORMAL_COMPLETION: done\n",
+    sc->axen_dev.dv_xname,__func__));
  goto done;
  }
 
  usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
 
- if (total_len < sizeof(pkt_hdr)) {
+ if (total_len < sizeof(rx_hdr)) {
+ printf("%s: rxeof: too short transfer (len %u)\n",
+    sc->axen_dev.dv_xname, total_len);
+ ifp->if_ierrors++;
+ goto done;
+ }
+
+ if (total_len > sc->axen_bufsz) {
+ printf("%s: rxeof: too large transfer (len %u)\n",
+    sc->axen_dev.dv_xname, total_len);
  ifp->if_ierrors++;
  goto done;
  }
 
- /*
- * buffer map
- * [packet #0]...[packet #n][pkt hdr#0]..[pkt hdr#n][recv_hdr]
- * each packet has 0xeeee as psuedo header..
+ /*
+ * <--------------------- total_len -------------------->
+ * [pkt #0]...[pkt #n][pkt_hdr #0]...[pkt_hdr #n][rx_hdr]
+ * ^buf               ^pkt_end                   ^hdr_end
+ *
+ * Each RX frame is aligned on 8 bytes boundary. If RXCTL_IPE
+ * bit is set in MAC_RXCTL register, there would be 2
+ * padding bytes and 6 dummy bytes(as the padding also should
+ * be aligned on 8 bytes boundary) for each RX frame to align
+ * IP header on 32bits boundary. We don't set RXCTL_IPE bit
+ * of MAC_RXCTL register, so there should be no padding bytes
+ * which simplifies RX logic a lot.
  */
- hdr_p = (u_int32_t *)(buf + total_len - sizeof(u_int32_t));
- rx_hdr = letoh32(*hdr_p);
+
+ hdr_end = (u_int32_t *)(buf + total_len - sizeof(rx_hdr));
+ rx_hdr = le32toh(*hdr_end);
  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;
- }
+#ifdef AXEN_DEBUG
+ total_pkt_count = pkt_count;
+#endif
 
  /* sanity check */
- if (hdr_offset > total_len) {
+ if (hdr_offset > total_len - sizeof(rx_hdr)) {
+ DPRINTFN(7,("%s: %s: hdr_offset (%u) > total_len (%u)"
+    " - sizeof(pkt_hdr) (%lu)\n",
+    sc->axen_dev.dv_xname,__func__,hdr_offset,total_len,
+    sizeof(rx_hdr)));
  ifp->if_ierrors++;
  goto done;
  }
 
  /* point first packet header */
- hdr_p = (u_int32_t*)(buf + hdr_offset);
-
- /*
- * ax88179 will pack multiple ip packet to a USB transaction.
- * process all of packets in the buffer
- */
+ hdr_p = pkt_end = (u_int32_t *)(buf + hdr_offset);
 
-#if 1 /* XXX: paranoiac check. need to remove later */
-#define AXEN_MAX_PACKED_PACKET 200
+#ifdef AXEN_DEBUG
+#define AXEN_MAX_PACKED_PACKET 200
  if (pkt_count > AXEN_MAX_PACKED_PACKET) {
- DPRINTF(("Too many packets (%d) in a transaction, discard.\n",
+ DPRINTF(("Too many packets (%d) in a transaction, discard.\n",
     pkt_count));
+ ifp->if_ierrors += pkt_count;
  goto done;
  }
 #endif
-
- do {
- if ((buf[0] != 0xee) || (buf[1] != 0xee)){
- printf("%s: invalid buffer(pkt#%d), continue\n",
-    sc->axen_dev.dv_xname, pkt_count);
-     ifp->if_ierrors += pkt_count;
- goto done;
+ /*
+ * ax88179 will pack multiple ip packet to a USB transaction.
+ * process all of packets in the buffer
+ */
+ DPRINTFN(10,("%s: %s: pkt_count = %u\n",
+    sc->axen_dev.dv_xname,__func__,pkt_count));
+ while(pkt_count--) {
+ /* verify the header offset */
+ if (hdr_p >= hdr_end) {
+ DPRINTF(("%s: %s: end of packet headers(pkt#%d)\n",
+    sc->axen_dev.dv_xname,__func__,pkt_count));
+ ifp->if_ierrors += pkt_count + 1;
+ goto input;
  }
 
  pkt_hdr = letoh32(*hdr_p);
  pkt_len = (pkt_hdr >> 16) & 0x1fff;
 
  DPRINTFN(10,("rxeof: packet#%d, pkt_hdr 0x%08x, pkt_len %zu\n",
-   pkt_count, pkt_hdr, pkt_len));
+    pkt_count, pkt_hdr, pkt_len));
 
- 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));
- goto nextpkt;
+ /* verify the data length */
+ if ((void *)buf + pkt_len > (void *)hdr_p) {
+ DPRINTF(("%s: %s: end of packet data(pkt#%d)\n",
+    sc->axen_dev.dv_xname,__func__,pkt_count));
+ ifp->if_ierrors += pkt_count + 1;
+ goto input;
  }
 
- /* process each packet */
- /* allocate mbuf */
- m = axen_newbuf();
- if (m == NULL) {
+ 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;
  }
 
- /* skip pseudo header (2byte) and trailer padding (4Byte) */
- m->m_pkthdr.len = m->m_len = pkt_len - 6;
+ if (AXEN_RXHDR_ERR(pkt_hdr)) {
+#ifdef AXEN_DEBUG
+ DPRINTFN(7,("%s: %s: err(pkt#%d) pkt_hdr 0x%08x,",
+    sc->axen_dev.dv_xname,__func__,pkt_count,pkt_hdr));
+ if (pkt_hdr & AXEN_RXHDR_DROP_ERR)
+ DPRINTFN(7,(" drop"));
+ if (pkt_hdr & AXEN_RXHDR_MII_ERR)
+ DPRINTFN(7,(" mii"));
+ if (pkt_hdr & AXEN_RXHDR_CRC_ERR)
+ DPRINTFN(7,(" crc"));
+ DPRINTFN(7,("\n"));
+#endif
+ ifp->if_ierrors++;
+ /* move to next pkt header */
+ goto nextpkt;
+ }
 
 #ifdef AXEN_TOE
  /* cheksum err */
- if ((pkt_hdr & AXEN_RXHDR_L3CSUM_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);
  goto nextpkt;
- } else {
- m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
  }
+#endif
 
- int l4_type;
- l4_type = (pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >>
-    AXEN_RXHDR_L4_TYPE_OFFSET;
+ /* process each packet */
+ /* allocate mbuf */
+ m = m_devget(buf, pkt_len, ETHER_ALIGN); /* axen_newbuf(sc) */
+ if (m == NULL) {
+#ifdef AXEN_DEBUG
+ DPRINTF(("%s: could not allocate rx mbuf "
+    "(%d total, %d remaining)\n",
+    sc->axen_dev.dv_xname,
+    total_pkt_count, pkt_count + 1));
+#endif
+ ifp->if_ierrors += pkt_count + 1;
+ goto input;
+ }
+
+#if 0 /* if using axen_newbuf() instead of m_devget() */
+ m->m_pkthdr.len = m->m_len = pkt_len;
+#endif
+
+#if 0 /* ifdef AXEN_TOE */
+ switch ((pkt_hdr & AXEN_RXHDR_L3_TYPE_MASK) >>
+    AXEN_RXHDR_L3_TYPE_OFFSET) {
+ case AXEN_RXHDR_L3_TYPE_IPV4:
+ m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
+ break;
+ case AXEN_RXHDR_L3_TYPE_IPV6:
+ /* XXX IPV6 equivalent of M_IPV4_CSUM_IN_OK? */
+ break;
+ default:
+ /* do we need to set something here? */
+ break;
+ }
 
- 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;
+ switch ((pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >>
+    AXEN_RXHDR_L4_TYPE_OFFSET) {
+ case AXEN_RXHDR_L4_TYPE_ICMP:
+ m->m_pkthdr.csum_flags |= M_ICMP_CSUM_IN_OK;
+ break;
+ case AXEN_RXHDR_L4_TYPE_UDP:
+ m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK;
+ break;
+ case AXEN_RXHDR_L4_TYPE_TCP:
+ m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK;
+ break;
+ default:
+ /* do we need to set something here? */
+ break;
+ }
 #endif
 
- memcpy(mtod(m, char *), buf + 2, pkt_len - 6);
+#if 0 /* if using axen_newbuf() instead of m_devget() */
+ memcpy(mtod(m, char *), buf, pkt_len);
+#endif
 
  ml_enqueue(&ml, m);
 
 nextpkt:
  /*
- * prepare next packet
+ * prepare next packet
  * 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 += (pkt_len + 7) & 0xfff8;
  hdr_p++;
- pkt_count--;
- } while( pkt_count > 0);
+ }
 
-done:
- /* push the packet up */
+input:
+ /* push the packets up */
  s = splnet();
  if_input(ifp, &ml);
  splx(s);
 
+done:
  /* clear buffer for next transaction */
  memset(c->axen_buf, 0, sc->axen_bufsz);
 
@@ -1043,7 +1222,7 @@ done:
     USBD_NO_TIMEOUT, axen_rxeof);
  usbd_transfer(xfer);
 
- DPRINTFN(10,("%s: %s: start rx\n", sc->axen_dev.dv_xname, __func__));
+ DPRINTFN(10,("%s: %s: end rx\n", sc->axen_dev.dv_xname, __func__));
 }
 
 /*
@@ -1076,7 +1255,8 @@ axen_txeof(struct usbd_xfer *xfer, void
  printf("axen%d: usb error on tx: %s\n", sc->axen_unit,
     usbd_errstr(status));
  if (status == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_TX]);
+ usbd_clear_endpoint_stall_async(
+    sc->axen_ep[AXEN_ENDPT_TX]);
  splx(s);
  return;
  }
@@ -1190,6 +1370,8 @@ axen_encap(struct axen_softc *sc, struct
  /* Transmit */
  err = usbd_transfer(c->axen_xfer);
  if (err != USBD_IN_PROGRESS) {
+ DPRINTFN(2,("%s: %s: usbd_transfer err = %d\n",
+    sc->axen_dev.dv_xname,__func__, err));
  axen_stop(sc);
  return EIO;
  }
@@ -1249,21 +1431,33 @@ axen_init(void *xsc)
  struct axen_chain *c;
  usbd_status err;
  int i, s;
- uByte bval;
  uWord wval;
  uint16_t rxmode;
 
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
+
  s = splnet();
 
  /*
  * Cancel pending I/O and free all RX/TX buffers.
  */
+ axen_stop(sc);
  axen_reset(sc);
 
- /* XXX: ? */
- bval = 0x01;
+ /* Set MAC address. */
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE_ETHER, ETHER_ADDR_LEN,
+    AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr);
+
+ /* Program promiscuous mode and multicast filters. */
+ axen_iff(sc);
+
+ /* Enable receiver, set RX mode */
  axen_lock_mii(sc);
- axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_UNK_28, &bval);
+ axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
+ rxmode = UGETW(wval);
+ rxmode |= AXEN_RXCTL_START;
+ USETW(wval, rxmode);
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
  axen_unlock_mii(sc);
 
  /* Init RX ring. */
@@ -1280,18 +1474,6 @@ axen_init(void *xsc)
  return;
  }
 
- /* Program promiscuous mode and multicast filters. */
- axen_iff(sc);
-
- /* Enable receiver, set RX mode */
- axen_lock_mii(sc);
- axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
- rxmode = UGETW(wval);
- rxmode |= AXEN_RXCTL_START;
- USETW(wval, rxmode);
- axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
- axen_unlock_mii(sc);
-
  /* Open RX and TX pipes. */
  err = usbd_open_pipe(sc->axen_iface, sc->axen_ed[AXEN_ENDPT_RX],
     USBD_EXCLUSIVE_USE, &sc->axen_ep[AXEN_ENDPT_RX]);
@@ -1396,7 +1578,7 @@ axen_watchdog(struct ifnet *ifp)
  sc = ifp->if_softc;
 
  ifp->if_oerrors++;
- printf("axen%d: watchdog timeout\n", sc->axen_unit);
+ printf("%s: watchdog timeout\n", sc->axen_dev.dv_xname);
 
  s = splusb();
  c = &sc->axen_cdata.axen_tx_chain[0];
@@ -1418,8 +1600,10 @@ axen_stop(struct axen_softc *sc)
  usbd_status err;
  struct ifnet *ifp;
  int i;
+ u_int16_t ctl;
+ uWord wval;
 
- axen_reset(sc);
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
 
  ifp = &sc->arpcom.ac_if;
  ifp->if_timer = 0;
@@ -1427,6 +1611,13 @@ axen_stop(struct axen_softc *sc)
  ifq_clr_oactive(&ifp->if_snd);
 
  timeout_del(&sc->axen_stat_ch);
+
+ /* disable receive */
+ axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval);
+ ctl = UGETW(wval);
+ ctl &= ~AXEN_MEDIUM_RECV_EN;
+ USETW(wval, ctl);
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
 
  /* Stop transfers. */
  if (sc->axen_ep[AXEN_ENDPT_RX] != NULL) {
Index: dev/usb/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
--- dev/usb/if_axenreg.h 14 Sep 2016 12:41:09 -0000 1.6
+++ dev/usb/if_axenreg.h 12 Feb 2019 18:26:48 -0000
@@ -12,9 +12,10 @@
 #define AXEN_PHY_ID 0x0003
 #define AXEN_MCAST_FILTER_SIZE 8
 /* unit: KB */
-#define AXEN_BUFSZ_LS 8
-#define AXEN_BUFSZ_HS 16
-#define AXEN_BUFSZ_SS 24
+#define AXEN_BUFSZ_LS 0x18
+#define AXEN_BUFSZ_HS 0x16
+#define AXEN_BUFSZ_SS 0x12
+#define AXEN_BUFSZ_MAX AXEN_BUFSZ_LS
 
 #define AXEN_REV_UA1 0
 #define AXEN_REV_UA2 1
@@ -26,8 +27,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
@@ -62,6 +63,10 @@
 #define AXEN_RXHDR_L3CSUM_ERR (1U << 1)
 #define AXEN_RXHDR_L4CSUM_ERR (1U << 0)
 
+#define AXEN_RXHDR_ERR(x) ((x) & (AXEN_RXHDR_DROP_ERR | \
+        AXEN_RXHDR_MII_ERR | \
+        AXEN_RXHDR_CRC_ERR))
+
 /* L4 packet type (3bit) */
 #define AXEN_RXHDR_L4_TYPE_MASK 0x0000001c
 #define AXEN_RXHDR_L4_TYPE_OFFSET 2
@@ -70,7 +75,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
@@ -88,10 +93,13 @@
 #define AXEN_CMD_MAC_READ 0x1001
 #define AXEN_CMD_MAC_WRITE 0x1101
 
-#define   AXEN_USB_UPLINK 0x02
+#define   AXEN_PHYSICAL_LINK_STATUS 0x02
 #define     AXEN_USB_FS  0x01
 #define     AXEN_USB_HS  0x02
 #define     AXEN_USB_SS  0x04
+#define     AXEN_EPHY_10  0x10
+#define     AXEN_EPHY_100  0x20
+#define     AXEN_EPHY_1000  0x40
 #define   AXEN_GENERAL_STATUS 0x03
 #define     AXEN_GENERAL_STATUS_MASK  0x4
 #define     AXEN_REV0  0x0
@@ -149,9 +157,9 @@
 #define     AXEN_RXCTL_STOP  0x0000
 #define     AXEN_RXCTL_PROMISC  0x0001
 #define     AXEN_RXCTL_ACPT_ALL_MCAST  0x0002
-#define     AXEN_RXCTL_HA8B  0x0004
-#define     AXEN_RXCTL_AUTOB  0x0008
-#define     AXEN_RXCTL_ACPT_BCAST  0x0010
+#define     AXEN_RXCTL_AUTOPAD_BNDRY  0x0004
+#define     AXEN_RXCTL_ACPT_BCAST  0x0008
+#define     AXEN_RXCTL_ACPT_MCAST  0x0010
 #define     AXEN_RXCTL_ACPT_PHY_MCAST  0x0020
 #define     AXEN_RXCTL_START  0x0080
 #define     AXEN_RXCTL_DROPCRCERR  0x0100
@@ -162,16 +170,27 @@
 #define    AXEN_MEDIUM_GIGA  0x0001
 #define    AXEN_MEDIUM_FDX  0x0002
 #define    AXEN_MEDIUM_ALWAYS_ONE  0x0004
-#define    AXEN_MEDIUM_EN_125MHZ  0x0008
+#define    AXEN_MEDIUM_ALWAYS_ZERO1  0x0008
 #define    AXEN_MEDIUM_RXFLOW_CTRL_EN  0x0010
 #define    AXEN_MEDIUM_TXFLOW_CTRL_EN  0x0020
+#define    AXEN_MEDIUM_JUMBOFRAME_EN  0x0040
+#define    AXEN_MEDIUM_PAUSEFRAME_LT_ONLY_EN  0x0080
 #define    AXEN_MEDIUM_RECV_EN  0x0100
-#define    AXEN_MEDIUM_PS  0x0200
-#define    AXEN_MEDIUM_JUMBO_EN  0x8040
+#define    AXEN_MEDIUM_PORTSPEED_100  0x0200
+#define    AXEN_MEDIUM_ALWAYS_ZERO2  0x0400
+#define    AXEN_MEDIUM_STOP_BACKPRESSURE  0x0800
+#define    AXEN_MEDIUM_SUPERMAC  0x1000
+#define    AXEN_MEDIUM_ALWAYS_ZERO3  0x2000
+#define    AXEN_MEDIUM_ALWAYS_ZERO4  0x4000
+#define    AXEN_MEDIUM_ALWAYS_ZERO5  0x8000
+#define    AXEN_MEDIUM_JUMBO_EN \
+ (AXEN_MEDIUM_JUMBOFRAME_EN | AXEN_MEDIUM_STOP_BACKPRESSURE)
 #define   AXEN_PHYPWR_RSTCTL 0x26
+#define     AXEN_PHYPWR_RSTCTL_BZ_AUTOCLEAR_DIS  0x0004
 #define     AXEN_PHYPWR_RSTCTL_BZ  0x0010
 #define     AXEN_PHYPWR_RSTCTL_IPRL  0x0020
 #define     AXEN_PHYPWR_RSTCTL_AUTODETACH  0x1000
+#define     AXEN_PHYPWR_RSTCTL_WOL_LOWPOWER  0x8000
 
 #define AXEN_CMD_EEPROM_READ 0x2004
 #define    AXEN_EEPROM_STAT  0x43
@@ -212,6 +231,20 @@
 #define AXEN_RX_LIST_CNT 1
 #define AXEN_TX_LIST_CNT 1
 
+
+/* ---GMII--- */
+#define AXEN_GMII_PHYPAGE 0x1e
+#define AXEN_GMII_PHY_PAGE_SELECT 0x1f
+#define AXEN_GMII_PHY_PGSEL_EXT  0x0007
+#define AXEN_GMII_PHY_PGSEL_PAGE0  0x0000
+#define AXEN_GMII_PHY_PGSEL_PAGE3  0x0003
+#define AXEN_GMII_PHY_PGSEL_PAGE5  0x0005
+#define AXEN_GMII_PHY_PGSEL_PAGE5  0x0005
+
+#define AXEN_MII_PHYADDR 0x19
+#define AXEN_MII_PHYADDR_EEE_DIS  0x3246
+#define AXEN_MII_PHYADDR_EEE_EN1  0x3247
+#define AXEN_MII_PHYADDR_EEE_EN2  0x0680
 
 /*
  * The interrupt endpoint is currently unused

Reply | Threaded
Open this post in threaded view
|

Re: patch axen(4) (WIP)

Martin Pieuchot
On 25/02/19(Mon) 14:52, Nils Frohberg wrote:
> Hi,
>
> as mentioned previously, I'm looking into axen(4). While searching
> for the cause of a panic (fixed since, thanks mpi@) I started to
> rewrite parts of the driver. References were mainly the FreeBSD and
> Linux drivers.

Please try to isolate parts of your diff that fixes issues and cosmetic
changes.  The simpler it gets the easier it is for us to review it.

> I didn't get around to much testing/debugging lately, therefore I
> wanted to share the current state (diff below).
>
> The current state works a lot better than previously (for me). I
> used to have a huge amount of ierrs (aprrox. 1 ierr per ipkt) and
> often no packets would be transferred at all (or stop being transferred
> after some time).

Do you know why?  What were the problems?

> This box hosts backups (rsync and TimeMachine), so it gets its fair
> share of traffic. I could reduce the ierrs to ~2100 with 5d uptime,
> and the packets keep flowing:
>
> $ netstat -niI axen0
> Name    Mtu   Network     Address              Ipkts Ierrs    Opkts Oerrs Colls
> axen0   1500  <Link>      94:c6:91:1f:85:a5 141199356  2099 112289969     0     0
> $ uptime
>  7:15PM  up 5 days,  9:57, 3 users, load averages: 0.11, 0.13, 0.14
> $
>
> But there a still a few problems:
>
> 1) There are still ierrs. These happen when the rx path can't
> allocate mbufs (cf. diff below for DPRINTF):
> axen0: could not allocate rx mbuf (2 total, 2 remaining)
> axen0: could not allocate rx mbuf (3 total, 3 remaining)
> axen0: could not allocate rx mbuf (2 total, 2 remaining)
> axen0: could not allocate rx mbuf (1 total, 1 remaining)

Look at the pools when this happen, what do you see?  What is the size
of `pkt_len' when this happen?

> 2) If the adapter is plugged into a USB 3 port at boot, it will
> return 0x42 when aked for AXEN_PHYSICAL_LINK_STATUS, ie.
> (AXEN_EPHY_1000|AXEN_USB_HS). The adapter most often then simply
> doesn't receive packets. If I plug in the adapter after boot is
> complete, 0x44 is returned (AXEN_EPHY_1000|AXEN_USB_SS), as expected.
> I'm not sure if I'm still missing something in init (probably) or
> if this results from something higher in the stack (xhci?).
> (Didn't test USB 2 or lower.)

Do you see any difference in 'usbdevs -vv' output during the two cases?

>
> 3) Transfer speed
>
> Here's the diff:
>
> Index: dev/usb/if_axen.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/if_axen.c,v
> retrieving revision 1.26
> diff -u -p -r1.26 if_axen.c
> --- dev/usb/if_axen.c 5 Dec 2018 15:54:58 -0000 1.26
> +++ dev/usb/if_axen.c 12 Feb 2019 18:26:48 -0000
> @@ -97,7 +97,7 @@ const struct cfattach axen_ca = {
>  
>  int axen_tx_list_init(struct axen_softc *);
>  int axen_rx_list_init(struct axen_softc *);
> -struct mbuf *axen_newbuf(void);
> +struct mbuf *axen_newbuf(struct axen_softc *);
>  int axen_encap(struct axen_softc *, struct mbuf *, int);
>  void axen_rxeof(struct usbd_xfer *, void *, usbd_status);
>  void axen_txeof(struct usbd_xfer *, void *, usbd_status);
> @@ -121,6 +121,13 @@ void axen_unlock_mii(struct axen_softc *
>  
>  void axen_ax88179_init(struct axen_softc *);
>  
> +struct axen_qctrl axen_bulk_size[] = {
> + { 7, 0x4f, 0x00, AXEN_BUFSZ_SS, 0xff },
> + { 7, 0x20, 0x03, AXEN_BUFSZ_HS, 0xff },
> + { 7, 0xae, 0x07, AXEN_BUFSZ_LS, 0xff },
> + { 7, 0xcc, 0x4c, AXEN_BUFSZ_LS, 0x08 }
> +};
> +
>  /* Get exclusive access to the MII registers */
>  void
>  axen_lock_mii(struct axen_softc *sc)
> @@ -156,7 +163,7 @@ axen_cmd(struct axen_softc *sc, int cmd,
>   USETW(req.wLength, AXEN_CMD_LEN(cmd));
>  
>   err = usbd_do_request(sc->axen_udev, &req, buf);
> - DPRINTFN(5, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n",
> + DPRINTFN(15, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n",
>      cmd, val, AXEN_CMD_LEN(cmd)));
>  
>   if (err) {
> @@ -193,7 +200,7 @@ axen_miibus_readreg(struct device *dev,
>   }
>  
>   ival = UGETW(val);
> - DPRINTFN(2,("axen_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n",
> + DPRINTFN(12,("axen_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n",
>      phy, reg, ival));
>  
>   if (reg == MII_BMSR) {
> @@ -220,7 +227,7 @@ axen_miibus_writereg(struct device *dev,
>   axen_lock_mii(sc);
>   err = axen_cmd(sc, AXEN_CMD_MII_WRITE_REG, reg, phy, &uval);
>   axen_unlock_mii(sc);
> - DPRINTFN(2, ("axen_miibus_writereg: phy 0x%x reg 0x%x val 0x%0x\n",
> + DPRINTFN(12, ("axen_miibus_writereg: phy 0x%x reg 0x%x val 0x%0x\n",
>      phy, reg, val));
>  
>   if (err) {
> @@ -236,13 +243,17 @@ axen_miibus_statchg(struct device *dev)
>   struct mii_data *mii = GET_MII(sc);
>   struct ifnet *ifp;
>   int err;
> + uint8_t link_status;
>   uint16_t val;
>   uWord wval;
> + struct axen_qctrl *qctrl;
> +
> + axen_lock_mii(sc);
>  
>   ifp = GET_IFP(sc);
>   if (mii == NULL || ifp == NULL ||
>      (ifp->if_flags & IFF_RUNNING) == 0)
> - return;
> + goto done;
>  
>   sc->axen_link = 0;
>   if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
> @@ -250,10 +261,8 @@ axen_miibus_statchg(struct device *dev)
>   switch (IFM_SUBTYPE(mii->mii_media_active)) {
>      case IFM_10_T:
>      case IFM_100_TX:
> - sc->axen_link++;
> - break;
>      case IFM_1000_T:
> - sc->axen_link++;
> + sc->axen_link = 1;
>   break;
>      default:
>   break;
> @@ -261,37 +270,97 @@ axen_miibus_statchg(struct device *dev)
>   }
>  
>   /* Lost link, do nothing. */
> - if (sc->axen_link == 0)
> - return;
> + if (sc->axen_link == 0) {
> + DPRINTF(("%s: %s: lost link\n", sc->axen_dev.dv_xname,
> +    __func__));
> + goto done;
> + }
>  
> - val = 0;
> - if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
> - val |= AXEN_MEDIUM_FDX;
> + err = axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_PHYSICAL_LINK_STATUS,
> +    &link_status);
> + if (err)
> + goto error;
> + DPRINTF(("%s: %s: link status: 0x%x\n", sc->axen_dev.dv_xname,
> +    __func__, link_status));
> +
> + /* both freebsd and linux don't define/set AXEN_MEDIUM_ALWAYS_ONE,
> + * but 6.2.2.10 of the datasheet (p40) sets it to 1 */
> + val = AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE;
>  
> - val |= (AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE);
> - val |= (AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN);
> + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
> + val |= AXEN_MEDIUM_FDX;
> +#if 0
> + 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;
> +#else
> + val |= AXEN_MEDIUM_TXFLOW_CTRL_EN | AXEN_MEDIUM_RXFLOW_CTRL_EN;
> +#endif
> + }
>  
>   switch (IFM_SUBTYPE(mii->mii_media_active)) {
>   case IFM_1000_T:
> - val |= AXEN_MEDIUM_GIGA | AXEN_MEDIUM_EN_125MHZ;
> + if (!(link_status & AXEN_EPHY_1000)) {
> + printf("%s: wrong phy link (want 1000)\n",
> +    sc->axen_dev.dv_xname);
> + }
> + val |= AXEN_MEDIUM_GIGA;
> + if (link_status & AXEN_USB_SS)
> + qctrl = &axen_bulk_size[0];
> + else if (link_status & AXEN_USB_HS)
> + qctrl = &axen_bulk_size[1];
> + else
> + qctrl = &axen_bulk_size[3];
>   break;
>   case IFM_100_TX:
> - val |= AXEN_MEDIUM_PS;
> + if (!(link_status & AXEN_EPHY_100)) {
> + printf("%s: wrong phy link (want 100)\n",
> +    sc->axen_dev.dv_xname);
> + }
> + val |= AXEN_MEDIUM_PORTSPEED_100;
> + if (link_status & (AXEN_USB_SS | AXEN_USB_HS))
> + qctrl = &axen_bulk_size[2];
> + else
> + qctrl = &axen_bulk_size[3];
>   break;
>   case IFM_10_T:
> - /* doesn't need to be handled */
> + if (!(link_status & AXEN_EPHY_10)) {
> + printf("%s: wrong phy link (want 10)\n",
> +    sc->axen_dev.dv_xname);
> + }
> + qctrl = &axen_bulk_size[3];
>   break;
> + default:
> + printf("%s: unknown uplink bus: 0x%02x\n",
> +    sc->axen_dev.dv_xname, link_status);
> + axen_unlock_mii(sc);
> + goto error;
>   }
> + /* XXX change buffer size here */
> +
> + /* RX bulk configuration. */
> + DPRINTF(("%s: %s: qtrl bufsize = 0x%x, ifg = 0x%x\n",
> +    sc->axen_dev.dv_xname, __func__,
> +    qctrl->bufsize, qctrl->ifg));
> + err = axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL,
> +    qctrl);
> + if (err)
> + goto error;
>  
> - DPRINTF(("axen_miibus_statchg: val=0x%x\n", val));
> + DPRINTF(("%s: %s: val=0x%x\n", sc->axen_dev.dv_xname, __func__,val));
>   USETW(wval, val);
> - axen_lock_mii(sc);
>   err = axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
> + if (err)
> + goto error;
> +
> + goto done;
> +
> +error:
> + printf("%s: media change failed (err: 0x%x)\n", sc->axen_dev.dv_xname,
> +    err);
> +done:
>   axen_unlock_mii(sc);
> - if (err) {
> - printf("%s: media change failed\n", sc->axen_dev.dv_xname);
> - return;
> - }
>  }
>  
>  /*
> @@ -345,6 +414,8 @@ axen_iff(struct axen_softc *sc)
>   u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
>   uWord wval;
>  
> + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
> +
>   if (usbd_is_dying(sc->axen_udev))
>   return;
>  
> @@ -352,27 +423,27 @@ axen_iff(struct axen_softc *sc)
>  
>   /* Enable receiver, set RX mode */
>   axen_lock_mii(sc);
> - axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
> - rxmode = UGETW(wval);
> - rxmode &= ~(AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST |
> -  AXEN_RXCTL_PROMISC);
> + rxmode = AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_START;
>   ifp->if_flags &= ~IFF_ALLMULTI;
>  
>   /*
> - * Always accept broadcast frames.
>   * Always accept frames destined to our station address.
>   */
> - rxmode |= AXEN_RXCTL_ACPT_BCAST;
> + rxmode |= AXEN_RXCTL_ACPT_PHY_MCAST;
> + /*
> + * Accept broadcast frames iff interface has IFF_BROADCAST set.
> + */
> + if (ifp->if_flags & IFF_BROADCAST)
> + rxmode |= AXEN_RXCTL_ACPT_BCAST;
>  
>   if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
>   ifp->if_flags |= IFF_ALLMULTI;
> - rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST;
> + rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST;
>   if (ifp->if_flags & IFF_PROMISC)
>   rxmode |= AXEN_RXCTL_PROMISC;
>   } else {
> - rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST;
> -
> - /* now program new ones */
> + rxmode |= AXEN_RXCTL_ACPT_MCAST;
> + /* compute multicast filter array */
>   ETHER_FIRST_MULTI(step, ac, enm);
>   while (enm != NULL) {
>   h = ether_crc32_be(enm->enm_addrlo,
> @@ -382,8 +453,15 @@ axen_iff(struct axen_softc *sc)
>   }
>   }
>  
> - axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI,
> + DPRINTFN(5,("%s: %s: hashtbl: %x %x %x %x %x %x %x %x\n",
> +    sc->axen_dev.dv_xname,__func__,
> +    hashtbl[0], hashtbl[1], hashtbl[2], hashtbl[3],
> +    hashtbl[4], hashtbl[5], hashtbl[6], hashtbl[7]));
> + axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI,
>      (void *)&hashtbl);
> +
> + DPRINTFN(2,("%s: %s: rxmode: 0x%x\n",
> +    sc->axen_dev.dv_xname,__func__,rxmode));
>   USETW(wval, rxmode);
>   axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
>   axen_unlock_mii(sc);
> @@ -392,13 +470,16 @@ axen_iff(struct axen_softc *sc)
>  void
>  axen_reset(struct axen_softc *sc)
>  {
> + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
> +
>   if (usbd_is_dying(sc->axen_udev))
>   return;
> -
> - axen_ax88179_init(sc);
>  
>   /* Wait a little while for the chip to get its brains in order. */
>   DELAY(1000);
> +
> + axen_ax88179_init(sc);
> +
>   return;
>  }
>  
> @@ -408,7 +489,8 @@ axen_ax88179_init(struct axen_softc *sc)
>   uWord wval;
>   uByte val;
>   u_int16_t ctl, temp;
> - struct axen_qctrl qctrl;
> +
> + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
>  
>   axen_lock_mii(sc);
>  
> @@ -440,6 +522,10 @@ axen_ax88179_init(struct axen_softc *sc)
>   axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val);
>   usbd_delay_ms(sc->axen_udev, 100);
>  
> + /* RX bulk configuration */
> + axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL,
> +    &axen_bulk_size[0]);
> +
>   /* set monitor mode (disable) */
>   val = AXEN_MONITOR_NONE;
>   axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
> @@ -466,60 +552,25 @@ axen_ax88179_init(struct axen_softc *sc)
>      sc->axen_dev.dv_xname, ctl);
>   }
>  
> - /* bulkin queue setting */
> - axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_USB_UPLINK, &val);
> - 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",
> -    sc->axen_dev.dv_xname, val);
> - 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,
> -    AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr);
> -
>   /*
>   * set buffer high/low watermark to pause/resume.
>   * write 2byte will set high/log simultaneous with AXEN_PAUSE_HIGH.
> - * XXX: what is the best value? OSX driver uses 0x3c-0x4c as LOW-HIGH
> - * watermark parameters.
> + * XXX: what is the best value?
> + * - defaults (datasheet): 0x24-0x42 as LOW-HIGH watermark parameters.
> + * - OSX driver uses 0x3c-0x4c as LOW-HIGH watermark parameters.(?)
> + * - FreeBSD driver uses 0x34-0x52 as LOW-HIGH watermark parameters.
> + * - Linux driver uses 0x34-0x52 as LOW-HIGH watermark parameters.
>   */
> - val = 0x34;
> + val = 0x24;
>   axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_LOW_WATERMARK, &val);
> - val = 0x52;
> + val = 0x42;
>   axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_HIGH_WATERMARK, &val);
>  
>   /* Set RX/TX configuration. */
> - /* Offloadng enable */
>  #ifdef AXEN_TOE
> + /* enable offloading */
>   val = AXEN_RXCOE_IPv4 | AXEN_RXCOE_TCPv4 | AXEN_RXCOE_UDPv4 |
> +      AXEN_RXCOE_ICMP | AXEN_RXCOE_IGMP |
>        AXEN_RXCOE_TCPv6 | AXEN_RXCOE_UDPv6;
>  #else
>   val = AXEN_RXCOE_OFF;
> @@ -528,36 +579,36 @@ axen_ax88179_init(struct axen_softc *sc)
>  
>  #ifdef AXEN_TOE
>   val = AXEN_TXCOE_IPv4 | AXEN_TXCOE_TCPv4 | AXEN_TXCOE_UDPv4 |
> +      AXEN_TXCOE_ICMP | AXEN_TXCOE_IGMP |
>        AXEN_TXCOE_TCPv6 | AXEN_TXCOE_UDPv6;
>  #else
>   val = AXEN_TXCOE_OFF;
>  #endif
>   axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val);
>  
> - /* Set RX control register */
> - ctl = AXEN_RXCTL_IPE | AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_AUTOB;
> - ctl |= AXEN_RXCTL_ACPT_PHY_MCAST | AXEN_RXCTL_ACPT_ALL_MCAST;
> - ctl |= AXEN_RXCTL_START;
> - USETW(wval, ctl);
> - axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
> -
> - /* set monitor mode (enable) */
> - val = AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP;
> + /* set monitor mode (XXX enable) */
> + /* AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP; */
> + val = 0;
>   axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
> +#ifdef AXEN_DEBUG
>   axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_MONITOR_MODE, &val);
>   DPRINTF(("axen: Monitor mode = 0x%02x\n", val));
> +#endif
>  
>   /* set medium type */
> - ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX | AXEN_MEDIUM_ALWAYS_ONE |
> -      AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN;
> - ctl |= AXEN_MEDIUM_RECV_EN;
> + ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX |
> +      AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN |
> +      AXEN_MEDIUM_RECV_EN;
>   USETW(wval, ctl);
>   DPRINTF(("axen: set to medium mode: 0x%04x\n", UGETW(wval)));
>   axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
> - usbd_delay_ms(sc->axen_udev, 100);
>  
> +#ifdef AXEN_DEBUG
> + usbd_delay_ms(sc->axen_udev, 100);
>   axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval);
>   DPRINTF(("axen: current medium mode: 0x%04x\n", UGETW(wval)));
> +#endif
> +
>   axen_unlock_mii(sc);
>  
>  #if 0 /* XXX: TBD.... */
> @@ -571,7 +622,16 @@ axen_ax88179_init(struct axen_softc *sc)
>      0x002c);
>  #endif
>  
> -#if 1 /* XXX: phy hack ? */
> +#if 1 /* disable eee */
> + axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
> +    AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE3);
> + axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
> +    AXEN_MII_PHYADDR, 0x3246);
> + axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
> +    AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE0);
> +#endif
> +
> +#if 0 /* XXX: phy hack ? */
>   axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x1F, 0x0005);
>   axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x0C, 0x0000);
>   val = axen_miibus_readreg(&sc->axen_dev, sc->axen_phyno, 0x0001);
> @@ -606,6 +666,8 @@ axen_attach(struct device *parent, struc
>   struct ifnet *ifp;
>   int i, s;
>  
> + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
> +
>   sc->axen_unit = self->dv_unit; /*device_get_unit(self);*/
>   sc->axen_udev = uaa->device;
>   sc->axen_iface = uaa->iface;
> @@ -622,22 +684,23 @@ axen_attach(struct device *parent, struc
>  
>   id = usbd_get_interface_descriptor(sc->axen_iface);
>  
> - /* decide on what our bufsize will be */
> + /*
> + * our bufsize is determined by the usb speed and link speed
> + * so set it to the biggest buffer (slowest speed) available
> + * this will be updated once the link state changes
> + */
>   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;
> + /* linux adds 2 to the buffer size (why?) */
> + sc->axen_bufsz = (AXEN_BUFSZ_MAX + 2) * 1024;
>   break;
>   default:
>   printf("%s: not supported usb bus type", sc->axen_dev.dv_xname);
>   return;
>   }
> -
> +
>   /* Find endpoints. */
>   for (i = 0; i < id->bNumEndpoints; i++) {
>   ed = usbd_interface2endpoint_descriptor(sc->axen_iface, i);
> @@ -733,6 +796,8 @@ axen_detach(struct device *self, int fla
>   struct axen_softc *sc = (struct axen_softc *)self;
>   int s;
>   struct ifnet *ifp = GET_IFP(sc);
> + uWord wval;
> + u_int16_t ctl;
>  
>   DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
>  
> @@ -760,9 +825,26 @@ axen_detach(struct device *self, int fla
>   usb_detach_wait(&sc->axen_dev);
>   }
>  
> - if (ifp->if_flags & IFF_RUNNING)
> + if (ifp->if_flags & IFF_RUNNING) {
>   axen_stop(sc);
>  
> + /* force bulk-in to return a zero-length USB packet */
> + axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_PHYPWR_RSTCTL, &wval);
> + ctl = UGETW(wval);
> + ctl |= AXEN_PHYPWR_RSTCTL_BZ | AXEN_PHYPWR_RSTCTL_IPRL;
> + ctl &= ~AXEN_PHYPWR_RSTCTL_BZ_AUTOCLEAR_DIS;
> + USETW(wval, ctl);
> + axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval);
> +
> + /* set clock to zero */
> + axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, 0);
> +
> + /* disable MAC */
> + ctl = AXEN_RXCTL_STOP;
> + USETW(wval, ctl);
> + axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
> + }
> +
>   mii_detach(&sc->axen_mii, MII_PHY_ANY, MII_OFFSET_ANY);
>   ifmedia_delete_instance(&sc->axen_mii.mii_media, IFM_INST_ANY);
>   if (ifp->if_softc != NULL) {
> @@ -788,16 +870,21 @@ axen_detach(struct device *self, int fla
>  }
>  
>  struct mbuf *
> -axen_newbuf(void)
> +axen_newbuf(struct axen_softc *sc)
>  {
>   struct mbuf *m;
>  
>   MGETHDR(m, M_DONTWAIT, MT_DATA);
> - if (m == NULL)
> + if (m == NULL) {
> + printf("%s: could not allocate mbuf\n",
> +    sc->axen_dev.dv_xname);
>   return NULL;
> + }
>  
>   MCLGET(m, M_DONTWAIT);
>   if (!(m->m_flags & M_EXT)) {
> + printf("%s: could not allocate mbuf cluster\n",
> +    sc->axen_dev.dv_xname);
>   m_freem(m);
>   return NULL;
>   }
> @@ -815,7 +902,8 @@ axen_rx_list_init(struct axen_softc *sc)
>   struct axen_chain *c;
>   int i;
>  
> - DPRINTF(("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
> + DPRINTF(("%s: %s: %d rx list entries of size %u\n",
> +    sc->axen_dev.dv_xname, __func__,AXEN_RX_LIST_CNT,sc->axen_bufsz));
>  
>   cd = &sc->axen_cdata;
>   for (i = 0; i < AXEN_RX_LIST_CNT; i++) {
> @@ -846,7 +934,8 @@ axen_tx_list_init(struct axen_softc *sc)
>   struct axen_chain *c;
>   int i;
>  
> - DPRINTF(("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
> + DPRINTF(("%s: %s: %d tx list entries of size %u\n",
> +    sc->axen_dev.dv_xname, __func__,AXEN_TX_LIST_CNT,sc->axen_bufsz));
>  
>   cd = &sc->axen_cdata;
>   for (i = 0; i < AXEN_TX_LIST_CNT; i++) {
> @@ -885,154 +974,244 @@ axen_rxeof(struct usbd_xfer *xfer, void
>   struct mbuf *m;
>   u_int32_t total_len;
>   u_int32_t rx_hdr, pkt_hdr;
> - u_int32_t *hdr_p;
> + u_int32_t *hdr_p, *pkt_end, *hdr_end;
>   u_int16_t hdr_offset, pkt_count;
>   size_t pkt_len;
> - size_t temp;
>   int s;
> +#ifdef AXEN_DEBUG
> + u_int16_t total_pkt_count;
> +#endif
>  
>   DPRINTFN(10,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
>  
> - if (usbd_is_dying(sc->axen_udev))
> + if (usbd_is_dying(sc->axen_udev)) {
> + DPRINTFN(15,("%s: %s: usbd_is_dying\n",
> +    sc->axen_dev.dv_xname,__func__));
>   return;
> + }
>  
> - if (!(ifp->if_flags & IFF_RUNNING))
> + if (!(ifp->if_flags & IFF_RUNNING)) {
> + DPRINTFN(15,("%s: %s: ! IFF_RUNNING\n",
> +    sc->axen_dev.dv_xname,__func__));
>   return;
> + }
>  
>   if (status != USBD_NORMAL_COMPLETION) {
> + DPRINTFN(9,("%s: %s: ! USBD_NORMAL_COMPLETION: 0x%x\n",
> +    sc->axen_dev.dv_xname,__func__,status));
>   if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
>   return;
>   if (usbd_ratecheck(&sc->axen_rx_notice)) {
>   printf("%s: usb errors on rx: %s\n",
>      sc->axen_dev.dv_xname, usbd_errstr(status));
>   }
> - if (status == USBD_STALLED)
> - usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_RX]);
> + if (status == USBD_STALLED) {
> + DPRINTFN(9,("%s: %s: USBD_STALLED\n",
> +    sc->axen_dev.dv_xname,__func__));
> + usbd_clear_endpoint_stall_async(
> +    sc->axen_ep[AXEN_ENDPT_RX]);
> + }
> + DPRINTFN(10,("%s: %s: ! USBD_NORMAL_COMPLETION: done\n",
> +    sc->axen_dev.dv_xname,__func__));
>   goto done;
>   }
>  
>   usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
>  
> - if (total_len < sizeof(pkt_hdr)) {
> + if (total_len < sizeof(rx_hdr)) {
> + printf("%s: rxeof: too short transfer (len %u)\n",
> +    sc->axen_dev.dv_xname, total_len);
> + ifp->if_ierrors++;
> + goto done;
> + }
> +
> + if (total_len > sc->axen_bufsz) {
> + printf("%s: rxeof: too large transfer (len %u)\n",
> +    sc->axen_dev.dv_xname, total_len);
>   ifp->if_ierrors++;
>   goto done;
>   }
>  
> - /*
> - * buffer map
> - * [packet #0]...[packet #n][pkt hdr#0]..[pkt hdr#n][recv_hdr]
> - * each packet has 0xeeee as psuedo header..
> + /*
> + * <--------------------- total_len -------------------->
> + * [pkt #0]...[pkt #n][pkt_hdr #0]...[pkt_hdr #n][rx_hdr]
> + * ^buf               ^pkt_end                   ^hdr_end
> + *
> + * Each RX frame is aligned on 8 bytes boundary. If RXCTL_IPE
> + * bit is set in MAC_RXCTL register, there would be 2
> + * padding bytes and 6 dummy bytes(as the padding also should
> + * be aligned on 8 bytes boundary) for each RX frame to align
> + * IP header on 32bits boundary. We don't set RXCTL_IPE bit
> + * of MAC_RXCTL register, so there should be no padding bytes
> + * which simplifies RX logic a lot.
>   */
> - hdr_p = (u_int32_t *)(buf + total_len - sizeof(u_int32_t));
> - rx_hdr = letoh32(*hdr_p);
> +
> + hdr_end = (u_int32_t *)(buf + total_len - sizeof(rx_hdr));
> + rx_hdr = le32toh(*hdr_end);
>   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;
> - }
> +#ifdef AXEN_DEBUG
> + total_pkt_count = pkt_count;
> +#endif
>  
>   /* sanity check */
> - if (hdr_offset > total_len) {
> + if (hdr_offset > total_len - sizeof(rx_hdr)) {
> + DPRINTFN(7,("%s: %s: hdr_offset (%u) > total_len (%u)"
> +    " - sizeof(pkt_hdr) (%lu)\n",
> +    sc->axen_dev.dv_xname,__func__,hdr_offset,total_len,
> +    sizeof(rx_hdr)));
>   ifp->if_ierrors++;
>   goto done;
>   }
>  
>   /* point first packet header */
> - hdr_p = (u_int32_t*)(buf + hdr_offset);
> -
> - /*
> - * ax88179 will pack multiple ip packet to a USB transaction.
> - * process all of packets in the buffer
> - */
> + hdr_p = pkt_end = (u_int32_t *)(buf + hdr_offset);
>  
> -#if 1 /* XXX: paranoiac check. need to remove later */
> -#define AXEN_MAX_PACKED_PACKET 200
> +#ifdef AXEN_DEBUG
> +#define AXEN_MAX_PACKED_PACKET 200
>   if (pkt_count > AXEN_MAX_PACKED_PACKET) {
> - DPRINTF(("Too many packets (%d) in a transaction, discard.\n",
> + DPRINTF(("Too many packets (%d) in a transaction, discard.\n",
>      pkt_count));
> + ifp->if_ierrors += pkt_count;
>   goto done;
>   }
>  #endif
> -
> - do {
> - if ((buf[0] != 0xee) || (buf[1] != 0xee)){
> - printf("%s: invalid buffer(pkt#%d), continue\n",
> -    sc->axen_dev.dv_xname, pkt_count);
> -     ifp->if_ierrors += pkt_count;
> - goto done;
> + /*
> + * ax88179 will pack multiple ip packet to a USB transaction.
> + * process all of packets in the buffer
> + */
> + DPRINTFN(10,("%s: %s: pkt_count = %u\n",
> +    sc->axen_dev.dv_xname,__func__,pkt_count));
> + while(pkt_count--) {
> + /* verify the header offset */
> + if (hdr_p >= hdr_end) {
> + DPRINTF(("%s: %s: end of packet headers(pkt#%d)\n",
> +    sc->axen_dev.dv_xname,__func__,pkt_count));
> + ifp->if_ierrors += pkt_count + 1;
> + goto input;
>   }
>  
>   pkt_hdr = letoh32(*hdr_p);
>   pkt_len = (pkt_hdr >> 16) & 0x1fff;
>  
>   DPRINTFN(10,("rxeof: packet#%d, pkt_hdr 0x%08x, pkt_len %zu\n",
> -   pkt_count, pkt_hdr, pkt_len));
> +    pkt_count, pkt_hdr, pkt_len));
>  
> - 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));
> - goto nextpkt;
> + /* verify the data length */
> + if ((void *)buf + pkt_len > (void *)hdr_p) {
> + DPRINTF(("%s: %s: end of packet data(pkt#%d)\n",
> +    sc->axen_dev.dv_xname,__func__,pkt_count));
> + ifp->if_ierrors += pkt_count + 1;
> + goto input;
>   }
>  
> - /* process each packet */
> - /* allocate mbuf */
> - m = axen_newbuf();
> - if (m == NULL) {
> + 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;
>   }
>  
> - /* skip pseudo header (2byte) and trailer padding (4Byte) */
> - m->m_pkthdr.len = m->m_len = pkt_len - 6;
> + if (AXEN_RXHDR_ERR(pkt_hdr)) {
> +#ifdef AXEN_DEBUG
> + DPRINTFN(7,("%s: %s: err(pkt#%d) pkt_hdr 0x%08x,",
> +    sc->axen_dev.dv_xname,__func__,pkt_count,pkt_hdr));
> + if (pkt_hdr & AXEN_RXHDR_DROP_ERR)
> + DPRINTFN(7,(" drop"));
> + if (pkt_hdr & AXEN_RXHDR_MII_ERR)
> + DPRINTFN(7,(" mii"));
> + if (pkt_hdr & AXEN_RXHDR_CRC_ERR)
> + DPRINTFN(7,(" crc"));
> + DPRINTFN(7,("\n"));
> +#endif
> + ifp->if_ierrors++;
> + /* move to next pkt header */
> + goto nextpkt;
> + }
>  
>  #ifdef AXEN_TOE
>   /* cheksum err */
> - if ((pkt_hdr & AXEN_RXHDR_L3CSUM_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);
>   goto nextpkt;
> - } else {
> - m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
>   }
> +#endif
>  
> - int l4_type;
> - l4_type = (pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >>
> -    AXEN_RXHDR_L4_TYPE_OFFSET;
> + /* process each packet */
> + /* allocate mbuf */
> + m = m_devget(buf, pkt_len, ETHER_ALIGN); /* axen_newbuf(sc) */
> + if (m == NULL) {
> +#ifdef AXEN_DEBUG
> + DPRINTF(("%s: could not allocate rx mbuf "
> +    "(%d total, %d remaining)\n",
> +    sc->axen_dev.dv_xname,
> +    total_pkt_count, pkt_count + 1));
> +#endif
> + ifp->if_ierrors += pkt_count + 1;
> + goto input;
> + }
> +
> +#if 0 /* if using axen_newbuf() instead of m_devget() */
> + m->m_pkthdr.len = m->m_len = pkt_len;
> +#endif
> +
> +#if 0 /* ifdef AXEN_TOE */
> + switch ((pkt_hdr & AXEN_RXHDR_L3_TYPE_MASK) >>
> +    AXEN_RXHDR_L3_TYPE_OFFSET) {
> + case AXEN_RXHDR_L3_TYPE_IPV4:
> + m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
> + break;
> + case AXEN_RXHDR_L3_TYPE_IPV6:
> + /* XXX IPV6 equivalent of M_IPV4_CSUM_IN_OK? */
> + break;
> + default:
> + /* do we need to set something here? */
> + break;
> + }
>  
> - 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;
> + switch ((pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >>
> +    AXEN_RXHDR_L4_TYPE_OFFSET) {
> + case AXEN_RXHDR_L4_TYPE_ICMP:
> + m->m_pkthdr.csum_flags |= M_ICMP_CSUM_IN_OK;
> + break;
> + case AXEN_RXHDR_L4_TYPE_UDP:
> + m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK;
> + break;
> + case AXEN_RXHDR_L4_TYPE_TCP:
> + m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK;
> + break;
> + default:
> + /* do we need to set something here? */
> + break;
> + }
>  #endif
>  
> - memcpy(mtod(m, char *), buf + 2, pkt_len - 6);
> +#if 0 /* if using axen_newbuf() instead of m_devget() */
> + memcpy(mtod(m, char *), buf, pkt_len);
> +#endif
>  
>   ml_enqueue(&ml, m);
>  
>  nextpkt:
>   /*
> - * prepare next packet
> + * prepare next packet
>   * 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 += (pkt_len + 7) & 0xfff8;
>   hdr_p++;
> - pkt_count--;
> - } while( pkt_count > 0);
> + }
>  
> -done:
> - /* push the packet up */
> +input:
> + /* push the packets up */
>   s = splnet();
>   if_input(ifp, &ml);
>   splx(s);
>  
> +done:
>   /* clear buffer for next transaction */
>   memset(c->axen_buf, 0, sc->axen_bufsz);
>  
> @@ -1043,7 +1222,7 @@ done:
>      USBD_NO_TIMEOUT, axen_rxeof);
>   usbd_transfer(xfer);
>  
> - DPRINTFN(10,("%s: %s: start rx\n", sc->axen_dev.dv_xname, __func__));
> + DPRINTFN(10,("%s: %s: end rx\n", sc->axen_dev.dv_xname, __func__));
>  }
>  
>  /*
> @@ -1076,7 +1255,8 @@ axen_txeof(struct usbd_xfer *xfer, void
>   printf("axen%d: usb error on tx: %s\n", sc->axen_unit,
>      usbd_errstr(status));
>   if (status == USBD_STALLED)
> - usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_TX]);
> + usbd_clear_endpoint_stall_async(
> +    sc->axen_ep[AXEN_ENDPT_TX]);
>   splx(s);
>   return;
>   }
> @@ -1190,6 +1370,8 @@ axen_encap(struct axen_softc *sc, struct
>   /* Transmit */
>   err = usbd_transfer(c->axen_xfer);
>   if (err != USBD_IN_PROGRESS) {
> + DPRINTFN(2,("%s: %s: usbd_transfer err = %d\n",
> +    sc->axen_dev.dv_xname,__func__, err));
>   axen_stop(sc);
>   return EIO;
>   }
> @@ -1249,21 +1431,33 @@ axen_init(void *xsc)
>   struct axen_chain *c;
>   usbd_status err;
>   int i, s;
> - uByte bval;
>   uWord wval;
>   uint16_t rxmode;
>  
> + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
> +
>   s = splnet();
>  
>   /*
>   * Cancel pending I/O and free all RX/TX buffers.
>   */
> + axen_stop(sc);
>   axen_reset(sc);
>  
> - /* XXX: ? */
> - bval = 0x01;
> + /* Set MAC address. */
> + axen_cmd(sc, AXEN_CMD_MAC_WRITE_ETHER, ETHER_ADDR_LEN,
> +    AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr);
> +
> + /* Program promiscuous mode and multicast filters. */
> + axen_iff(sc);
> +
> + /* Enable receiver, set RX mode */
>   axen_lock_mii(sc);
> - axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_UNK_28, &bval);
> + axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
> + rxmode = UGETW(wval);
> + rxmode |= AXEN_RXCTL_START;
> + USETW(wval, rxmode);
> + axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
>   axen_unlock_mii(sc);
>  
>   /* Init RX ring. */
> @@ -1280,18 +1474,6 @@ axen_init(void *xsc)
>   return;
>   }
>  
> - /* Program promiscuous mode and multicast filters. */
> - axen_iff(sc);
> -
> - /* Enable receiver, set RX mode */
> - axen_lock_mii(sc);
> - axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
> - rxmode = UGETW(wval);
> - rxmode |= AXEN_RXCTL_START;
> - USETW(wval, rxmode);
> - axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
> - axen_unlock_mii(sc);
> -
>   /* Open RX and TX pipes. */
>   err = usbd_open_pipe(sc->axen_iface, sc->axen_ed[AXEN_ENDPT_RX],
>      USBD_EXCLUSIVE_USE, &sc->axen_ep[AXEN_ENDPT_RX]);
> @@ -1396,7 +1578,7 @@ axen_watchdog(struct ifnet *ifp)
>   sc = ifp->if_softc;
>  
>   ifp->if_oerrors++;
> - printf("axen%d: watchdog timeout\n", sc->axen_unit);
> + printf("%s: watchdog timeout\n", sc->axen_dev.dv_xname);
>  
>   s = splusb();
>   c = &sc->axen_cdata.axen_tx_chain[0];
> @@ -1418,8 +1600,10 @@ axen_stop(struct axen_softc *sc)
>   usbd_status err;
>   struct ifnet *ifp;
>   int i;
> + u_int16_t ctl;
> + uWord wval;
>  
> - axen_reset(sc);
> + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
>  
>   ifp = &sc->arpcom.ac_if;
>   ifp->if_timer = 0;
> @@ -1427,6 +1611,13 @@ axen_stop(struct axen_softc *sc)
>   ifq_clr_oactive(&ifp->if_snd);
>  
>   timeout_del(&sc->axen_stat_ch);
> +
> + /* disable receive */
> + axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval);
> + ctl = UGETW(wval);
> + ctl &= ~AXEN_MEDIUM_RECV_EN;
> + USETW(wval, ctl);
> + axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
>  
>   /* Stop transfers. */
>   if (sc->axen_ep[AXEN_ENDPT_RX] != NULL) {
> Index: dev/usb/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
> --- dev/usb/if_axenreg.h 14 Sep 2016 12:41:09 -0000 1.6
> +++ dev/usb/if_axenreg.h 12 Feb 2019 18:26:48 -0000
> @@ -12,9 +12,10 @@
>  #define AXEN_PHY_ID 0x0003
>  #define AXEN_MCAST_FILTER_SIZE 8
>  /* unit: KB */
> -#define AXEN_BUFSZ_LS 8
> -#define AXEN_BUFSZ_HS 16
> -#define AXEN_BUFSZ_SS 24
> +#define AXEN_BUFSZ_LS 0x18
> +#define AXEN_BUFSZ_HS 0x16
> +#define AXEN_BUFSZ_SS 0x12
> +#define AXEN_BUFSZ_MAX AXEN_BUFSZ_LS
>  
>  #define AXEN_REV_UA1 0
>  #define AXEN_REV_UA2 1
> @@ -26,8 +27,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
> @@ -62,6 +63,10 @@
>  #define AXEN_RXHDR_L3CSUM_ERR (1U << 1)
>  #define AXEN_RXHDR_L4CSUM_ERR (1U << 0)
>  
> +#define AXEN_RXHDR_ERR(x) ((x) & (AXEN_RXHDR_DROP_ERR | \
> +        AXEN_RXHDR_MII_ERR | \
> +        AXEN_RXHDR_CRC_ERR))
> +
>  /* L4 packet type (3bit) */
>  #define AXEN_RXHDR_L4_TYPE_MASK 0x0000001c
>  #define AXEN_RXHDR_L4_TYPE_OFFSET 2
> @@ -70,7 +75,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
> @@ -88,10 +93,13 @@
>  #define AXEN_CMD_MAC_READ 0x1001
>  #define AXEN_CMD_MAC_WRITE 0x1101
>  
> -#define   AXEN_USB_UPLINK 0x02
> +#define   AXEN_PHYSICAL_LINK_STATUS 0x02
>  #define     AXEN_USB_FS  0x01
>  #define     AXEN_USB_HS  0x02
>  #define     AXEN_USB_SS  0x04
> +#define     AXEN_EPHY_10  0x10
> +#define     AXEN_EPHY_100  0x20
> +#define     AXEN_EPHY_1000  0x40
>  #define   AXEN_GENERAL_STATUS 0x03
>  #define     AXEN_GENERAL_STATUS_MASK  0x4
>  #define     AXEN_REV0  0x0
> @@ -149,9 +157,9 @@
>  #define     AXEN_RXCTL_STOP  0x0000
>  #define     AXEN_RXCTL_PROMISC  0x0001
>  #define     AXEN_RXCTL_ACPT_ALL_MCAST  0x0002
> -#define     AXEN_RXCTL_HA8B  0x0004
> -#define     AXEN_RXCTL_AUTOB  0x0008
> -#define     AXEN_RXCTL_ACPT_BCAST  0x0010
> +#define     AXEN_RXCTL_AUTOPAD_BNDRY  0x0004
> +#define     AXEN_RXCTL_ACPT_BCAST  0x0008
> +#define     AXEN_RXCTL_ACPT_MCAST  0x0010
>  #define     AXEN_RXCTL_ACPT_PHY_MCAST  0x0020
>  #define     AXEN_RXCTL_START  0x0080
>  #define     AXEN_RXCTL_DROPCRCERR  0x0100
> @@ -162,16 +170,27 @@
>  #define    AXEN_MEDIUM_GIGA  0x0001
>  #define    AXEN_MEDIUM_FDX  0x0002
>  #define    AXEN_MEDIUM_ALWAYS_ONE  0x0004
> -#define    AXEN_MEDIUM_EN_125MHZ  0x0008
> +#define    AXEN_MEDIUM_ALWAYS_ZERO1  0x0008
>  #define    AXEN_MEDIUM_RXFLOW_CTRL_EN  0x0010
>  #define    AXEN_MEDIUM_TXFLOW_CTRL_EN  0x0020
> +#define    AXEN_MEDIUM_JUMBOFRAME_EN  0x0040
> +#define    AXEN_MEDIUM_PAUSEFRAME_LT_ONLY_EN  0x0080
>  #define    AXEN_MEDIUM_RECV_EN  0x0100
> -#define    AXEN_MEDIUM_PS  0x0200
> -#define    AXEN_MEDIUM_JUMBO_EN  0x8040
> +#define    AXEN_MEDIUM_PORTSPEED_100  0x0200
> +#define    AXEN_MEDIUM_ALWAYS_ZERO2  0x0400
> +#define    AXEN_MEDIUM_STOP_BACKPRESSURE  0x0800
> +#define    AXEN_MEDIUM_SUPERMAC  0x1000
> +#define    AXEN_MEDIUM_ALWAYS_ZERO3  0x2000
> +#define    AXEN_MEDIUM_ALWAYS_ZERO4  0x4000
> +#define    AXEN_MEDIUM_ALWAYS_ZERO5  0x8000
> +#define    AXEN_MEDIUM_JUMBO_EN \
> + (AXEN_MEDIUM_JUMBOFRAME_EN | AXEN_MEDIUM_STOP_BACKPRESSURE)
>  #define   AXEN_PHYPWR_RSTCTL 0x26
> +#define     AXEN_PHYPWR_RSTCTL_BZ_AUTOCLEAR_DIS  0x0004
>  #define     AXEN_PHYPWR_RSTCTL_BZ  0x0010
>  #define     AXEN_PHYPWR_RSTCTL_IPRL  0x0020
>  #define     AXEN_PHYPWR_RSTCTL_AUTODETACH  0x1000
> +#define     AXEN_PHYPWR_RSTCTL_WOL_LOWPOWER  0x8000
>  
>  #define AXEN_CMD_EEPROM_READ 0x2004
>  #define    AXEN_EEPROM_STAT  0x43
> @@ -212,6 +231,20 @@
>  #define AXEN_RX_LIST_CNT 1
>  #define AXEN_TX_LIST_CNT 1
>  
> +
> +/* ---GMII--- */
> +#define AXEN_GMII_PHYPAGE 0x1e
> +#define AXEN_GMII_PHY_PAGE_SELECT 0x1f
> +#define AXEN_GMII_PHY_PGSEL_EXT  0x0007
> +#define AXEN_GMII_PHY_PGSEL_PAGE0  0x0000
> +#define AXEN_GMII_PHY_PGSEL_PAGE3  0x0003
> +#define AXEN_GMII_PHY_PGSEL_PAGE5  0x0005
> +#define AXEN_GMII_PHY_PGSEL_PAGE5  0x0005
> +
> +#define AXEN_MII_PHYADDR 0x19
> +#define AXEN_MII_PHYADDR_EEE_DIS  0x3246
> +#define AXEN_MII_PHYADDR_EEE_EN1  0x3247
> +#define AXEN_MII_PHYADDR_EEE_EN2  0x0680
>  
>  /*
>   * The interrupt endpoint is currently unused
>

Reply | Threaded
Open this post in threaded view
|

Re: patch axen(4) (WIP)

Nils Frohberg
On Mon, Feb 25, 2019 at 03:50:48PM -0300, Martin Pieuchot wrote:

> On 25/02/19(Mon) 14:52, Nils Frohberg wrote:
> > Hi,
> >
> > as mentioned previously, I'm looking into axen(4). While searching
> > for the cause of a panic (fixed since, thanks mpi@) I started to
> > rewrite parts of the driver. References were mainly the FreeBSD and
> > Linux drivers.
>
> Please try to isolate parts of your diff that fixes issues and cosmetic
> changes.  The simpler it gets the easier it is for us to review it.

Sure, I'll send separate patches.

(I cvs up'ed my src forder in order to test compile the individual
patches and found out that xhci.c,v1.91 breaks my USB devices. I'll
send a mail to bugs@ later.)

> > I didn't get around to much testing/debugging lately, therefore I
> > wanted to share the current state (diff below).
> >
> > The current state works a lot better than previously (for me). I
> > used to have a huge amount of ierrs (aprrox. 1 ierr per ipkt) and
> > often no packets would be transferred at all (or stop being transferred
> > after some time).
>
> Do you know why?  What were the problems?

I'm not 100% sure, since I did a lot of back and forth. It finally
got better once I disabled EEE and lowered the watermark levels.

> > This box hosts backups (rsync and TimeMachine), so it gets its fair
> > share of traffic. I could reduce the ierrs to ~2100 with 5d uptime,
> > and the packets keep flowing:
> >
> > $ netstat -niI axen0
> > Name    Mtu   Network     Address              Ipkts Ierrs    Opkts Oerrs Colls
> > axen0   1500  <Link>      94:c6:91:1f:85:a5 141199356  2099 112289969     0     0
> > $ uptime
> >  7:15PM  up 5 days,  9:57, 3 users, load averages: 0.11, 0.13, 0.14
> > $
> >
> > But there a still a few problems:
> >
> > 1) There are still ierrs. These happen when the rx path can't
> > allocate mbufs (cf. diff below for DPRINTF):
> > axen0: could not allocate rx mbuf (2 total, 2 remaining)
> > axen0: could not allocate rx mbuf (3 total, 3 remaining)
> > axen0: could not allocate rx mbuf (2 total, 2 remaining)
> > axen0: could not allocate rx mbuf (1 total, 1 remaining)
>
> Look at the pools when this happen, what do you see?  What is the size
> of `pkt_len' when this happen?

I added pkt_len to the DPRINTF so that I can check the relevant
pools once I see this error.

> > 2) If the adapter is plugged into a USB 3 port at boot, it will
> > return 0x42 when aked for AXEN_PHYSICAL_LINK_STATUS, ie.
> > (AXEN_EPHY_1000|AXEN_USB_HS). The adapter most often then simply
> > doesn't receive packets. If I plug in the adapter after boot is
> > complete, 0x44 is returned (AXEN_EPHY_1000|AXEN_USB_SS), as expected.
> > I'm not sure if I'm still missing something in init (probably) or
> > if this results from something higher in the stack (xhci?).
> > (Didn't test USB 2 or lower.)
>
> Do you see any difference in 'usbdevs -vv' output during the two cases?

Yes, high speed vs super speed and power draw:

# Plugged in after boot:

$ usbdevs -vv
Controller /dev/usb0:
addr 01: 8086:0000 Intel, xHCI root hub
         super speed, self powered, config 1, rev 1.00
         driver: uhub0
         port 01: 0001.02a0 power Rx.detect
         port 02: 0011.02a0 power Rx.detect
         port 03: 0000.0503 connect enabled recovery
         port 04: 0000.0503 connect enabled recovery
         port 05: 0000.02a0 power Rx.detect
         port 06: 0000.02a0 power Rx.detect
         port 07: 0000.02a0 power Rx.detect
         port 08: 0000.0103 connect enabled recovery
         port 09: 0000.02a0 power Rx.detect
         port 10: 0000.0203 connect enabled power U0
         port 11: 0000.0203 connect enabled power U0
         port 12: 0000.0203 connect enabled power U0
         port 13: 0000.02a0 power Rx.detect
         port 14: 0000.02a0 power Rx.detect
         port 15: 0000.02a0 power Rx.detect
addr 04: 0bc2:ab44 Seagate, Backup+ Hub
         high speed, self powered, config 1, rev 48.85, iSerial 01CB7236B0N6
         driver: uhub2
         port 01: 0000.0100 power
         port 02: 0000.0100 power
         port 03: 0000.0100 power
addr 05: 05e3:0610 GenesysLogic, USB2.0 Hub
         high speed, self powered, config 1, rev 92.16
         driver: uhub3
         port 01: 0000.0100 power
         port 02: 0000.0100 power
         port 03: 0000.0100 power
         port 04: 0000.0100 power
addr 06: 8087:0aa7 Intel, product 0x0aa7
         full speed, self powered, config 1, rev 0.01
         driver: ugen0
addr 07: 0bc2:ab45 Seagate, Backup+ Hub
         super speed, self powered, config 1, rev 48.85, iSerial 01CB7236B0N6
         driver: uhub4
         port 01: 0000.0203 connect enabled power U0
         port 02: 0000.02a0 power Rx.detect
         port 03: 0000.0203 connect enabled power U0
addr 08: 0bc2:ab38 Seagate, Backup+ Hub BK
         super speed, self powered, config 1, rev 1.00, iSerial NA8TMK6F
         driver: umass0
addr 09: 05e3:0612 GenesysLogic, USB3.0 Hub
         super speed, self powered, config 1, rev 92.16
         driver: uhub5
         port 01: 0000.02a0 power Rx.detect
         port 02: 0000.02a0 power Rx.detect
         port 03: 0000.02a0 power Rx.detect
         port 04: 0000.0203 connect enabled power U0
addr 10: 1058:25a2 Western Digital, Elements 25A2
         super speed, power 224 mA, config 1, rev 10.14, iSerial 575854314131373838593538
         driver: umass1
addr 11: 0b95:1790 ASIX Elec. Corp., AX88179
         super speed, power 124 mA, config 1, rev 1.00, iSerial 0000000000013F
         driver: axen0
addr 12: 2109:0701 Intenso, External USB 3.0
         super speed, self powered, config 1, rev 3.07, iSerial 20130301005083
         driver: umass2
$

# Plugged in before boot:

$ usbdevs -vv
Controller /dev/usb0:
addr 01: 8086:0000 Intel, xHCI root hub
         super speed, self powered, config 1, rev 1.00
         driver: uhub0
         port 01: 0001.02a0 power Rx.detect
         port 02: 0000.0503 connect enabled recovery
         port 03: 0000.0503 connect enabled recovery
         port 04: 0000.0503 connect enabled recovery
         port 05: 0000.02a0 power Rx.detect
         port 06: 0000.02a0 power Rx.detect
         port 07: 0000.02a0 power Rx.detect
         port 08: 0000.0103 connect enabled recovery
         port 09: 0000.02a0 power Rx.detect
         port 10: 0000.02a0 power Rx.detect
         port 11: 0000.0203 connect enabled power U0
         port 12: 0000.0203 connect enabled power U0
         port 13: 0000.02a0 power Rx.detect
         port 14: 0000.02a0 power Rx.detect
         port 15: 0000.02a0 power Rx.detect
addr 04: 0b95:1790 ASIX Elec. Corp., AX88179
         high speed, power 248 mA, config 1, rev 1.00, iSerial 0000000000013F
         driver: axen0
addr 05: 0bc2:ab44 Seagate, Backup+ Hub
         high speed, self powered, config 1, rev 48.85, iSerial 01CB7236B0N6
         driver: uhub2
         port 01: 0000.0100 power
         port 02: 0000.0100 power
         port 03: 0000.0100 power
addr 06: 05e3:0610 GenesysLogic, USB2.0 Hub
         high speed, self powered, config 1, rev 92.16
         driver: uhub3
         port 01: 0000.0100 power
         port 02: 0000.0100 power
         port 03: 0000.0100 power
         port 04: 0000.0100 power
addr 07: 8087:0aa7 Intel, product 0x0aa7
         full speed, self powered, config 1, rev 0.01
         driver: ugen0
addr 08: 0bc2:ab45 Seagate, Backup+ Hub
         super speed, self powered, config 1, rev 48.85, iSerial 01CB7236B0N6
         driver: uhub4
         port 01: 0000.0203 connect enabled power U0
         port 02: 0000.02a0 power Rx.detect
         port 03: 0000.02b0 power Rx.detect
addr 09: 0bc2:ab38 Seagate, Backup+ Hub BK
         super speed, self powered, config 1, rev 1.00, iSerial NA8TMK6F
         driver: umass0
addr 10: 05e3:0612 GenesysLogic, USB3.0 Hub
         super speed, self powered, config 1, rev 92.16
         driver: uhub5
         port 01: 0000.02a0 power Rx.detect
         port 02: 0000.02a0 power Rx.detect
         port 03: 0000.02a0 power Rx.detect
         port 04: 0000.0203 connect enabled power U0
addr 11: 1058:25a2 Western Digital, Elements 25A2
         super speed, power 224 mA, config 1, rev 10.14, iSerial 575854314131373838593538
         driver: umass1
$

Here's a dmesg:

OpenBSD 6.4-current (AXEN_DEBUG) #58: Tue Feb 26 13:42:44 CET 2019
    [hidden email]:/usr/src/sys/arch/amd64/compile/AXEN_DEBUG
real mem = 8415174656 (8025MB)
avail mem = 8150171648 (7772MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 3.0 @ 0x79a9a000 (51 entries)
bios0: vendor Intel Corp. version "AYAPLCEL.86A.0056.2018.0926.1100" date 09/26/2018
bios0: Intel Corporation NUC6CAYH
acpi0 at bios0: rev 2
acpi0: sleep states S0 S3 S4 S5
acpi0: tables DSDT FACP FPDT FIDT MCFG DBG2 DBGP HPET LPIT APIC NPKT PRAM WSMT SSDT SSDT SSDT SSDT SSDT SSDT SSDT UEFI BGRT TPM2 DMAR WDAT NHLT
acpi0: wakeup devices SIO1(S3) HDAS(S3) XHC_(S4) XDCI(S4) BRCM(S0) PXSX(S4) RP01(S4) PXSX(S4) RP02(S4) PXSX(S4) RP03(S4) PXSX(S4) RP04(S4) PXSX(S4) RP05(S4) PXSX(S4) [...]
acpitimer0 at acpi0: 3579545 Hz, 32 bits
acpimcfg0 at acpi0
acpimcfg0: addr 0xe0000000, bus 0-255
acpihpet0 at acpi0: 19200000 Hz
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Celeron(R) CPU J3455 @ 1.50GHz, 1496.67 MHz, 06-5c-09
cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,FSGSBASE,SMEP,ERMS,MPX,RDSEED,SMAP,CLFLUSHOPT,PT,SHA,IBRS,IBPB,STIBP,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES
cpu0: 1MB 64b/line 16-way L2 cache
cpu0: smt 0, core 0, package 0
mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges
cpu0: apic clock running at 19MHz
cpu0: mwait min=64, max=64, C-substates=0.2.0.2.4.2.1.1, IBE
cpu1 at mainbus0: apid 2 (application processor)
cpu1: Intel(R) Celeron(R) CPU J3455 @ 1.50GHz, 1496.55 MHz, 06-5c-09
cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,FSGSBASE,SMEP,ERMS,MPX,RDSEED,SMAP,CLFLUSHOPT,PT,SHA,IBRS,IBPB,STIBP,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES
cpu1: 1MB 64b/line 16-way L2 cache
cpu1: smt 0, core 1, package 0
cpu2 at mainbus0: apid 4 (application processor)
cpu2: Intel(R) Celeron(R) CPU J3455 @ 1.50GHz, 1496.55 MHz, 06-5c-09
cpu2: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,FSGSBASE,SMEP,ERMS,MPX,RDSEED,SMAP,CLFLUSHOPT,PT,SHA,IBRS,IBPB,STIBP,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES
cpu2: 1MB 64b/line 16-way L2 cache
cpu2: smt 0, core 2, package 0
cpu3 at mainbus0: apid 6 (application processor)
cpu3: Intel(R) Celeron(R) CPU J3455 @ 1.50GHz, 1496.55 MHz, 06-5c-09
cpu3: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,FSGSBASE,SMEP,ERMS,MPX,RDSEED,SMAP,CLFLUSHOPT,PT,SHA,IBRS,IBPB,STIBP,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES
cpu3: 1MB 64b/line 16-way L2 cache
cpu3: smt 0, core 3, package 0
ioapic0 at mainbus0: apid 1 pa 0xfec00000, version 20, 120 pins
acpiprt0 at acpi0: bus 0 (PCI0)
acpiprt1 at acpi0: bus -1 (RP01)
acpiprt2 at acpi0: bus -1 (RP02)
acpiprt3 at acpi0: bus 1 (RP03)
acpiprt4 at acpi0: bus 2 (RP04)
acpiprt5 at acpi0: bus 3 (RP05)
acpiprt6 at acpi0: bus -1 (RP06)
acpiec0 at acpi0
acpicpu0 at acpi0: C1(@1 halt!), PSS
acpicpu1 at acpi0: C1(@1 halt!), PSS
acpicpu2 at acpi0: C1(@1 halt!), PSS
acpicpu3 at acpi0: C1(@1 halt!), PSS
acpipwrres0 at acpi0: FN00, resource for FAN0
acpitz0 at acpi0: critical temperature is 100 degC
acpipci0 at acpi0 PCI0: 0x00000000 0x00000011 0x00000001
acpicmos0 at acpi0
acpibtn0 at acpi0: PWRB
acpibtn1 at acpi0: SLPB
"INT3452" at acpi0 not configured
"INT3452" at acpi0 not configured
"INT3452" at acpi0 not configured
"INT3452" at acpi0 not configured
"INT33A1" at acpi0 not configured
"MSFT0101" at acpi0 not configured
"PNP0C0B" at acpi0 not configured
"PNP0C14" at acpi0 not configured
acpivideo0 at acpi0: GFX0
acpivout0 at acpivideo0: DD1F
cpu0: Enhanced SpeedStep 1496 MHz: speeds: 1501, 1500, 1400, 1300, 1200, 1100, 1000, 900, 800 MHz
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel Apollo Lake Host" rev 0x0b
inteldrm0 at pci0 dev 2 function 0 "Intel HD Graphics 500" rev 0x0b
drm0 at inteldrm0
inteldrm0: msi
error: [drm:pid0:i915_firmware_load_error_print] *ERROR* failed to load firmware i915/bxt_dmc_ver1.bin (-22)
error: [drm:pid0:i915_gem_init_hw] *ERROR* Failed to initialize GuC, error -8 (ignored)
inteldrm0: 1680x1050, 32bpp
wsdisplay0 at inteldrm0 mux 1: console (std, vt100 emulation)
wsdisplay0: screen 1-5 added (std, vt100 emulation)
azalia0 at pci0 dev 14 function 0 "Intel Apollo Lake HD Audio" rev 0x0b: msi
azalia0: codecs: Realtek/0x0283, Intel/0x280a, using Realtek/0x0283
audio0 at azalia0
"Intel Apollo Lake TXE" rev 0x0b at pci0 dev 15 function 0 not configured
ahci0 at pci0 dev 18 function 0 "Intel Apollo Lake AHCI" rev 0x0b: msi, AHCI 1.3.1
ahci0: port 0: 6.0Gb/s
ahci0: PHY offline on port 1
scsibus1 at ahci0: 32 targets
sd0 at scsibus1 targ 0 lun 0: <ATA, KINGSTON SA400S3, SBFK> SCSI3 0/direct fixed naa.50026b7682433dc5
sd0: 114473MB, 512 bytes/sector, 234441648 sectors, thin
ppb0 at pci0 dev 19 function 0 "Intel Apollo Lake PCIE" rev 0xfb: msi
pci1 at ppb0 bus 1
rtsx0 at pci1 dev 0 function 0 "Realtek RTS5229 Card Reader" rev 0x01: msi
sdmmc0 at rtsx0: 4-bit, dma
ppb1 at pci0 dev 19 function 1 "Intel Apollo Lake PCIE" rev 0xfb: msi
pci2 at ppb1 bus 2
iwm0 at pci2 dev 0 function 0 "Intel Dual Band Wireless-AC 3168" rev 0x10, msi
ppb2 at pci0 dev 19 function 2 "Intel Apollo Lake PCIE" rev 0xfb: msi
pci3 at ppb2 bus 3
re0 at pci3 dev 0 function 0 "Realtek 8168" rev 0x15: RTL8168H/8111H (0x5400), msi, address 94:c6:91:1f:85:a5
rgephy0 at re0 phy 7: RTL8251 PHY, rev. 0
xhci0 at pci0 dev 21 function 0 "Intel Apollo Lake xHCI" rev 0x0b: msi, xHCI 1.0
usb0 at xhci0: USB revision 3.0
uhub0 at usb0 configuration 1 interface 0 "Intel xHCI root hub" rev 3.00/1.00 addr 1
"Intel Apollo Lake I2C" rev 0x0b at pci0 dev 22 function 0 not configured
"Intel Apollo Lake HSUART" rev 0x0b at pci0 dev 24 function 0 not configured
"Intel Apollo Lake SPI" rev 0x0b at pci0 dev 25 function 0 not configured
"Intel Apollo Lake SPI" rev 0x0b at pci0 dev 25 function 1 not configured
"Intel Apollo Lake SPI" rev 0x0b at pci0 dev 25 function 2 not configured
pcib0 at pci0 dev 31 function 0 "Intel Apollo Lake LPC" rev 0x0b
ichiic0 at pci0 dev 31 function 1 "Intel Apollo Lake SMBus" rev 0x0b: polling
iic0 at ichiic0
spdmem0 at iic0 addr 0x50: 4GB DDR3 SDRAM PC3-14200 SO-DIMM
spdmem1 at iic0 addr 0x52: 4GB DDR3 SDRAM PC3-14200 SO-DIMM
isa0 at pcib0
isadma0 at isa0
fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com0: probed fifo depth: 0 bytes
pckbc0 at isa0 port 0x60/5 irq 1 irq 12
pckbd0 at pckbc0 (kbd slot)
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
vmm0 at mainbus0: VMX/EPT
efifb at mainbus0 not configured
fdc0: drive 0: unknown device type 0xf0
uhub1 at uhub0 port 1 configuration 1 interface 0 "Mitsumi Electric Hub in Apple Extended USB Keyboard" rev 1.10/4.20 addr 2
uhidev0 at uhub1 port 3 configuration 1 interface 0 "Mitsumi Electric Apple Extended USB Keyboard" rev 1.10/4.20 addr 3
uhidev0: iclass 3/1
ukbd0 at uhidev0: 8 variable keys, 6 key codes, country code 13
wskbd1 at ukbd0 mux 1
wskbd1: connecting to wsdisplay0
uhidev1 at uhub1 port 3 configuration 1 interface 1 "Mitsumi Electric Apple Extended USB Keyboard" rev 1.10/4.20 addr 3
uhidev1: iclass 3/0, 3 report ids
uhid0 at uhidev1 reportid 2: input=1, output=0, feature=0
uhid1 at uhidev1 reportid 3: input=3, output=0, feature=0
fdc0: drive 1: unknown device type 0xd0
axen0 at uhub0 port 2 configuration 1 interface 0 "ASIX Elec. Corp. AX88179" rev 2.10/1.00 addr 4
axen0: AX88179, address 94:c6:91:1f:85:a5
rgephy1 at axen0 phy 3: RTL8169S/8110S/8211 PHY, rev. 5
uhub2 at uhub0 port 3 configuration 1 interface 0 "Seagate Backup+ Hub" rev 2.10/48.85 addr 5
uhub3 at uhub0 port 4 configuration 1 interface 0 "GenesysLogic USB2.0 Hub" rev 2.10/92.16 addr 6
ugen0 at uhub0 port 8 "Intel product 0x0aa7" rev 2.00/0.01 addr 7
uhub4 at uhub0 port 11 configuration 1 interface 0 "Seagate Backup+ Hub" rev 3.00/48.85 addr 8
umass0 at uhub4 port 1 configuration 1 interface 0 "Seagate Backup+ Hub BK" rev 3.10/1.00 addr 9
umass0: using SCSI over Bulk-Only
scsibus2 at umass0: 2 targets, initiator 0
sd1 at scsibus2 targ 1 lun 0: <Seagate, Backup+ Hub BK, D781> SCSI4 0/direct fixed
sd1: 7630885MB, 512 bytes/sector, 15628053167 sectors
uhub5 at uhub0 port 12 configuration 1 interface 0 "GenesysLogic USB3.0 Hub" rev 3.00/92.16 addr 10
umass1 at uhub5 port 4 configuration 1 interface 0 "Western Digital Elements 25A2" rev 3.00/10.14 addr 11
umass1: using SCSI over Bulk-Only
scsibus3 at umass1: 2 targets, initiator 0
sd2 at scsibus3 targ 1 lun 0: <WD, Elements 25A2, 1014> SCSI4 0/direct fixed serial.105825a2373838593538
sd2: 1907697MB, 512 bytes/sector, 3906963456 sectors
vscsi0 at root
scsibus4 at vscsi0: 256 targets
softraid0 at root
scsibus5 at softraid0: 256 targets
sd3 at scsibus5 targ 1 lun 0: <OPENBSD, SR CRYPTO, 006> SCSI2 0/direct fixed
sd3: 107519MB, 512 bytes/sector, 220200432 sectors
root on sd3a (b8ec0b353d2db63d.a) swap on sd3b dump on sd3b
iwm0: hw rev 0x220, fw ver 22.361476.0, address 0c:54:15:d0:a3:95
wskbd1: disconnecting from wsdisplay0
wskbd1 detached
ukbd0 detached
uhidev0 detached
uhid0 detached
uhid1 detached
uhidev1 detached
uhidev0 at uhub1 port 3 configuration 1 interface 0 "Mitsumi Electric Apple Extended USB Keyboard" rev 1.10/4.20 addr 3
uhidev0: iclass 3/1
ukbd0 at uhidev0: 8 variable keys, 6 key codes, country code 13
wskbd1 at ukbd0: console keyboard, using wsdisplay0
uhidev1 at uhub1 port 3 configuration 1 interface 1 "Mitsumi Electric Apple Extended USB Keyboard" rev 1.10/4.20 addr 3
uhidev1: iclass 3/0, 3 report ids
uhid0 at uhidev1 reportid 2: input=1, output=0, feature=0
uhid1 at uhidev1 reportid 3: input=3, output=0, feature=0
sd4 at scsibus5 targ 2 lun 0: <OPENBSD, SR CRYPTO, 006> SCSI2 0/direct fixed
sd4: 1907694MB, 512 bytes/sector, 3906959213 sectors
sd5 at scsibus5 targ 3 lun 0: <OPENBSD, SR CRYPTO, 006> SCSI2 0/direct fixed
sd5: 7630885MB, 512 bytes/sector, 15628052512 sectors

Reply | Threaded
Open this post in threaded view
|

[axen 1/7] rx path

Nils Frohberg
In reply to this post by Nils Frohberg
adjust rx path:
- do not set RXCTL_IPE, thus eliminating padding bytes on each
  packet
- switch from MGETHDR/MCLGET/memcpy to m_getdev
- improve buffer length and packet checks

---
 dev/usb/if_axen.c    | 172 +++++++++++++++++++++++--------------------
 dev/usb/if_axenreg.h |   4 +
 2 files changed, 95 insertions(+), 81 deletions(-)

diff --git a/dev/usb/if_axen.c b/dev/usb/if_axen.c
index 190bf2e..909c04f 100644
--- a/dev/usb/if_axen.c
+++ b/dev/usb/if_axen.c
@@ -97,7 +97,6 @@ const struct cfattach axen_ca = {
 
 int axen_tx_list_init(struct axen_softc *);
 int axen_rx_list_init(struct axen_softc *);
-struct mbuf *axen_newbuf(void);
 int axen_encap(struct axen_softc *, struct mbuf *, int);
 void axen_rxeof(struct usbd_xfer *, void *, usbd_status);
 void axen_txeof(struct usbd_xfer *, void *, usbd_status);
@@ -535,7 +534,7 @@ axen_ax88179_init(struct axen_softc *sc)
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val);
 
  /* Set RX control register */
- ctl = AXEN_RXCTL_IPE | AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_AUTOB;
+ ctl = AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_AUTOB;
  ctl |= AXEN_RXCTL_ACPT_PHY_MCAST | AXEN_RXCTL_ACPT_ALL_MCAST;
  ctl |= AXEN_RXCTL_START;
  USETW(wval, ctl);
@@ -787,27 +786,6 @@ axen_detach(struct device *self, int flags)
  return 0;
 }
 
-struct mbuf *
-axen_newbuf(void)
-{
- struct mbuf *m;
-
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return NULL;
-
- MCLGET(m, M_DONTWAIT);
- if (!(m->m_flags & M_EXT)) {
- m_freem(m);
- return NULL;
- }
-
- m->m_len = m->m_pkthdr.len = MCLBYTES;
- m_adj(m, ETHER_ALIGN);
-
- return m;
-}
-
 int
 axen_rx_list_init(struct axen_softc *sc)
 {
@@ -885,11 +863,13 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
  struct mbuf *m;
  u_int32_t total_len;
  u_int32_t rx_hdr, pkt_hdr;
- u_int32_t *hdr_p;
+ u_int32_t *hdr_p, *pkt_end, *hdr_end;
  u_int16_t hdr_offset, pkt_count;
  size_t pkt_len;
- size_t temp;
  int s;
+#ifdef AXEN_DEBUG
+ u_int16_t total_pkt_count;
+#endif
 
  DPRINTFN(10,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
 
@@ -913,56 +893,72 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
 
  usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
 
- if (total_len < sizeof(pkt_hdr)) {
+ if (total_len < sizeof(rx_hdr)) {
+ printf("%s: rxeof: too short transfer (len %u)\n",
+    sc->axen_dev.dv_xname, total_len);
+ ifp->if_ierrors++;
+ goto done;
+ }
+
+ if (total_len > sc->axen_bufsz) {
+ printf("%s: rxeof: too large transfer (len %u)\n",
+    sc->axen_dev.dv_xname, total_len);
  ifp->if_ierrors++;
  goto done;
  }
 
- /*
- * buffer map
- * [packet #0]...[packet #n][pkt hdr#0]..[pkt hdr#n][recv_hdr]
- * each packet has 0xeeee as psuedo header..
+ /*
+ * <--------------------- total_len -------------------->
+ * [pkt #0]...[pkt #n][pkt_hdr #0]...[pkt_hdr #n][rx_hdr]
+ * ^buf               ^pkt_end                   ^hdr_end
+ *
+ * Each RX frame is aligned on 8 bytes boundary. If RXCTL_IPE
+ * bit is set in MAC_RXCTL register, there would be 2
+ * padding bytes and 6 dummy bytes(as the padding also should
+ * be aligned on 8 bytes boundary) for each RX frame to align
+ * IP header on 32bits boundary. We don't set RXCTL_IPE bit
+ * of MAC_RXCTL register, so there should be no padding bytes
+ * which simplifies RX logic a lot.
  */
- hdr_p = (u_int32_t *)(buf + total_len - sizeof(u_int32_t));
- rx_hdr = letoh32(*hdr_p);
+
+ hdr_end = (u_int32_t *)(buf + total_len - sizeof(rx_hdr));
+ rx_hdr = le32toh(*hdr_end);
  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;
- }
+#ifdef AXEN_DEBUG
+ total_pkt_count = pkt_count;
+#endif
 
  /* sanity check */
- if (hdr_offset > total_len) {
+ if (hdr_offset > total_len - sizeof(rx_hdr)) {
  ifp->if_ierrors++;
  goto done;
  }
 
  /* point first packet header */
- hdr_p = (u_int32_t*)(buf + hdr_offset);
-
- /*
- * ax88179 will pack multiple ip packet to a USB transaction.
- * process all of packets in the buffer
- */
+ hdr_p = pkt_end = (u_int32_t *)(buf + hdr_offset);
 
-#if 1 /* XXX: paranoiac check. need to remove later */
-#define AXEN_MAX_PACKED_PACKET 200
+#ifdef AXEN_DEBUG
+#define AXEN_MAX_PACKED_PACKET 200
  if (pkt_count > AXEN_MAX_PACKED_PACKET) {
  DPRINTF(("Too many packets (%d) in a transaction, discard.\n",
     pkt_count));
+ ifp->if_ierrors += pkt_count;
  goto done;
  }
 #endif
-
- do {
- if ((buf[0] != 0xee) || (buf[1] != 0xee)){
- printf("%s: invalid buffer(pkt#%d), continue\n",
-    sc->axen_dev.dv_xname, pkt_count);
-     ifp->if_ierrors += pkt_count;
- goto done;
+ /*
+ * ax88179 will pack multiple ip packet to a USB transaction.
+ * process all of packets in the buffer
+ */
+ while(pkt_count--) {
+ /* verify the header offset */
+ if (hdr_p >= hdr_end) {
+ DPRINTF(("%s: %s: end of packet headers(pkt#%d)\n",
+    sc->axen_dev.dv_xname,__func__,pkt_count));
+ ifp->if_ierrors += pkt_count + 1;
+ goto input;
  }
 
  pkt_hdr = letoh32(*hdr_p);
@@ -971,24 +967,36 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
  DPRINTFN(10,("rxeof: packet#%d, pkt_hdr 0x%08x, pkt_len %zu\n",
    pkt_count, pkt_hdr, pkt_len));
 
- 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));
- goto nextpkt;
+ /* verify the data length */
+ if ((void *)buf + pkt_len > (void *)hdr_p) {
+ DPRINTF(("%s: %s: end of packet data(pkt#%d)\n",
+    sc->axen_dev.dv_xname,__func__,pkt_count));
+ ifp->if_ierrors += pkt_count + 1;
+ goto input;
  }
 
- /* process each packet */
- /* allocate mbuf */
- m = axen_newbuf();
- if (m == NULL) {
+ 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;
  }
 
- /* skip pseudo header (2byte) and trailer padding (4Byte) */
- m->m_pkthdr.len = m->m_len = pkt_len - 6;
+ if (AXEN_RXHDR_ERR(pkt_hdr)) {
+#ifdef AXEN_DEBUG
+ DPRINTFN(7,("%s: %s: err(pkt#%d) pkt_hdr 0x%08x,",
+    sc->axen_dev.dv_xname,__func__,pkt_count,pkt_hdr));
+ if (pkt_hdr & AXEN_RXHDR_DROP_ERR)
+ DPRINTFN(7,(" drop"));
+ if (pkt_hdr & AXEN_RXHDR_MII_ERR)
+ DPRINTFN(7,(" mii"));
+ if (pkt_hdr & AXEN_RXHDR_CRC_ERR)
+ DPRINTFN(7,(" crc"));
+ DPRINTFN(7,("\n"));
+#endif
+ ifp->if_ierrors++;
+ goto nextpkt;
+ }
 
 #ifdef AXEN_TOE
  /* cheksum err */
@@ -1000,18 +1008,21 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
  } else {
  m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
  }
-
- int l4_type;
- l4_type = (pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >>
-    AXEN_RXHDR_L4_TYPE_OFFSET;
-
- 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;
 #endif
 
- memcpy(mtod(m, char *), buf + 2, pkt_len - 6);
+ /* process each packet */
+ /* allocate mbuf */
+ m = m_devget(buf, pkt_len, ETHER_ALIGN);
+ if (m == NULL) {
+#ifdef AXEN_DEBUG
+ DPRINTF(("%s: could not allocate rx mbuf of size %zu "
+    "(%d total, %d remaining)\n",
+    sc->axen_dev.dv_xname, pkt_len,
+    total_pkt_count, pkt_count + 1));
+#endif
+ ifp->if_ierrors += pkt_count + 1;
+ goto input;
+ }
 
  ml_enqueue(&ml, m);
 
@@ -1021,18 +1032,17 @@ 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 += (pkt_len + 7) & 0xfff8;
  hdr_p++;
- pkt_count--;
- } while( pkt_count > 0);
+ }
 
-done:
- /* push the packet up */
+input:
+ /* push the packets up */
  s = splnet();
  if_input(ifp, &ml);
  splx(s);
 
+done:
  /* clear buffer for next transaction */
  memset(c->axen_buf, 0, sc->axen_bufsz);
 
diff --git a/dev/usb/if_axenreg.h b/dev/usb/if_axenreg.h
index 8de2c6d..bbfb035 100644
--- a/dev/usb/if_axenreg.h
+++ b/dev/usb/if_axenreg.h
@@ -62,6 +62,10 @@
 #define AXEN_RXHDR_L3CSUM_ERR (1U << 1)
 #define AXEN_RXHDR_L4CSUM_ERR (1U << 0)
 
+#define AXEN_RXHDR_ERR(x) ((x) & (AXEN_RXHDR_DROP_ERR | \
+        AXEN_RXHDR_MII_ERR | \
+        AXEN_RXHDR_CRC_ERR))
+
 /* L4 packet type (3bit) */
 #define AXEN_RXHDR_L4_TYPE_MASK 0x0000001c
 #define AXEN_RXHDR_L4_TYPE_OFFSET 2
--
2.20.1

Reply | Threaded
Open this post in threaded view
|

[axen 2/7] set bulk buffers according to link and bus speed

Nils Frohberg
In reply to this post by Nils Frohberg
set bulk buffers according to link and bus speed. values are taken
from freebsd and linux drivers.

while here, only enable full duplex if link is also full duplex.

---
 dev/usb/if_axen.c    | 119 +++++++++++++++++++++++--------------------
 dev/usb/if_axenreg.h |  13 +++--
 2 files changed, 72 insertions(+), 60 deletions(-)

diff --git a/dev/usb/if_axen.c b/dev/usb/if_axen.c
index 909c04f..dfdcecf 100644
--- a/dev/usb/if_axen.c
+++ b/dev/usb/if_axen.c
@@ -120,6 +120,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, AXEN_BUFSZ_SS, 0xff },
+ { 7, 0x20, 0x03, AXEN_BUFSZ_HS, 0xff },
+ { 7, 0xae, 0x07, AXEN_BUFSZ_LS, 0xff },
+ { 7, 0xcc, 0x4c, AXEN_BUFSZ_LS, 0x08 }
+};
+
 /* Get exclusive access to the MII registers */
 void
 axen_lock_mii(struct axen_softc *sc)
@@ -235,13 +242,17 @@ axen_miibus_statchg(struct device *dev)
  struct mii_data *mii = GET_MII(sc);
  struct ifnet *ifp;
  int err;
+ uint8_t link_status;
  uint16_t val;
  uWord wval;
+ struct axen_qctrl *qctrl;
+
+ axen_lock_mii(sc);
 
  ifp = GET_IFP(sc);
  if (mii == NULL || ifp == NULL ||
     (ifp->if_flags & IFF_RUNNING) == 0)
- return;
+ goto done;
 
  sc->axen_link = 0;
  if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
@@ -249,10 +260,8 @@ axen_miibus_statchg(struct device *dev)
  switch (IFM_SUBTYPE(mii->mii_media_active)) {
     case IFM_10_T:
     case IFM_100_TX:
- sc->axen_link++;
- break;
     case IFM_1000_T:
- sc->axen_link++;
+ sc->axen_link = 1;
  break;
     default:
  break;
@@ -261,36 +270,68 @@ axen_miibus_statchg(struct device *dev)
 
  /* Lost link, do nothing. */
  if (sc->axen_link == 0)
- return;
+ goto done;
 
- val = 0;
- if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
- val |= AXEN_MEDIUM_FDX;
+ err = axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_PHYSICAL_LINK_STATUS,
+    &link_status);
+ if (err)
+ goto error;
 
- val |= (AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE);
- val |= (AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN);
+ /* both freebsd and linux don't define/set AXEN_MEDIUM_ALWAYS_ONE,
+ * but 6.2.2.10 of the datasheet (p40) sets it to 1 */
+ val = AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE;
+
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
+ val |= AXEN_MEDIUM_FDX;
+ val |= AXEN_MEDIUM_TXFLOW_CTRL_EN | AXEN_MEDIUM_RXFLOW_CTRL_EN;
+ }
 
  switch (IFM_SUBTYPE(mii->mii_media_active)) {
  case IFM_1000_T:
- val |= AXEN_MEDIUM_GIGA | AXEN_MEDIUM_EN_125MHZ;
+ val |= AXEN_MEDIUM_GIGA;
+ if (link_status & AXEN_USB_SS)
+ qctrl = &axen_bulk_size[0];
+ else if (link_status & AXEN_USB_HS)
+ qctrl = &axen_bulk_size[1];
+ else
+ qctrl = &axen_bulk_size[3];
  break;
  case IFM_100_TX:
- val |= AXEN_MEDIUM_PS;
+ val |= AXEN_MEDIUM_PORTSPEED_100;
+ if (link_status & (AXEN_USB_SS | AXEN_USB_HS))
+ qctrl = &axen_bulk_size[2];
+ else
+ qctrl = &axen_bulk_size[3];
  break;
  case IFM_10_T:
- /* doesn't need to be handled */
+ qctrl = &axen_bulk_size[3];
  break;
+ default:
+ printf("%s: unknown uplink bus: 0x%02x\n",
+    sc->axen_dev.dv_xname, link_status);
+ goto error;
  }
+ /* XXX change buffer size here */
+
+ /* RX bulk configuration. */
+ err = axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL,
+    qctrl);
+ if (err)
+ goto error;
 
- DPRINTF(("axen_miibus_statchg: val=0x%x\n", val));
+ DPRINTF(("%s: %s: val=0x%x\n", sc->axen_dev.dv_xname, __func__,val));
  USETW(wval, val);
- axen_lock_mii(sc);
  err = axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
+ if (err)
+ goto error;
+
+ goto done;
+
+error:
+ printf("%s: media change failed (err: 0x%x)\n", sc->axen_dev.dv_xname,
+    err);
+done:
  axen_unlock_mii(sc);
- if (err) {
- printf("%s: media change failed\n", sc->axen_dev.dv_xname);
- return;
- }
 }
 
 /*
@@ -407,7 +448,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);
 
@@ -439,6 +479,10 @@ axen_ax88179_init(struct axen_softc *sc)
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val);
  usbd_delay_ms(sc->axen_udev, 100);
 
+ /* RX bulk configuration */
+ axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL,
+    &axen_bulk_size[0]);
+
  /* set monitor mode (disable) */
  val = AXEN_MONITOR_NONE;
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
@@ -465,41 +509,6 @@ axen_ax88179_init(struct axen_softc *sc)
     sc->axen_dev.dv_xname, ctl);
  }
 
- /* bulkin queue setting */
- axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_USB_UPLINK, &val);
- 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",
-    sc->axen_dev.dv_xname, val);
- 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,
     AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr);
diff --git a/dev/usb/if_axenreg.h b/dev/usb/if_axenreg.h
index bbfb035..336727f 100644
--- a/dev/usb/if_axenreg.h
+++ b/dev/usb/if_axenreg.h
@@ -12,9 +12,9 @@
 #define AXEN_PHY_ID 0x0003
 #define AXEN_MCAST_FILTER_SIZE 8
 /* unit: KB */
-#define AXEN_BUFSZ_LS 8
-#define AXEN_BUFSZ_HS 16
-#define AXEN_BUFSZ_SS 24
+#define AXEN_BUFSZ_LS 0x18
+#define AXEN_BUFSZ_HS 0x16
+#define AXEN_BUFSZ_SS 0x12
 
 #define AXEN_REV_UA1 0
 #define AXEN_REV_UA2 1
@@ -92,10 +92,13 @@
 #define AXEN_CMD_MAC_READ 0x1001
 #define AXEN_CMD_MAC_WRITE 0x1101
 
-#define   AXEN_USB_UPLINK 0x02
+#define   AXEN_PHYSICAL_LINK_STATUS 0x02
 #define     AXEN_USB_FS  0x01
 #define     AXEN_USB_HS  0x02
 #define     AXEN_USB_SS  0x04
+#define     AXEN_EPHY_10  0x10
+#define     AXEN_EPHY_100  0x20
+#define     AXEN_EPHY_1000  0x40
 #define   AXEN_GENERAL_STATUS 0x03
 #define     AXEN_GENERAL_STATUS_MASK  0x4
 #define     AXEN_REV0  0x0
@@ -170,7 +173,7 @@
 #define    AXEN_MEDIUM_RXFLOW_CTRL_EN  0x0010
 #define    AXEN_MEDIUM_TXFLOW_CTRL_EN  0x0020
 #define    AXEN_MEDIUM_RECV_EN  0x0100
-#define    AXEN_MEDIUM_PS  0x0200
+#define    AXEN_MEDIUM_PORTSPEED_100  0x0200
 #define    AXEN_MEDIUM_JUMBO_EN  0x8040
 #define   AXEN_PHYPWR_RSTCTL 0x26
 #define     AXEN_PHYPWR_RSTCTL_BZ  0x0010
--
2.20.1

Reply | Threaded
Open this post in threaded view
|

[axen 3/7] rebuild the filter flags from scratch

Nils Frohberg
In reply to this post by Nils Frohberg
rebuild the filter flags from scratch instead of pulling the state
from the card and setting/unsetting the necessary bits.

---
 dev/usb/if_axen.c    | 23 ++++++++++++-----------
 dev/usb/if_axenreg.h |  4 ++--
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/dev/usb/if_axen.c b/dev/usb/if_axen.c
index dfdcecf..088f40f 100644
--- a/dev/usb/if_axen.c
+++ b/dev/usb/if_axen.c
@@ -392,27 +392,27 @@ axen_iff(struct axen_softc *sc)
 
  /* Enable receiver, set RX mode */
  axen_lock_mii(sc);
- axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
- rxmode = UGETW(wval);
- rxmode &= ~(AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST |
-  AXEN_RXCTL_PROMISC);
+ rxmode = AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_START;
  ifp->if_flags &= ~IFF_ALLMULTI;
 
  /*
- * Always accept broadcast frames.
  * Always accept frames destined to our station address.
  */
- rxmode |= AXEN_RXCTL_ACPT_BCAST;
+ rxmode |= AXEN_RXCTL_ACPT_PHY_MCAST;
+ /*
+ * Accept broadcast frames iff interface has IFF_BROADCAST set.
+ */
+ if (ifp->if_flags & IFF_BROADCAST)
+ rxmode |= AXEN_RXCTL_ACPT_BCAST;
 
  if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
  ifp->if_flags |= IFF_ALLMULTI;
- rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST;
+ rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST;
  if (ifp->if_flags & IFF_PROMISC)
  rxmode |= AXEN_RXCTL_PROMISC;
  } else {
- rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST;
-
- /* now program new ones */
+ rxmode |= AXEN_RXCTL_ACPT_MCAST;
+ /* compute multicast filter array */
  ETHER_FIRST_MULTI(step, ac, enm);
  while (enm != NULL) {
  h = ether_crc32_be(enm->enm_addrlo,
@@ -424,6 +424,7 @@ axen_iff(struct axen_softc *sc)
 
  axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI,
     (void *)&hashtbl);
+
  USETW(wval, rxmode);
  axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
  axen_unlock_mii(sc);
@@ -543,7 +544,7 @@ axen_ax88179_init(struct axen_softc *sc)
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val);
 
  /* Set RX control register */
- ctl = AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_AUTOB;
+ ctl = AXEN_RXCTL_DROPCRCERR;
  ctl |= AXEN_RXCTL_ACPT_PHY_MCAST | AXEN_RXCTL_ACPT_ALL_MCAST;
  ctl |= AXEN_RXCTL_START;
  USETW(wval, ctl);
diff --git a/dev/usb/if_axenreg.h b/dev/usb/if_axenreg.h
index 336727f..766c89e 100644
--- a/dev/usb/if_axenreg.h
+++ b/dev/usb/if_axenreg.h
@@ -157,8 +157,8 @@
 #define     AXEN_RXCTL_PROMISC  0x0001
 #define     AXEN_RXCTL_ACPT_ALL_MCAST  0x0002
 #define     AXEN_RXCTL_HA8B  0x0004
-#define     AXEN_RXCTL_AUTOB  0x0008
-#define     AXEN_RXCTL_ACPT_BCAST  0x0010
+#define     AXEN_RXCTL_ACPT_BCAST  0x0008
+#define     AXEN_RXCTL_ACPT_MCAST  0x0010
 #define     AXEN_RXCTL_ACPT_PHY_MCAST  0x0020
 #define     AXEN_RXCTL_START  0x0080
 #define     AXEN_RXCTL_DROPCRCERR  0x0100
--
2.20.1

Reply | Threaded
Open this post in threaded view
|

[axen 4/7] init/stop/attach/detach

Nils Frohberg
In reply to this post by Nils Frohberg
try to align attach/detach/init/stop routines with what freebsd and
linux are doing.

one important part of this diff is disabling Energy Efficient
Ethernet (EEE) and setting the low/high watermarks. this reduces
the amount of RXHDR_DROP_ERRs, but could maybe be tweaked (improved).

---
 dev/usb/if_axen.c    | 145 +++++++++++++++++++++++++++----------------
 dev/usb/if_axenreg.h |  20 +++++-
 2 files changed, 110 insertions(+), 55 deletions(-)

diff --git a/dev/usb/if_axen.c b/dev/usb/if_axen.c
index 088f40f..817cad8 100644
--- a/dev/usb/if_axen.c
+++ b/dev/usb/if_axen.c
@@ -433,13 +433,16 @@ axen_iff(struct axen_softc *sc)
 void
 axen_reset(struct axen_softc *sc)
 {
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
+
  if (usbd_is_dying(sc->axen_udev))
  return;
-
- axen_ax88179_init(sc);
 
  /* Wait a little while for the chip to get its brains in order. */
  DELAY(1000);
+
+ axen_ax88179_init(sc);
+
  return;
 }
 
@@ -510,63 +513,65 @@ axen_ax88179_init(struct axen_softc *sc)
     sc->axen_dev.dv_xname, ctl);
  }
 
- /* Set MAC address. */
- axen_cmd(sc, AXEN_CMD_MAC_WRITE_ETHER, ETHER_ADDR_LEN,
-    AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr);
-
  /*
  * set buffer high/low watermark to pause/resume.
  * write 2byte will set high/log simultaneous with AXEN_PAUSE_HIGH.
- * XXX: what is the best value? OSX driver uses 0x3c-0x4c as LOW-HIGH
- * watermark parameters.
+ * XXX: what is the best value?
+ * - defaults (datasheet): 0x24-0x42 as LOW-HIGH watermark parameters.
+ * - OSX driver uses 0x3c-0x4c as LOW-HIGH watermark parameters.(?)
+ * - FreeBSD driver uses 0x34-0x52 as LOW-HIGH watermark parameters.
+ * - Linux driver uses 0x34-0x52 as LOW-HIGH watermark parameters.
  */
- val = 0x34;
+ val = 0x24;
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_LOW_WATERMARK, &val);
- val = 0x52;
+ val = 0x42;
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_HIGH_WATERMARK, &val);
 
  /* Set RX/TX configuration. */
- /* Offloadng enable */
 #ifdef AXEN_TOE
- val = AXEN_RXCOE_IPv4 | AXEN_RXCOE_TCPv4 | AXEN_RXCOE_UDPv4 |
-      AXEN_RXCOE_TCPv6 | AXEN_RXCOE_UDPv6;
+ /* enable offloading */
+ val = AXEN_RXCOE_IPv4 |
+      AXEN_RXCOE_TCPv4 | AXEN_RXCOE_UDPv4 | AXEN_RXCOE_ICMPv4 |
+      AXEN_RXCOE_IGMP |
+      AXEN_RXCOE_TCPv6 | AXEN_RXCOE_UDPv6 | AXEN_RXCOE_ICMPv6;
 #else
  val = AXEN_RXCOE_OFF;
 #endif
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_RX_COE, &val);
 
 #ifdef AXEN_TOE
- val = AXEN_TXCOE_IPv4 | AXEN_TXCOE_TCPv4 | AXEN_TXCOE_UDPv4 |
-      AXEN_TXCOE_TCPv6 | AXEN_TXCOE_UDPv6;
+ val = AXEN_TXCOE_IPv4 |
+      AXEN_TXCOE_TCPv4 | AXEN_TXCOE_UDPv4 |AXEN_TXCOE_ICMPv4 |
+      AXEN_TXCOE_IGMP |
+      AXEN_TXCOE_TCPv6 | AXEN_TXCOE_UDPv6 | AXEN_TXCOE_ICMPv6;
 #else
  val = AXEN_TXCOE_OFF;
 #endif
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val);
 
- /* Set RX control register */
- ctl = AXEN_RXCTL_DROPCRCERR;
- ctl |= AXEN_RXCTL_ACPT_PHY_MCAST | AXEN_RXCTL_ACPT_ALL_MCAST;
- ctl |= AXEN_RXCTL_START;
- USETW(wval, ctl);
- axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
-
- /* set monitor mode (enable) */
- val = AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP;
+ /* set monitor mode (XXX enable) */
+ /* AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP; */
+ val = 0;
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
+#ifdef AXEN_DEBUG
  axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_MONITOR_MODE, &val);
  DPRINTF(("axen: Monitor mode = 0x%02x\n", val));
+#endif
 
  /* set medium type */
- ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX | AXEN_MEDIUM_ALWAYS_ONE |
-      AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN;
- ctl |= AXEN_MEDIUM_RECV_EN;
+ ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX |
+      AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN |
+      AXEN_MEDIUM_RECV_EN;
  USETW(wval, ctl);
  DPRINTF(("axen: set to medium mode: 0x%04x\n", UGETW(wval)));
  axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
- usbd_delay_ms(sc->axen_udev, 100);
 
+#ifdef AXEN_DEBUG
+ usbd_delay_ms(sc->axen_udev, 100);
  axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval);
  DPRINTF(("axen: current medium mode: 0x%04x\n", UGETW(wval)));
+#endif
+
  axen_unlock_mii(sc);
 
 #if 0 /* XXX: TBD.... */
@@ -580,7 +585,15 @@ axen_ax88179_init(struct axen_softc *sc)
     0x002c);
 #endif
 
-#if 1 /* XXX: phy hack ? */
+ /* disable eee */
+ axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
+    AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE3);
+ axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
+    AXEN_MII_PHYADDR, 0x3246);
+ axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
+    AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE0);
+
+#if 0 /* XXX: phy hack ? */
  axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x1F, 0x0005);
  axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x0C, 0x0000);
  val = axen_miibus_readreg(&sc->axen_dev, sc->axen_phyno, 0x0001);
@@ -631,16 +644,17 @@ axen_attach(struct device *parent, struct device *self, void *aux)
 
  id = usbd_get_interface_descriptor(sc->axen_iface);
 
- /* decide on what our bufsize will be */
+ /*
+ * our bufsize is determined by the usb speed and link speed
+ * so set it to the biggest buffer (slowest speed) available
+ * this will be updated once the link state changes
+ */
  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;
+ /* linux adds 2 to the buffer size (why?) */
+ sc->axen_bufsz = (AXEN_BUFSZ_MAX + 2) * 1024;
  break;
  default:
  printf("%s: not supported usb bus type", sc->axen_dev.dv_xname);
@@ -742,6 +756,8 @@ axen_detach(struct device *self, int flags)
  struct axen_softc *sc = (struct axen_softc *)self;
  int s;
  struct ifnet *ifp = GET_IFP(sc);
+ uWord wval;
+ u_int16_t ctl;
 
  DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
 
@@ -769,9 +785,26 @@ axen_detach(struct device *self, int flags)
  usb_detach_wait(&sc->axen_dev);
  }
 
- if (ifp->if_flags & IFF_RUNNING)
+ if (ifp->if_flags & IFF_RUNNING) {
  axen_stop(sc);
 
+ /* force bulk-in to return a zero-length USB packet */
+ axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_PHYPWR_RSTCTL, &wval);
+ ctl = UGETW(wval);
+ ctl |= AXEN_PHYPWR_RSTCTL_BZ | AXEN_PHYPWR_RSTCTL_IPRL;
+ ctl &= ~AXEN_PHYPWR_RSTCTL_BZ_AUTOCLEAR_DIS;
+ USETW(wval, ctl);
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval);
+
+ /* set clock to zero */
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, 0);
+
+ /* disable MAC */
+ ctl = AXEN_RXCTL_STOP;
+ USETW(wval, ctl);
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
+ }
+
  mii_detach(&sc->axen_mii, MII_PHY_ANY, MII_OFFSET_ANY);
  ifmedia_delete_instance(&sc->axen_mii.mii_media, IFM_INST_ANY);
  if (ifp->if_softc != NULL) {
@@ -1269,7 +1302,6 @@ axen_init(void *xsc)
  struct axen_chain *c;
  usbd_status err;
  int i, s;
- uByte bval;
  uWord wval;
  uint16_t rxmode;
 
@@ -1278,12 +1310,23 @@ axen_init(void *xsc)
  /*
  * Cancel pending I/O and free all RX/TX buffers.
  */
+ axen_stop(sc);
  axen_reset(sc);
 
- /* XXX: ? */
- bval = 0x01;
+ /* Set MAC address. */
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE_ETHER, ETHER_ADDR_LEN,
+    AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr);
+
+ /* Program promiscuous mode and multicast filters. */
+ axen_iff(sc);
+
+ /* Enable receiver, set RX mode */
  axen_lock_mii(sc);
- axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_UNK_28, &bval);
+ axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
+ rxmode = UGETW(wval);
+ rxmode |= AXEN_RXCTL_START;
+ USETW(wval, rxmode);
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
  axen_unlock_mii(sc);
 
  /* Init RX ring. */
@@ -1300,18 +1343,6 @@ axen_init(void *xsc)
  return;
  }
 
- /* Program promiscuous mode and multicast filters. */
- axen_iff(sc);
-
- /* Enable receiver, set RX mode */
- axen_lock_mii(sc);
- axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
- rxmode = UGETW(wval);
- rxmode |= AXEN_RXCTL_START;
- USETW(wval, rxmode);
- axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
- axen_unlock_mii(sc);
-
  /* Open RX and TX pipes. */
  err = usbd_open_pipe(sc->axen_iface, sc->axen_ed[AXEN_ENDPT_RX],
     USBD_EXCLUSIVE_USE, &sc->axen_ep[AXEN_ENDPT_RX]);
@@ -1438,8 +1469,9 @@ axen_stop(struct axen_softc *sc)
  usbd_status err;
  struct ifnet *ifp;
  int i;
+ u_int16_t ctl;
+ uWord wval;
 
- axen_reset(sc);
 
  ifp = &sc->arpcom.ac_if;
  ifp->if_timer = 0;
@@ -1448,6 +1480,13 @@ axen_stop(struct axen_softc *sc)
 
  timeout_del(&sc->axen_stat_ch);
 
+ /* disable receive */
+ axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval);
+ ctl = UGETW(wval);
+ ctl &= ~AXEN_MEDIUM_RECV_EN;
+ USETW(wval, ctl);
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
+
  /* Stop transfers. */
  if (sc->axen_ep[AXEN_ENDPT_RX] != NULL) {
  usbd_abort_pipe(sc->axen_ep[AXEN_ENDPT_RX]);
diff --git a/dev/usb/if_axenreg.h b/dev/usb/if_axenreg.h
index 766c89e..bc594a0 100644
--- a/dev/usb/if_axenreg.h
+++ b/dev/usb/if_axenreg.h
@@ -15,6 +15,7 @@
 #define AXEN_BUFSZ_LS 0x18
 #define AXEN_BUFSZ_HS 0x16
 #define AXEN_BUFSZ_SS 0x12
+#define AXEN_BUFSZ_MAX AXEN_BUFSZ_LS
 
 #define AXEN_REV_UA1 0
 #define AXEN_REV_UA2 1
@@ -129,7 +130,7 @@
 #define    AXEN_RXCOE_IPv4  0x01
 #define    AXEN_RXCOE_TCPv4  0x02
 #define    AXEN_RXCOE_UDPv4  0x04
-#define    AXEN_RXCOE_ICMP  0x08
+#define    AXEN_RXCOE_ICMPv4  0x08
 #define    AXEN_RXCOE_IGMP  0x10
 #define    AXEN_RXCOE_TCPv6  0x20
 #define    AXEN_RXCOE_UDPv6  0x40
@@ -139,7 +140,7 @@
 #define    AXEN_TXCOE_IPv4  0x01
 #define    AXEN_TXCOE_TCPv4  0x02
 #define    AXEN_TXCOE_UDPv4  0x04
-#define    AXEN_TXCOE_ICMP  0x08
+#define    AXEN_TXCOE_ICMPv4  0x08
 #define    AXEN_TXCOE_IGMP  0x10
 #define    AXEN_TXCOE_TCPv6  0x20
 #define    AXEN_TXCOE_UDPv6  0x40
@@ -176,6 +177,7 @@
 #define    AXEN_MEDIUM_PORTSPEED_100  0x0200
 #define    AXEN_MEDIUM_JUMBO_EN  0x8040
 #define   AXEN_PHYPWR_RSTCTL 0x26
+#define     AXEN_PHYPWR_RSTCTL_BZ_AUTOCLEAR_DIS  0x0004
 #define     AXEN_PHYPWR_RSTCTL_BZ  0x0010
 #define     AXEN_PHYPWR_RSTCTL_IPRL  0x0020
 #define     AXEN_PHYPWR_RSTCTL_AUTODETACH  0x1000
@@ -220,6 +222,20 @@
 #define AXEN_TX_LIST_CNT 1
 
 
+/* ---GMII--- */
+#define AXEN_GMII_PHYPAGE 0x1e
+#define AXEN_GMII_PHY_PAGE_SELECT 0x1f
+#define AXEN_GMII_PHY_PGSEL_EXT  0x0007
+#define AXEN_GMII_PHY_PGSEL_PAGE0  0x0000
+#define AXEN_GMII_PHY_PGSEL_PAGE3  0x0003
+#define AXEN_GMII_PHY_PGSEL_PAGE5  0x0005
+#define AXEN_GMII_PHY_PGSEL_PAGE5  0x0005
+
+#define AXEN_MII_PHYADDR 0x19
+#define AXEN_MII_PHYADDR_EEE_DIS  0x3246
+#define AXEN_MII_PHYADDR_EEE_EN1  0x3247
+#define AXEN_MII_PHYADDR_EEE_EN2  0x0680
+
 /*
  * The interrupt endpoint is currently unused
  * by the ASIX part.
--
2.20.1

Reply | Threaded
Open this post in threaded view
|

[axen 5/7] fix #defines and comments

Nils Frohberg
In reply to this post by Nils Frohberg
fix defines/comments for L3_TYPE and CRC errors.

---
 dev/usb/if_axenreg.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/dev/usb/if_axenreg.h b/dev/usb/if_axenreg.h
index bc594a0..e6b8355 100644
--- a/dev/usb/if_axenreg.h
+++ b/dev/usb/if_axenreg.h
@@ -27,8 +27,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
@@ -75,7 +75,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
--
2.20.1

Reply | Threaded
Open this post in threaded view
|

[axen 6/7] add more #defines (currently not used)

Nils Frohberg
In reply to this post by Nils Frohberg
add missing defines (currently unused).

---
 dev/usb/if_axenreg.h | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/dev/usb/if_axenreg.h b/dev/usb/if_axenreg.h
index e6b8355..9b4c721 100644
--- a/dev/usb/if_axenreg.h
+++ b/dev/usb/if_axenreg.h
@@ -157,7 +157,7 @@
 #define     AXEN_RXCTL_STOP  0x0000
 #define     AXEN_RXCTL_PROMISC  0x0001
 #define     AXEN_RXCTL_ACPT_ALL_MCAST  0x0002
-#define     AXEN_RXCTL_HA8B  0x0004
+#define     AXEN_RXCTL_AUTOPAD_BNDRY  0x0004
 #define     AXEN_RXCTL_ACPT_BCAST  0x0008
 #define     AXEN_RXCTL_ACPT_MCAST  0x0010
 #define     AXEN_RXCTL_ACPT_PHY_MCAST  0x0020
@@ -170,17 +170,27 @@
 #define    AXEN_MEDIUM_GIGA  0x0001
 #define    AXEN_MEDIUM_FDX  0x0002
 #define    AXEN_MEDIUM_ALWAYS_ONE  0x0004
-#define    AXEN_MEDIUM_EN_125MHZ  0x0008
+#define    AXEN_MEDIUM_ALWAYS_ZERO1  0x0008
 #define    AXEN_MEDIUM_RXFLOW_CTRL_EN  0x0010
 #define    AXEN_MEDIUM_TXFLOW_CTRL_EN  0x0020
+#define    AXEN_MEDIUM_JUMBOFRAME_EN  0x0040
+#define    AXEN_MEDIUM_PAUSEFRAME_LT_ONLY_EN  0x0080
 #define    AXEN_MEDIUM_RECV_EN  0x0100
 #define    AXEN_MEDIUM_PORTSPEED_100  0x0200
-#define    AXEN_MEDIUM_JUMBO_EN  0x8040
+#define    AXEN_MEDIUM_ALWAYS_ZERO2  0x0400
+#define    AXEN_MEDIUM_STOP_BACKPRESSURE  0x0800
+#define    AXEN_MEDIUM_SUPERMAC  0x1000
+#define    AXEN_MEDIUM_ALWAYS_ZERO3  0x2000
+#define    AXEN_MEDIUM_ALWAYS_ZERO4  0x4000
+#define    AXEN_MEDIUM_ALWAYS_ZERO5  0x8000
+#define    AXEN_MEDIUM_JUMBO_EN \
+ (AXEN_MEDIUM_JUMBOFRAME_EN | AXEN_MEDIUM_STOP_BACKPRESSURE)
 #define   AXEN_PHYPWR_RSTCTL 0x26
 #define     AXEN_PHYPWR_RSTCTL_BZ_AUTOCLEAR_DIS  0x0004
 #define     AXEN_PHYPWR_RSTCTL_BZ  0x0010
 #define     AXEN_PHYPWR_RSTCTL_IPRL  0x0020
 #define     AXEN_PHYPWR_RSTCTL_AUTODETACH  0x1000
+#define     AXEN_PHYPWR_RSTCTL_WOL_LOWPOWER  0x8000
 
 #define AXEN_CMD_EEPROM_READ 0x2004
 #define    AXEN_EEPROM_STAT  0x43
--
2.20.1

Reply | Threaded
Open this post in threaded view
|

[axen 7/7] DPRINTF and cosmetic changes

Nils Frohberg
In reply to this post by Nils Frohberg
cosmetic changes

---
 dev/usb/if_axen.c | 142 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 120 insertions(+), 22 deletions(-)

diff --git a/dev/usb/if_axen.c b/dev/usb/if_axen.c
index 817cad8..f3a71f4 100644
--- a/dev/usb/if_axen.c
+++ b/dev/usb/if_axen.c
@@ -162,7 +162,7 @@ axen_cmd(struct axen_softc *sc, int cmd, int index, int val, void *buf)
  USETW(req.wLength, AXEN_CMD_LEN(cmd));
 
  err = usbd_do_request(sc->axen_udev, &req, buf);
- DPRINTFN(5, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n",
+ DPRINTFN(15, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n",
     cmd, val, AXEN_CMD_LEN(cmd)));
 
  if (err) {
@@ -199,7 +199,7 @@ axen_miibus_readreg(struct device *dev, int phy, int reg)
  }
 
  ival = UGETW(val);
- DPRINTFN(2,("axen_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n",
+ DPRINTFN(12,("axen_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n",
     phy, reg, ival));
 
  if (reg == MII_BMSR) {
@@ -226,7 +226,7 @@ axen_miibus_writereg(struct device *dev, int phy, int reg, int val)
  axen_lock_mii(sc);
  err = axen_cmd(sc, AXEN_CMD_MII_WRITE_REG, reg, phy, &uval);
  axen_unlock_mii(sc);
- DPRINTFN(2, ("axen_miibus_writereg: phy 0x%x reg 0x%x val 0x%0x\n",
+ DPRINTFN(12, ("axen_miibus_writereg: phy 0x%x reg 0x%x val 0x%0x\n",
     phy, reg, val));
 
  if (err) {
@@ -269,13 +269,18 @@ axen_miibus_statchg(struct device *dev)
  }
 
  /* Lost link, do nothing. */
- if (sc->axen_link == 0)
+ if (sc->axen_link == 0) {
+ DPRINTF(("%s: %s: lost link\n", sc->axen_dev.dv_xname,
+    __func__));
  goto done;
+ }
 
  err = axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_PHYSICAL_LINK_STATUS,
     &link_status);
  if (err)
  goto error;
+ DPRINTF(("%s: %s: link status: 0x%x\n", sc->axen_dev.dv_xname,
+    __func__, link_status));
 
  /* both freebsd and linux don't define/set AXEN_MEDIUM_ALWAYS_ONE,
  * but 6.2.2.10 of the datasheet (p40) sets it to 1 */
@@ -283,11 +288,22 @@ axen_miibus_statchg(struct device *dev)
 
  if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
  val |= AXEN_MEDIUM_FDX;
+#if 0
+ 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;
+#else
  val |= AXEN_MEDIUM_TXFLOW_CTRL_EN | AXEN_MEDIUM_RXFLOW_CTRL_EN;
+#endif
  }
 
  switch (IFM_SUBTYPE(mii->mii_media_active)) {
  case IFM_1000_T:
+ if (!(link_status & AXEN_EPHY_1000)) {
+ printf("%s: wrong phy link (want 1000)\n",
+    sc->axen_dev.dv_xname);
+ }
  val |= AXEN_MEDIUM_GIGA;
  if (link_status & AXEN_USB_SS)
  qctrl = &axen_bulk_size[0];
@@ -297,6 +313,10 @@ axen_miibus_statchg(struct device *dev)
  qctrl = &axen_bulk_size[3];
  break;
  case IFM_100_TX:
+ if (!(link_status & AXEN_EPHY_100)) {
+ printf("%s: wrong phy link (want 100)\n",
+    sc->axen_dev.dv_xname);
+ }
  val |= AXEN_MEDIUM_PORTSPEED_100;
  if (link_status & (AXEN_USB_SS | AXEN_USB_HS))
  qctrl = &axen_bulk_size[2];
@@ -304,6 +324,10 @@ axen_miibus_statchg(struct device *dev)
  qctrl = &axen_bulk_size[3];
  break;
  case IFM_10_T:
+ if (!(link_status & AXEN_EPHY_10)) {
+ printf("%s: wrong phy link (want 10)\n",
+    sc->axen_dev.dv_xname);
+ }
  qctrl = &axen_bulk_size[3];
  break;
  default:
@@ -314,6 +338,9 @@ axen_miibus_statchg(struct device *dev)
  /* XXX change buffer size here */
 
  /* RX bulk configuration. */
+ DPRINTF(("%s: %s: qtrl bufsize = 0x%x, ifg = 0x%x\n",
+    sc->axen_dev.dv_xname, __func__,
+    qctrl->bufsize, qctrl->ifg));
  err = axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL,
     qctrl);
  if (err)
@@ -385,6 +412,8 @@ axen_iff(struct axen_softc *sc)
  u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  uWord wval;
 
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
+
  if (usbd_is_dying(sc->axen_udev))
  return;
 
@@ -422,9 +451,15 @@ axen_iff(struct axen_softc *sc)
  }
  }
 
- axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI,
+ DPRINTFN(5,("%s: %s: hashtbl: %x %x %x %x %x %x %x %x\n",
+    sc->axen_dev.dv_xname,__func__,
+    hashtbl[0], hashtbl[1], hashtbl[2], hashtbl[3],
+    hashtbl[4], hashtbl[5], hashtbl[6], hashtbl[7]));
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI,
     (void *)&hashtbl);
 
+ DPRINTFN(2,("%s: %s: rxmode: 0x%x\n",
+    sc->axen_dev.dv_xname,__func__,rxmode));
  USETW(wval, rxmode);
  axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
  axen_unlock_mii(sc);
@@ -453,6 +488,8 @@ axen_ax88179_init(struct axen_softc *sc)
  uByte val;
  u_int16_t ctl, temp;
 
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
+
  axen_lock_mii(sc);
 
  /* XXX: ? */
@@ -585,13 +622,14 @@ axen_ax88179_init(struct axen_softc *sc)
     0x002c);
 #endif
 
- /* disable eee */
+#if 1 /* disable eee */
  axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
     AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE3);
  axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
     AXEN_MII_PHYADDR, 0x3246);
  axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
     AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE0);
+#endif
 
 #if 0 /* XXX: phy hack ? */
  axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x1F, 0x0005);
@@ -628,6 +666,8 @@ axen_attach(struct device *parent, struct device *self, void *aux)
  struct ifnet *ifp;
  int i, s;
 
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
+
  sc->axen_unit = self->dv_unit; /*device_get_unit(self);*/
  sc->axen_udev = uaa->device;
  sc->axen_iface = uaa->iface;
@@ -660,7 +700,7 @@ axen_attach(struct device *parent, struct device *self, void *aux)
  printf("%s: not supported usb bus type", sc->axen_dev.dv_xname);
  return;
  }
-
+
  /* Find endpoints. */
  for (i = 0; i < id->bNumEndpoints; i++) {
  ed = usbd_interface2endpoint_descriptor(sc->axen_iface, i);
@@ -836,7 +876,8 @@ axen_rx_list_init(struct axen_softc *sc)
  struct axen_chain *c;
  int i;
 
- DPRINTF(("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
+ DPRINTF(("%s: %s: %d rx list entries of size %u\n",
+    sc->axen_dev.dv_xname, __func__,AXEN_RX_LIST_CNT,sc->axen_bufsz));
 
  cd = &sc->axen_cdata;
  for (i = 0; i < AXEN_RX_LIST_CNT; i++) {
@@ -867,7 +908,8 @@ axen_tx_list_init(struct axen_softc *sc)
  struct axen_chain *c;
  int i;
 
- DPRINTF(("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
+ DPRINTF(("%s: %s: %d tx list entries of size %u\n",
+    sc->axen_dev.dv_xname, __func__,AXEN_TX_LIST_CNT,sc->axen_bufsz));
 
  cd = &sc->axen_cdata;
  for (i = 0; i < AXEN_TX_LIST_CNT; i++) {
@@ -916,21 +958,35 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
 
  DPRINTFN(10,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
 
- if (usbd_is_dying(sc->axen_udev))
+ if (usbd_is_dying(sc->axen_udev)) {
+ DPRINTFN(15,("%s: %s: usbd_is_dying\n",
+    sc->axen_dev.dv_xname,__func__));
  return;
+ }
 
- if (!(ifp->if_flags & IFF_RUNNING))
+ if (!(ifp->if_flags & IFF_RUNNING)) {
+ DPRINTFN(15,("%s: %s: ! IFF_RUNNING\n",
+    sc->axen_dev.dv_xname,__func__));
  return;
+ }
 
  if (status != USBD_NORMAL_COMPLETION) {
+ DPRINTFN(9,("%s: %s: ! USBD_NORMAL_COMPLETION: 0x%x\n",
+    sc->axen_dev.dv_xname,__func__,status));
  if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
  return;
  if (usbd_ratecheck(&sc->axen_rx_notice)) {
  printf("%s: usb errors on rx: %s\n",
     sc->axen_dev.dv_xname, usbd_errstr(status));
  }
- if (status == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_RX]);
+ if (status == USBD_STALLED) {
+ DPRINTFN(9,("%s: %s: USBD_STALLED\n",
+    sc->axen_dev.dv_xname,__func__));
+ usbd_clear_endpoint_stall_async(
+    sc->axen_ep[AXEN_ENDPT_RX]);
+ }
+ DPRINTFN(10,("%s: %s: ! USBD_NORMAL_COMPLETION: done\n",
+    sc->axen_dev.dv_xname,__func__));
  goto done;
  }
 
@@ -975,6 +1031,10 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
 
  /* sanity check */
  if (hdr_offset > total_len - sizeof(rx_hdr)) {
+ DPRINTFN(7,("%s: %s: hdr_offset (%u) > total_len (%u)"
+    " - sizeof(pkt_hdr) (%lu)\n",
+    sc->axen_dev.dv_xname,__func__,hdr_offset,total_len,
+    sizeof(rx_hdr)));
  ifp->if_ierrors++;
  goto done;
  }
@@ -985,7 +1045,7 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
 #ifdef AXEN_DEBUG
 #define AXEN_MAX_PACKED_PACKET 200
  if (pkt_count > AXEN_MAX_PACKED_PACKET) {
- DPRINTF(("Too many packets (%d) in a transaction, discard.\n",
+ DPRINTF(("Too many packets (%d) in a transaction, discard.\n",
     pkt_count));
  ifp->if_ierrors += pkt_count;
  goto done;
@@ -995,6 +1055,8 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
  * ax88179 will pack multiple ip packet to a USB transaction.
  * process all of packets in the buffer
  */
+ DPRINTFN(10,("%s: %s: pkt_count = %u\n",
+    sc->axen_dev.dv_xname,__func__,pkt_count));
  while(pkt_count--) {
  /* verify the header offset */
  if (hdr_p >= hdr_end) {
@@ -1008,7 +1070,7 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
  pkt_len = (pkt_hdr >> 16) & 0x1fff;
 
  DPRINTFN(10,("rxeof: packet#%d, pkt_hdr 0x%08x, pkt_len %zu\n",
-   pkt_count, pkt_hdr, pkt_len));
+    pkt_count, pkt_hdr, pkt_len));
 
  /* verify the data length */
  if ((void *)buf + pkt_len > (void *)hdr_p) {
@@ -1038,18 +1100,17 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
  DPRINTFN(7,("\n"));
 #endif
  ifp->if_ierrors++;
+ /* move to next pkt header */
  goto nextpkt;
  }
 
 #ifdef AXEN_TOE
  /* cheksum err */
- if ((pkt_hdr & AXEN_RXHDR_L3CSUM_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);
  goto nextpkt;
- } else {
- m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
  }
 #endif
 
@@ -1067,11 +1128,42 @@ axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
  goto input;
  }
 
+#if 0 /* ifdef AXEN_TOE */
+ switch ((pkt_hdr & AXEN_RXHDR_L3_TYPE_MASK) >>
+    AXEN_RXHDR_L3_TYPE_OFFSET) {
+ case AXEN_RXHDR_L3_TYPE_IPV4:
+ m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
+ break;
+ case AXEN_RXHDR_L3_TYPE_IPV6:
+ /* XXX IPV6 equivalent of M_IPV4_CSUM_IN_OK? */
+ break;
+ default:
+ /* do we need to set something here? */
+ break;
+ }
+
+ switch ((pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >>
+    AXEN_RXHDR_L4_TYPE_OFFSET) {
+ case AXEN_RXHDR_L4_TYPE_ICMP:
+ m->m_pkthdr.csum_flags |= M_ICMP_CSUM_IN_OK;
+ break;
+ case AXEN_RXHDR_L4_TYPE_UDP:
+ m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK;
+ break;
+ case AXEN_RXHDR_L4_TYPE_TCP:
+ m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK;
+ break;
+ default:
+ /* do we need to set something here? */
+ break;
+ }
+#endif
+
  ml_enqueue(&ml, m);
 
 nextpkt:
  /*
- * prepare next packet
+ * prepare next packet
  * as each packet will be aligned 8byte boundary,
  * need to fix up the start point of the buffer.
  */
@@ -1096,7 +1188,7 @@ done:
     USBD_NO_TIMEOUT, axen_rxeof);
  usbd_transfer(xfer);
 
- DPRINTFN(10,("%s: %s: start rx\n", sc->axen_dev.dv_xname, __func__));
+ DPRINTFN(10,("%s: %s: end rx\n", sc->axen_dev.dv_xname, __func__));
 }
 
 /*
@@ -1129,7 +1221,8 @@ axen_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
  printf("axen%d: usb error on tx: %s\n", sc->axen_unit,
     usbd_errstr(status));
  if (status == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_TX]);
+ usbd_clear_endpoint_stall_async(
+    sc->axen_ep[AXEN_ENDPT_TX]);
  splx(s);
  return;
  }
@@ -1243,6 +1336,8 @@ axen_encap(struct axen_softc *sc, struct mbuf *m, int idx)
  /* Transmit */
  err = usbd_transfer(c->axen_xfer);
  if (err != USBD_IN_PROGRESS) {
+ DPRINTFN(2,("%s: %s: usbd_transfer err = %d\n",
+    sc->axen_dev.dv_xname,__func__, err));
  axen_stop(sc);
  return EIO;
  }
@@ -1305,6 +1400,8 @@ axen_init(void *xsc)
  uWord wval;
  uint16_t rxmode;
 
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
+
  s = splnet();
 
  /*
@@ -1447,7 +1544,7 @@ axen_watchdog(struct ifnet *ifp)
  sc = ifp->if_softc;
 
  ifp->if_oerrors++;
- printf("axen%d: watchdog timeout\n", sc->axen_unit);
+ printf("%s: watchdog timeout\n", sc->axen_dev.dv_xname);
 
  s = splusb();
  c = &sc->axen_cdata.axen_tx_chain[0];
@@ -1472,6 +1569,7 @@ axen_stop(struct axen_softc *sc)
  u_int16_t ctl;
  uWord wval;
 
+ DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
 
  ifp = &sc->arpcom.ac_if;
  ifp->if_timer = 0;
--
2.20.1

Reply | Threaded
Open this post in threaded view
|

Re: patch axen(4) (WIP)

Artturi Alm
In reply to this post by Nils Frohberg
On Tue, Feb 26, 2019 at 03:00:15PM +0100, Nils Frohberg wrote:

> On Mon, Feb 25, 2019 at 03:50:48PM -0300, Martin Pieuchot wrote:
> > On 25/02/19(Mon) 14:52, Nils Frohberg wrote:
> > > Hi,
> > >
> > > as mentioned previously, I'm looking into axen(4). While searching
> > > for the cause of a panic (fixed since, thanks mpi@) I started to
> > > rewrite parts of the driver. References were mainly the FreeBSD and
> > > Linux drivers.
> >
> > Please try to isolate parts of your diff that fixes issues and cosmetic
> > changes.  The simpler it gets the easier it is for us to review it.
>
> Sure, I'll send separate patches.
>
> (I cvs up'ed my src forder in order to test compile the individual
> patches and found out that xhci.c,v1.91 breaks my USB devices. I'll
> send a mail to bugs@ later.)
>
> > > I didn't get around to much testing/debugging lately, therefore I
> > > wanted to share the current state (diff below).
> > >
> > > The current state works a lot better than previously (for me). I
> > > used to have a huge amount of ierrs (aprrox. 1 ierr per ipkt) and
> > > often no packets would be transferred at all (or stop being transferred
> > > after some time).
> >
> > Do you know why?  What were the problems?
>
> I'm not 100% sure, since I did a lot of back and forth. It finally
> got better once I disabled EEE and lowered the watermark levels.
>

Have you looked at what NetBSD has done with their axen(4)? there has
been 20commits in 2019 so far[0], while some of them are possibly,
idk., useless to us(thinking about hw checksum offloading), there was
some bug fixes that did look relevant to me, but i succesfully
installed&built kernels on nfs over axen(4) a couple of weeks ago,
so the bugs it has didn't feel critical enough for me to make
a branch for them. that was on arm64/dwctwo(4), tbh. i haven't been
happy with axen(4) on amd64/{e,x}hci(4) myself in the past either. :]

I guess i'm trying to say maybe it wouldn't hurt to sync a bit before
deviating as much as atleast your whole WIP diff did. I haven't read
your separate patches yet, but i'll try to get around to also testing
those before weekend:]

-Artturi

[0] https://github.com/NetBSD/src/commits/trunk/sys/dev/usb/if_axen.c

Reply | Threaded
Open this post in threaded view
|

Re: patch axen(4) (WIP)

Nils Frohberg
On Tue, Feb 26, 2019 at 08:57:57PM +0200, Artturi Alm wrote:

> On Tue, Feb 26, 2019 at 03:00:15PM +0100, Nils Frohberg wrote:
> > On Mon, Feb 25, 2019 at 03:50:48PM -0300, Martin Pieuchot wrote:
> > > On 25/02/19(Mon) 14:52, Nils Frohberg wrote:
> > > > Hi,
> > > >
> > > > as mentioned previously, I'm looking into axen(4). While searching
> > > > for the cause of a panic (fixed since, thanks mpi@) I started to
> > > > rewrite parts of the driver. References were mainly the FreeBSD and
> > > > Linux drivers.
> > >
> > > Please try to isolate parts of your diff that fixes issues and cosmetic
> > > changes.  The simpler it gets the easier it is for us to review it.
> >
> > Sure, I'll send separate patches.
> >
> > (I cvs up'ed my src forder in order to test compile the individual
> > patches and found out that xhci.c,v1.91 breaks my USB devices. I'll
> > send a mail to bugs@ later.)
> >
> > > > I didn't get around to much testing/debugging lately, therefore I
> > > > wanted to share the current state (diff below).
> > > >
> > > > The current state works a lot better than previously (for me). I
> > > > used to have a huge amount of ierrs (aprrox. 1 ierr per ipkt) and
> > > > often no packets would be transferred at all (or stop being transferred
> > > > after some time).
> > >
> > > Do you know why?  What were the problems?
> >
> > I'm not 100% sure, since I did a lot of back and forth. It finally
> > got better once I disabled EEE and lowered the watermark levels.
> >
>
> Have you looked at what NetBSD has done with their axen(4)? there has
> been 20commits in 2019 so far[0], while some of them are possibly,
> idk., useless to us(thinking about hw checksum offloading), there was
> some bug fixes that did look relevant to me, but i succesfully
> installed&built kernels on nfs over axen(4) a couple of weeks ago,
> so the bugs it has didn't feel critical enough for me to make
> a branch for them. that was on arm64/dwctwo(4), tbh. i haven't been
> happy with axen(4) on amd64/{e,x}hci(4) myself in the past either. :]

I wrote the diff last December. I looked at NetBSD's code back then,
but they didn't have any significant changes.

At a cursory glance, many changes are similar to mine. But there are
a few things that should be worth looking at.

> I guess i'm trying to say maybe it wouldn't hurt to sync a bit before
> deviating as much as atleast your whole WIP diff did. I haven't read
> your separate patches yet, but i'll try to get around to also testing
> those before weekend:]

The separate patches are (more or less) the big patch split up via
$(git add -p). There are a few things that might be worth looking
into, such as the pause water levels, enabling EEE, axen_bulk_size
values, buffer sizes, ...

More testing would be great. Especially since this is the only box
I have where I can attach it to xhci.

> -Artturi
>
> [0] https://github.com/NetBSD/src/commits/trunk/sys/dev/usb/if_axen.c
>

Reply | Threaded
Open this post in threaded view
|

Re: patch axen(4) (WIP)

Nils Frohberg
Any there further interest in these patches? I was running these
since 61 days, doing lots of rsync and TimeMachine (netatalk)
backups. Didn't have any crashes or (noticeable) network dropouts.

$ uptime
11:05AM  up 61 days, 16:54, 1 user, load averages: 0.35, 0.38, 0.38
$

On Thu, Feb 28, 2019 at 07:53:39AM +0100, Nils Frohberg wrote:

> On Tue, Feb 26, 2019 at 08:57:57PM +0200, Artturi Alm wrote:
> > On Tue, Feb 26, 2019 at 03:00:15PM +0100, Nils Frohberg wrote:
> > > On Mon, Feb 25, 2019 at 03:50:48PM -0300, Martin Pieuchot wrote:
> > > > On 25/02/19(Mon) 14:52, Nils Frohberg wrote:
> > > > > Hi,
> > > > >
> > > > > as mentioned previously, I'm looking into axen(4). While searching
> > > > > for the cause of a panic (fixed since, thanks mpi@) I started to
> > > > > rewrite parts of the driver. References were mainly the FreeBSD and
> > > > > Linux drivers.
> > > >
> > > > Please try to isolate parts of your diff that fixes issues and cosmetic
> > > > changes.  The simpler it gets the easier it is for us to review it.
> > >
> > > Sure, I'll send separate patches.
> > >
> > > (I cvs up'ed my src forder in order to test compile the individual
> > > patches and found out that xhci.c,v1.91 breaks my USB devices. I'll
> > > send a mail to bugs@ later.)
> > >
> > > > > I didn't get around to much testing/debugging lately, therefore I
> > > > > wanted to share the current state (diff below).
> > > > >
> > > > > The current state works a lot better than previously (for me). I
> > > > > used to have a huge amount of ierrs (aprrox. 1 ierr per ipkt) and
> > > > > often no packets would be transferred at all (or stop being transferred
> > > > > after some time).
> > > >
> > > > Do you know why?  What were the problems?
> > >
> > > I'm not 100% sure, since I did a lot of back and forth. It finally
> > > got better once I disabled EEE and lowered the watermark levels.
> > >
> >
> > Have you looked at what NetBSD has done with their axen(4)? there has
> > been 20commits in 2019 so far[0], while some of them are possibly,
> > idk., useless to us(thinking about hw checksum offloading), there was
> > some bug fixes that did look relevant to me, but i succesfully
> > installed&built kernels on nfs over axen(4) a couple of weeks ago,
> > so the bugs it has didn't feel critical enough for me to make
> > a branch for them. that was on arm64/dwctwo(4), tbh. i haven't been
> > happy with axen(4) on amd64/{e,x}hci(4) myself in the past either. :]
>
> I wrote the diff last December. I looked at NetBSD's code back then,
> but they didn't have any significant changes.
>
> At a cursory glance, many changes are similar to mine. But there are
> a few things that should be worth looking at.
>
> > I guess i'm trying to say maybe it wouldn't hurt to sync a bit before
> > deviating as much as atleast your whole WIP diff did. I haven't read
> > your separate patches yet, but i'll try to get around to also testing
> > those before weekend:]
>
> The separate patches are (more or less) the big patch split up via
> $(git add -p). There are a few things that might be worth looking
> into, such as the pause water levels, enabling EEE, axen_bulk_size
> values, buffer sizes, ...
>
> More testing would be great. Especially since this is the only box
> I have where I can attach it to xhci.
>
> > -Artturi
> >
> > [0] https://github.com/NetBSD/src/commits/trunk/sys/dev/usb/if_axen.c
> >
>

Reply | Threaded
Open this post in threaded view
|

Re: patch axen(4) (WIP)

sc.dying
In reply to this post by Nils Frohberg
hi,

On 2019/02/28 06:53, Nils Frohberg wrote:
> On Tue, Feb 26, 2019 at 08:57:57PM +0200, Artturi Alm wrote:
>> On Tue, Feb 26, 2019 at 03:00:15PM +0100, Nils Frohberg wrote:
[snip]

>> Have you looked at what NetBSD has done with their axen(4)? there has
>> been 20commits in 2019 so far[0], while some of them are possibly,
>> idk., useless to us(thinking about hw checksum offloading), there was
>> some bug fixes that did look relevant to me, but i succesfully
>> installed&built kernels on nfs over axen(4) a couple of weeks ago,
>> so the bugs it has didn't feel critical enough for me to make
>> a branch for them. that was on arm64/dwctwo(4), tbh. i haven't been
>> happy with axen(4) on amd64/{e,x}hci(4) myself in the past either. :]
>
> I wrote the diff last December. I looked at NetBSD's code back then,
> but they didn't have any significant changes.
>
> At a cursory glance, many changes are similar to mine. But there are
> a few things that should be worth looking at.

Do you see the link status LED of axen is down when ifconfig it up/down?
The attached patch should fix that bug.
I applied the diff of NetBSD's if_axen.c between rev 1.20 and 1.21

https://github.com/NetBSD/src/commit/4603809d1167ab5cc2d8d35f95722aec85789fd0#diff-4748c3be63ca566d4a07520285f031a9

to if_axen.c of 6.5-current with [1-7]/7 patches.

The log reads:
> Enable AXEN_RXCTL_START bit only when RX is ready. Otherwise,
> the adapter eventually falls into "no carrier" state while it
> is not running.

I reverted 3/7 partially to keep previous value of AXEN_MAC_RXCTL reg,
so that RXCTL_START is set only in axen_init and is reset in axen_stop.

axen_reset does not initialise the chip any more.
It does nothing but delay.
The chip init, axen_ax88179_init, is called once while attach.


--- sys/dev/usb/if_axen.c Wed Jun 12 12:52:01 2019
+++ sys/dev/usb/if_axen.c Thu Jun 13 09:19:32 2019
@@ -421,7 +421,10 @@ axen_iff(struct axen_softc *sc)
 
  /* Enable receiver, set RX mode */
  axen_lock_mii(sc);
- rxmode = AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_START;
+ axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
+ rxmode = UGETW(wval);
+ rxmode &= ~(AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_PROMISC |
+    AXEN_RXCTL_ACPT_MCAST);
  ifp->if_flags &= ~IFF_ALLMULTI;
 
  /*
@@ -476,8 +479,6 @@ axen_reset(struct axen_softc *sc)
  /* Wait a little while for the chip to get its brains in order. */
  DELAY(1000);
 
- axen_ax88179_init(sc);
-
  return;
 }
 
@@ -486,7 +487,7 @@ axen_ax88179_init(struct axen_softc *sc)
 {
  uWord wval;
  uByte val;
- u_int16_t ctl, temp;
+ u_int16_t ctl, rxmode, temp;
 
  DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
 
@@ -565,6 +566,10 @@ axen_ax88179_init(struct axen_softc *sc)
  axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_HIGH_WATERMARK, &val);
 
  /* Set RX/TX configuration. */
+ rxmode = AXEN_RXCTL_DROPCRCERR;
+ USETW(wval, rxmode);
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
+
 #ifdef AXEN_TOE
  /* enable offloading */
  val = AXEN_RXCOE_IPv4 |
@@ -1566,7 +1571,7 @@ axen_stop(struct axen_softc *sc)
  usbd_status err;
  struct ifnet *ifp;
  int i;
- u_int16_t ctl;
+ u_int16_t ctl, rxmode;
  uWord wval;
 
  DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
@@ -1578,7 +1583,13 @@ axen_stop(struct axen_softc *sc)
 
  timeout_del(&sc->axen_stat_ch);
 
- /* disable receive */
+ /* Disable receiver, set RX mode */
+ axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
+ rxmode = UGETW(&wval);
+ rxmode &= ~AXEN_RXCTL_START;
+ USETW(wval, rxmode);
+ axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
+
  axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval);
  ctl = UGETW(wval);
  ctl &= ~AXEN_MEDIUM_RECV_EN;


>> I guess i'm trying to say maybe it wouldn't hurt to sync a bit before
>> deviating as much as atleast your whole WIP diff did. I haven't read
>> your separate patches yet, but i'll try to get around to also testing
>> those before weekend:]
>
> The separate patches are (more or less) the big patch split up via
> $(git add -p). There are a few things that might be worth looking
> into, such as the pause water levels, enabling EEE, axen_bulk_size
> values, buffer sizes, ...
>
> More testing would be great. Especially since this is the only box
> I have where I can attach it to xhci.
>
>> -Artturi
>>
>> [0] https://github.com/NetBSD/src/commits/trunk/sys/dev/usb/if_axen.c
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: patch axen(4) (WIP)

sc.dying
In reply to this post by Nils Frohberg
hi,

On 2019/02/26 14:00, Nils Frohberg wrote:
> On Mon, Feb 25, 2019 at 03:50:48PM -0300, Martin Pieuchot wrote:
>> On 25/02/19(Mon) 14:52, Nils Frohberg wrote:
[snip]

>>> I didn't get around to much testing/debugging lately, therefore I
>>> wanted to share the current state (diff below).
>>>
>>> The current state works a lot better than previously (for me). I
>>> used to have a huge amount of ierrs (aprrox. 1 ierr per ipkt) and
>>> often no packets would be transferred at all (or stop being transferred
>>> after some time).
>>
>> Do you know why?  What were the problems?
>
> I'm not 100% sure, since I did a lot of back and forth. It finally
> got better once I disabled EEE and lowered the watermark levels.

I run my axen + your [1-7]/7 patches on amd64 with ehci,
that is, on high-speed.
When I ping to another host, it drops 20-30% of receiving packets.
It looks like the txeof does its job but the rxeof is not called
when packets arrive.
(debug messages and tcpdump on another host says so).

I checked each difference of diffs and found out that the initial
bufsz value in attach causes the drops.
I reverted like as following diff, it works correctly without drops
even the BUFSZ of HS is lower than bufsz of qctrl of HS.

Thoughts?


--- sys/dev/usb/if_axenreg.h Sun Jun 16 00:48:48 2019
+++ sys/dev/usb/if_axenreg.h Sun Jun 16 00:49:24 2019
@@ -13,7 +13,7 @@
 #define AXEN_MCAST_FILTER_SIZE 8
 /* unit: KB */
 #define AXEN_BUFSZ_LS 0x18
-#define AXEN_BUFSZ_HS 0x16
+#define AXEN_BUFSZ_HS 0x10
 #define AXEN_BUFSZ_SS 0x12
 #define AXEN_BUFSZ_MAX AXEN_BUFSZ_LS
 
--- sys/dev/usb/if_axen.c Wed Jun 12 12:52:01 2019
+++ sys/dev/usb/if_axen.c Sun Jun 16 00:50:08 2019
@@ -690,8 +695,10 @@ axen_attach(struct device *parent, struct device *self
  * this will be updated once the link state changes
  */
  switch (sc->axen_udev->speed) {
- case USB_SPEED_FULL:
  case USB_SPEED_HIGH:
+ sc->axen_bufsz = AXEN_BUFSZ_HS * 1024;
+ break;
+ case USB_SPEED_FULL:
  case USB_SPEED_SUPER:
  /* linux adds 2 to the buffer size (why?) */
  sc->axen_bufsz = (AXEN_BUFSZ_MAX + 2) * 1024;


>>> This box hosts backups (rsync and TimeMachine), so it gets its fair
>>> share of traffic. I could reduce the ierrs to ~2100 with 5d uptime,
>>> and the packets keep flowing:
>>>
>>> $ netstat -niI axen0
>>> Name    Mtu   Network     Address              Ipkts Ierrs    Opkts Oerrs Colls
>>> axen0   1500  <Link>      94:c6:91:1f:85:a5 141199356  2099 112289969     0     0
>>> $ uptime
>>>  7:15PM  up 5 days,  9:57, 3 users, load averages: 0.11, 0.13, 0.14
>>> $
>>>
>>> But there a still a few problems:
>>>
>>> 1) There are still ierrs. These happen when the rx path can't
>>> allocate mbufs (cf. diff below for DPRINTF):
>>> axen0: could not allocate rx mbuf (2 total, 2 remaining)
>>> axen0: could not allocate rx mbuf (3 total, 3 remaining)
>>> axen0: could not allocate rx mbuf (2 total, 2 remaining)
>>> axen0: could not allocate rx mbuf (1 total, 1 remaining)
>>
>> Look at the pools when this happen, what do you see?  What is the size
>> of `pkt_len' when this happen?
>
> I added pkt_len to the DPRINTF so that I can check the relevant
> pools once I see this error.
>
>>> 2) If the adapter is plugged into a USB 3 port at boot, it will
>>> return 0x42 when aked for AXEN_PHYSICAL_LINK_STATUS, ie.
>>> (AXEN_EPHY_1000|AXEN_USB_HS). The adapter most often then simply
>>> doesn't receive packets. If I plug in the adapter after boot is
>>> complete, 0x44 is returned (AXEN_EPHY_1000|AXEN_USB_SS), as expected.
>>> I'm not sure if I'm still missing something in init (probably) or
>>> if this results from something higher in the stack (xhci?).
>>> (Didn't test USB 2 or lower.)
>>
>> Do you see any difference in 'usbdevs -vv' output during the two cases?
>
> Yes, high speed vs super speed and power draw:
>
> # Plugged in after boot:
>
> $ usbdevs -vv
> Controller /dev/usb0:
> addr 01: 8086:0000 Intel, xHCI root hub
> super speed, self powered, config 1, rev 1.00
> driver: uhub0
> port 01: 0001.02a0 power Rx.detect
> port 02: 0011.02a0 power Rx.detect
> port 03: 0000.0503 connect enabled recovery
> port 04: 0000.0503 connect enabled recovery
> port 05: 0000.02a0 power Rx.detect
> port 06: 0000.02a0 power Rx.detect
> port 07: 0000.02a0 power Rx.detect
> port 08: 0000.0103 connect enabled recovery
> port 09: 0000.02a0 power Rx.detect
> port 10: 0000.0203 connect enabled power U0
> port 11: 0000.0203 connect enabled power U0
> port 12: 0000.0203 connect enabled power U0
> port 13: 0000.02a0 power Rx.detect
> port 14: 0000.02a0 power Rx.detect
> port 15: 0000.02a0 power Rx.detect
> addr 04: 0bc2:ab44 Seagate, Backup+ Hub
> high speed, self powered, config 1, rev 48.85, iSerial 01CB7236B0N6
> driver: uhub2
> port 01: 0000.0100 power
> port 02: 0000.0100 power
> port 03: 0000.0100 power
> addr 05: 05e3:0610 GenesysLogic, USB2.0 Hub
> high speed, self powered, config 1, rev 92.16
> driver: uhub3
> port 01: 0000.0100 power
> port 02: 0000.0100 power
> port 03: 0000.0100 power
> port 04: 0000.0100 power
> addr 06: 8087:0aa7 Intel, product 0x0aa7
> full speed, self powered, config 1, rev 0.01
> driver: ugen0
> addr 07: 0bc2:ab45 Seagate, Backup+ Hub
> super speed, self powered, config 1, rev 48.85, iSerial 01CB7236B0N6
> driver: uhub4
> port 01: 0000.0203 connect enabled power U0
> port 02: 0000.02a0 power Rx.detect
> port 03: 0000.0203 connect enabled power U0
> addr 08: 0bc2:ab38 Seagate, Backup+ Hub BK
> super speed, self powered, config 1, rev 1.00, iSerial NA8TMK6F
> driver: umass0
> addr 09: 05e3:0612 GenesysLogic, USB3.0 Hub
> super speed, self powered, config 1, rev 92.16
> driver: uhub5
> port 01: 0000.02a0 power Rx.detect
> port 02: 0000.02a0 power Rx.detect
> port 03: 0000.02a0 power Rx.detect
> port 04: 0000.0203 connect enabled power U0
> addr 10: 1058:25a2 Western Digital, Elements 25A2
> super speed, power 224 mA, config 1, rev 10.14, iSerial 575854314131373838593538
> driver: umass1
> addr 11: 0b95:1790 ASIX Elec. Corp., AX88179
> super speed, power 124 mA, config 1, rev 1.00, iSerial 0000000000013F
> driver: axen0
> addr 12: 2109:0701 Intenso, External USB 3.0
> super speed, self powered, config 1, rev 3.07, iSerial 20130301005083
> driver: umass2
> $
>
> # Plugged in before boot:
>
> $ usbdevs -vv
> Controller /dev/usb0:
> addr 01: 8086:0000 Intel, xHCI root hub
> super speed, self powered, config 1, rev 1.00
> driver: uhub0
> port 01: 0001.02a0 power Rx.detect
> port 02: 0000.0503 connect enabled recovery
> port 03: 0000.0503 connect enabled recovery
> port 04: 0000.0503 connect enabled recovery
> port 05: 0000.02a0 power Rx.detect
> port 06: 0000.02a0 power Rx.detect
> port 07: 0000.02a0 power Rx.detect
> port 08: 0000.0103 connect enabled recovery
> port 09: 0000.02a0 power Rx.detect
> port 10: 0000.02a0 power Rx.detect
> port 11: 0000.0203 connect enabled power U0
> port 12: 0000.0203 connect enabled power U0
> port 13: 0000.02a0 power Rx.detect
> port 14: 0000.02a0 power Rx.detect
> port 15: 0000.02a0 power Rx.detect
> addr 04: 0b95:1790 ASIX Elec. Corp., AX88179
> high speed, power 248 mA, config 1, rev 1.00, iSerial 0000000000013F
> driver: axen0
> addr 05: 0bc2:ab44 Seagate, Backup+ Hub
> high speed, self powered, config 1, rev 48.85, iSerial 01CB7236B0N6
> driver: uhub2
> port 01: 0000.0100 power
> port 02: 0000.0100 power
> port 03: 0000.0100 power
> addr 06: 05e3:0610 GenesysLogic, USB2.0 Hub
> high speed, self powered, config 1, rev 92.16
> driver: uhub3
> port 01: 0000.0100 power
> port 02: 0000.0100 power
> port 03: 0000.0100 power
> port 04: 0000.0100 power
> addr 07: 8087:0aa7 Intel, product 0x0aa7
> full speed, self powered, config 1, rev 0.01
> driver: ugen0
> addr 08: 0bc2:ab45 Seagate, Backup+ Hub
> super speed, self powered, config 1, rev 48.85, iSerial 01CB7236B0N6
> driver: uhub4
> port 01: 0000.0203 connect enabled power U0
> port 02: 0000.02a0 power Rx.detect
> port 03: 0000.02b0 power Rx.detect
> addr 09: 0bc2:ab38 Seagate, Backup+ Hub BK
> super speed, self powered, config 1, rev 1.00, iSerial NA8TMK6F
> driver: umass0
> addr 10: 05e3:0612 GenesysLogic, USB3.0 Hub
> super speed, self powered, config 1, rev 92.16
> driver: uhub5
> port 01: 0000.02a0 power Rx.detect
> port 02: 0000.02a0 power Rx.detect
> port 03: 0000.02a0 power Rx.detect
> port 04: 0000.0203 connect enabled power U0
> addr 11: 1058:25a2 Western Digital, Elements 25A2
> super speed, power 224 mA, config 1, rev 10.14, iSerial 575854314131373838593538
> driver: umass1
> $
>
> Here's a dmesg:
>
> OpenBSD 6.4-current (AXEN_DEBUG) #58: Tue Feb 26 13:42:44 CET 2019
>     [hidden email]:/usr/src/sys/arch/amd64/compile/AXEN_DEBUG
> real mem = 8415174656 (8025MB)
> avail mem = 8150171648 (7772MB)
> mpath0 at root
> scsibus0 at mpath0: 256 targets
> mainbus0 at root
> bios0 at mainbus0: SMBIOS rev. 3.0 @ 0x79a9a000 (51 entries)
> bios0: vendor Intel Corp. version "AYAPLCEL.86A.0056.2018.0926.1100" date 09/26/2018
> bios0: Intel Corporation NUC6CAYH
> acpi0 at bios0: rev 2
> acpi0: sleep states S0 S3 S4 S5
> acpi0: tables DSDT FACP FPDT FIDT MCFG DBG2 DBGP HPET LPIT APIC NPKT PRAM WSMT SSDT SSDT SSDT SSDT SSDT SSDT SSDT UEFI BGRT TPM2 DMAR WDAT NHLT
> acpi0: wakeup devices SIO1(S3) HDAS(S3) XHC_(S4) XDCI(S4) BRCM(S0) PXSX(S4) RP01(S4) PXSX(S4) RP02(S4) PXSX(S4) RP03(S4) PXSX(S4) RP04(S4) PXSX(S4) RP05(S4) PXSX(S4) [...]
> acpitimer0 at acpi0: 3579545 Hz, 32 bits
> acpimcfg0 at acpi0
> acpimcfg0: addr 0xe0000000, bus 0-255
> acpihpet0 at acpi0: 19200000 Hz
> acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
> cpu0 at mainbus0: apid 0 (boot processor)
> cpu0: Intel(R) Celeron(R) CPU J3455 @ 1.50GHz, 1496.67 MHz, 06-5c-09
> cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,FSGSBASE,SMEP,ERMS,MPX,RDSEED,SMAP,CLFLUSHOPT,PT,SHA,IBRS,IBPB,STIBP,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES
> cpu0: 1MB 64b/line 16-way L2 cache
> cpu0: smt 0, core 0, package 0
> mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges
> cpu0: apic clock running at 19MHz
> cpu0: mwait min=64, max=64, C-substates=0.2.0.2.4.2.1.1, IBE
> cpu1 at mainbus0: apid 2 (application processor)
> cpu1: Intel(R) Celeron(R) CPU J3455 @ 1.50GHz, 1496.55 MHz, 06-5c-09
> cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,FSGSBASE,SMEP,ERMS,MPX,RDSEED,SMAP,CLFLUSHOPT,PT,SHA,IBRS,IBPB,STIBP,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES
> cpu1: 1MB 64b/line 16-way L2 cache
> cpu1: smt 0, core 1, package 0
> cpu2 at mainbus0: apid 4 (application processor)
> cpu2: Intel(R) Celeron(R) CPU J3455 @ 1.50GHz, 1496.55 MHz, 06-5c-09
> cpu2: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,FSGSBASE,SMEP,ERMS,MPX,RDSEED,SMAP,CLFLUSHOPT,PT,SHA,IBRS,IBPB,STIBP,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES
> cpu2: 1MB 64b/line 16-way L2 cache
> cpu2: smt 0, core 2, package 0
> cpu3 at mainbus0: apid 6 (application processor)
> cpu3: Intel(R) Celeron(R) CPU J3455 @ 1.50GHz, 1496.55 MHz, 06-5c-09
> cpu3: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,FSGSBASE,SMEP,ERMS,MPX,RDSEED,SMAP,CLFLUSHOPT,PT,SHA,IBRS,IBPB,STIBP,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES
> cpu3: 1MB 64b/line 16-way L2 cache
> cpu3: smt 0, core 3, package 0
> ioapic0 at mainbus0: apid 1 pa 0xfec00000, version 20, 120 pins
> acpiprt0 at acpi0: bus 0 (PCI0)
> acpiprt1 at acpi0: bus -1 (RP01)
> acpiprt2 at acpi0: bus -1 (RP02)
> acpiprt3 at acpi0: bus 1 (RP03)
> acpiprt4 at acpi0: bus 2 (RP04)
> acpiprt5 at acpi0: bus 3 (RP05)
> acpiprt6 at acpi0: bus -1 (RP06)
> acpiec0 at acpi0
> acpicpu0 at acpi0: C1(@1 halt!), PSS
> acpicpu1 at acpi0: C1(@1 halt!), PSS
> acpicpu2 at acpi0: C1(@1 halt!), PSS
> acpicpu3 at acpi0: C1(@1 halt!), PSS
> acpipwrres0 at acpi0: FN00, resource for FAN0
> acpitz0 at acpi0: critical temperature is 100 degC
> acpipci0 at acpi0 PCI0: 0x00000000 0x00000011 0x00000001
> acpicmos0 at acpi0
> acpibtn0 at acpi0: PWRB
> acpibtn1 at acpi0: SLPB
> "INT3452" at acpi0 not configured
> "INT3452" at acpi0 not configured
> "INT3452" at acpi0 not configured
> "INT3452" at acpi0 not configured
> "INT33A1" at acpi0 not configured
> "MSFT0101" at acpi0 not configured
> "PNP0C0B" at acpi0 not configured
> "PNP0C14" at acpi0 not configured
> acpivideo0 at acpi0: GFX0
> acpivout0 at acpivideo0: DD1F
> cpu0: Enhanced SpeedStep 1496 MHz: speeds: 1501, 1500, 1400, 1300, 1200, 1100, 1000, 900, 800 MHz
> pci0 at mainbus0 bus 0
> pchb0 at pci0 dev 0 function 0 "Intel Apollo Lake Host" rev 0x0b
> inteldrm0 at pci0 dev 2 function 0 "Intel HD Graphics 500" rev 0x0b
> drm0 at inteldrm0
> inteldrm0: msi
> error: [drm:pid0:i915_firmware_load_error_print] *ERROR* failed to load firmware i915/bxt_dmc_ver1.bin (-22)
> error: [drm:pid0:i915_gem_init_hw] *ERROR* Failed to initialize GuC, error -8 (ignored)
> inteldrm0: 1680x1050, 32bpp
> wsdisplay0 at inteldrm0 mux 1: console (std, vt100 emulation)
> wsdisplay0: screen 1-5 added (std, vt100 emulation)
> azalia0 at pci0 dev 14 function 0 "Intel Apollo Lake HD Audio" rev 0x0b: msi
> azalia0: codecs: Realtek/0x0283, Intel/0x280a, using Realtek/0x0283
> audio0 at azalia0
> "Intel Apollo Lake TXE" rev 0x0b at pci0 dev 15 function 0 not configured
> ahci0 at pci0 dev 18 function 0 "Intel Apollo Lake AHCI" rev 0x0b: msi, AHCI 1.3.1
> ahci0: port 0: 6.0Gb/s
> ahci0: PHY offline on port 1
> scsibus1 at ahci0: 32 targets
> sd0 at scsibus1 targ 0 lun 0: <ATA, KINGSTON SA400S3, SBFK> SCSI3 0/direct fixed naa.50026b7682433dc5
> sd0: 114473MB, 512 bytes/sector, 234441648 sectors, thin
> ppb0 at pci0 dev 19 function 0 "Intel Apollo Lake PCIE" rev 0xfb: msi
> pci1 at ppb0 bus 1
> rtsx0 at pci1 dev 0 function 0 "Realtek RTS5229 Card Reader" rev 0x01: msi
> sdmmc0 at rtsx0: 4-bit, dma
> ppb1 at pci0 dev 19 function 1 "Intel Apollo Lake PCIE" rev 0xfb: msi
> pci2 at ppb1 bus 2
> iwm0 at pci2 dev 0 function 0 "Intel Dual Band Wireless-AC 3168" rev 0x10, msi
> ppb2 at pci0 dev 19 function 2 "Intel Apollo Lake PCIE" rev 0xfb: msi
> pci3 at ppb2 bus 3
> re0 at pci3 dev 0 function 0 "Realtek 8168" rev 0x15: RTL8168H/8111H (0x5400), msi, address 94:c6:91:1f:85:a5
> rgephy0 at re0 phy 7: RTL8251 PHY, rev. 0
> xhci0 at pci0 dev 21 function 0 "Intel Apollo Lake xHCI" rev 0x0b: msi, xHCI 1.0
> usb0 at xhci0: USB revision 3.0
> uhub0 at usb0 configuration 1 interface 0 "Intel xHCI root hub" rev 3.00/1.00 addr 1
> "Intel Apollo Lake I2C" rev 0x0b at pci0 dev 22 function 0 not configured
> "Intel Apollo Lake HSUART" rev 0x0b at pci0 dev 24 function 0 not configured
> "Intel Apollo Lake SPI" rev 0x0b at pci0 dev 25 function 0 not configured
> "Intel Apollo Lake SPI" rev 0x0b at pci0 dev 25 function 1 not configured
> "Intel Apollo Lake SPI" rev 0x0b at pci0 dev 25 function 2 not configured
> pcib0 at pci0 dev 31 function 0 "Intel Apollo Lake LPC" rev 0x0b
> ichiic0 at pci0 dev 31 function 1 "Intel Apollo Lake SMBus" rev 0x0b: polling
> iic0 at ichiic0
> spdmem0 at iic0 addr 0x50: 4GB DDR3 SDRAM PC3-14200 SO-DIMM
> spdmem1 at iic0 addr 0x52: 4GB DDR3 SDRAM PC3-14200 SO-DIMM
> isa0 at pcib0
> isadma0 at isa0
> fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
> com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
> com0: probed fifo depth: 0 bytes
> pckbc0 at isa0 port 0x60/5 irq 1 irq 12
> pckbd0 at pckbc0 (kbd slot)
> wskbd0 at pckbd0: console keyboard, using wsdisplay0
> pcppi0 at isa0 port 0x61
> spkr0 at pcppi0
> vmm0 at mainbus0: VMX/EPT
> efifb at mainbus0 not configured
> fdc0: drive 0: unknown device type 0xf0
> uhub1 at uhub0 port 1 configuration 1 interface 0 "Mitsumi Electric Hub in Apple Extended USB Keyboard" rev 1.10/4.20 addr 2
> uhidev0 at uhub1 port 3 configuration 1 interface 0 "Mitsumi Electric Apple Extended USB Keyboard" rev 1.10/4.20 addr 3
> uhidev0: iclass 3/1
> ukbd0 at uhidev0: 8 variable keys, 6 key codes, country code 13
> wskbd1 at ukbd0 mux 1
> wskbd1: connecting to wsdisplay0
> uhidev1 at uhub1 port 3 configuration 1 interface 1 "Mitsumi Electric Apple Extended USB Keyboard" rev 1.10/4.20 addr 3
> uhidev1: iclass 3/0, 3 report ids
> uhid0 at uhidev1 reportid 2: input=1, output=0, feature=0
> uhid1 at uhidev1 reportid 3: input=3, output=0, feature=0
> fdc0: drive 1: unknown device type 0xd0
> axen0 at uhub0 port 2 configuration 1 interface 0 "ASIX Elec. Corp. AX88179" rev 2.10/1.00 addr 4
> axen0: AX88179, address 94:c6:91:1f:85:a5
> rgephy1 at axen0 phy 3: RTL8169S/8110S/8211 PHY, rev. 5
> uhub2 at uhub0 port 3 configuration 1 interface 0 "Seagate Backup+ Hub" rev 2.10/48.85 addr 5
> uhub3 at uhub0 port 4 configuration 1 interface 0 "GenesysLogic USB2.0 Hub" rev 2.10/92.16 addr 6
> ugen0 at uhub0 port 8 "Intel product 0x0aa7" rev 2.00/0.01 addr 7
> uhub4 at uhub0 port 11 configuration 1 interface 0 "Seagate Backup+ Hub" rev 3.00/48.85 addr 8
> umass0 at uhub4 port 1 configuration 1 interface 0 "Seagate Backup+ Hub BK" rev 3.10/1.00 addr 9
> umass0: using SCSI over Bulk-Only
> scsibus2 at umass0: 2 targets, initiator 0
> sd1 at scsibus2 targ 1 lun 0: <Seagate, Backup+ Hub BK, D781> SCSI4 0/direct fixed
> sd1: 7630885MB, 512 bytes/sector, 15628053167 sectors
> uhub5 at uhub0 port 12 configuration 1 interface 0 "GenesysLogic USB3.0 Hub" rev 3.00/92.16 addr 10
> umass1 at uhub5 port 4 configuration 1 interface 0 "Western Digital Elements 25A2" rev 3.00/10.14 addr 11
> umass1: using SCSI over Bulk-Only
> scsibus3 at umass1: 2 targets, initiator 0
> sd2 at scsibus3 targ 1 lun 0: <WD, Elements 25A2, 1014> SCSI4 0/direct fixed serial.105825a2373838593538
> sd2: 1907697MB, 512 bytes/sector, 3906963456 sectors
> vscsi0 at root
> scsibus4 at vscsi0: 256 targets
> softraid0 at root
> scsibus5 at softraid0: 256 targets
> sd3 at scsibus5 targ 1 lun 0: <OPENBSD, SR CRYPTO, 006> SCSI2 0/direct fixed
> sd3: 107519MB, 512 bytes/sector, 220200432 sectors
> root on sd3a (b8ec0b353d2db63d.a) swap on sd3b dump on sd3b
> iwm0: hw rev 0x220, fw ver 22.361476.0, address 0c:54:15:d0:a3:95
> wskbd1: disconnecting from wsdisplay0
> wskbd1 detached
> ukbd0 detached
> uhidev0 detached
> uhid0 detached
> uhid1 detached
> uhidev1 detached
> uhidev0 at uhub1 port 3 configuration 1 interface 0 "Mitsumi Electric Apple Extended USB Keyboard" rev 1.10/4.20 addr 3
> uhidev0: iclass 3/1
> ukbd0 at uhidev0: 8 variable keys, 6 key codes, country code 13
> wskbd1 at ukbd0: console keyboard, using wsdisplay0
> uhidev1 at uhub1 port 3 configuration 1 interface 1 "Mitsumi Electric Apple Extended USB Keyboard" rev 1.10/4.20 addr 3
> uhidev1: iclass 3/0, 3 report ids
> uhid0 at uhidev1 reportid 2: input=1, output=0, feature=0
> uhid1 at uhidev1 reportid 3: input=3, output=0, feature=0
> sd4 at scsibus5 targ 2 lun 0: <OPENBSD, SR CRYPTO, 006> SCSI2 0/direct fixed
> sd4: 1907694MB, 512 bytes/sector, 3906959213 sectors
> sd5 at scsibus5 targ 3 lun 0: <OPENBSD, SR CRYPTO, 006> SCSI2 0/direct fixed
> sd5: 7630885MB, 512 bytes/sector, 15628052512 sectors
>