Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Conditionally enable the formerly #if'ed-out cod...



details:   https://anonhg.NetBSD.org/src/rev/187bdd5dd71c
branches:  trunk
changeset: 934067:187bdd5dd71c
user:      gson <gson%NetBSD.org@localhost>
date:      Sat Jun 06 13:53:43 2020 +0000

description:
Conditionally enable the formerly #if'ed-out code to use the
WRITE_REGION_1 command for writing blocks of data to the device.
This is to address a performance issue where "ifconfig run0 up" would
take as long as 20-30 seconds when using a UHCI or OHCI host
controller due to the large number of control transfers performed by
the driver in combination with the inability of those host controllers
to perform multiple control transfers per USB frame.  Limit the
transfers to 64 bytes as in the corresponding #if'ed-out code in
FreeBSD.  Currently only enabled for mac_ver 0x5390 as it is the only
version tested so far.

diffstat:

 sys/dev/usb/if_run.c    |  98 +++++++++++++++++++++++++++++++++++--------------
 sys/dev/usb/if_runvar.h |   7 ++-
 2 files changed, 74 insertions(+), 31 deletions(-)

diffs (161 lines):

diff -r dc84bfb7ca39 -r 187bdd5dd71c sys/dev/usb/if_run.c
--- a/sys/dev/usb/if_run.c      Sat Jun 06 10:22:45 2020 +0000
+++ b/sys/dev/usb/if_run.c      Sat Jun 06 13:53:43 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_run.c,v 1.39 2020/03/15 23:04:51 thorpej Exp $      */
+/*     $NetBSD: if_run.c,v 1.40 2020/06/06 13:53:43 gson Exp $ */
 /*     $OpenBSD: if_run.c,v 1.90 2012/03/24 15:11:04 jsg Exp $ */
 
 /*-
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_run.c,v 1.39 2020/03/15 23:04:51 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_run.c,v 1.40 2020/06/06 13:53:43 gson Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -649,6 +649,19 @@
        sc->mac_ver = ver >> 16;
        sc->mac_rev = ver & 0xffff;
 
+       /*
+       * Per the comment in run_write_region_1(), "the WRITE_REGION_1
+       * command is not stable on RT2860", but WRITE_REGION_1 calls
+       * of up to 64 bytes have been tested and found to work with
+       * mac_ver 0x5390, and they reduce the run time of "ifconfig
+       * run0 up" from 30 seconds to a couple of seconds on OHCI.
+       * Enable WRITE_REGION_1 for the tested version only.  As other
+       * versions are tested and found to work, they can be added
+       * here.
+       */
+       if (sc->mac_ver == 0x5390)
+               sc->sc_flags |= RUN_USE_BLOCK_WRITE;
+
        /* retrieve RF rev. no and various other things from EEPROM */
        run_read_eeprom(sc);
 
@@ -1046,37 +1059,49 @@
 static int
 run_write(struct run_softc *sc, uint16_t reg, uint32_t val)
 {
-       int error;
-
-       if ((error = run_write_2(sc, reg, val & 0xffff)) == 0)
-               error = run_write_2(sc, reg + 2, val >> 16);
-       return error;
+       uint32_t tmp = htole32(val);
+       return run_write_region_1(sc, reg, (uint8_t *)&tmp, sizeof(tmp));
 }
 
 static int
 run_write_region_1(struct run_softc *sc, uint16_t reg, const uint8_t *buf,
     int len)
 {
-#if 1
-       int i, error = 0;
-       /*
-        * NB: the WRITE_REGION_1 command is not stable on RT2860.
-        * We thus issue multiple WRITE_2 commands instead.
-        */
-       KASSERT((len & 1) == 0);
-       for (i = 0; i < len && error == 0; i += 2)
-               error = run_write_2(sc, reg + i, buf[i] | buf[i + 1] << 8);
+       int error = 0;
+       if (sc->sc_flags & RUN_USE_BLOCK_WRITE) {
+               usb_device_request_t req;
+               /*
+                * NOTE: It appears the WRITE_REGION_1 command cannot be
+                * passed a huge amount of data, which will crash the
+                * firmware. Limit amount of data passed to 64 bytes at a
+                * time.
+                */
+               while (len > 0) {
+                       int delta = MIN(len, 64);
+                       req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+                       req.bRequest = RT2870_WRITE_REGION_1;
+                       USETW(req.wValue, 0);
+                       USETW(req.wIndex, reg);
+                       USETW(req.wLength, delta);
+                       error = usbd_do_request(sc->sc_udev, &req,
+                           __UNCONST(buf));
+                       if (error != 0)
+                               break;
+                       reg += delta;
+                       buf += delta;
+                       len -= delta;
+               }
+       } else {
+               /*
+                * NB: the WRITE_REGION_1 command is not stable on RT2860.
+                * We thus issue multiple WRITE_2 commands instead.
+                */
+               int i;
+               KASSERT((len & 1) == 0);
+               for (i = 0; i < len && error == 0; i += 2)
+                       error = run_write_2(sc, reg + i, buf[i] | buf[i + 1] << 8);
+       }
        return error;
-#else
-       usb_device_request_t req;
-
-       req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
-       req.bRequest = RT2870_WRITE_REGION_1;
-       USETW(req.wValue, 0);
-       USETW(req.wIndex, reg);
-       USETW(req.wLength, len);
-       return usbd_do_request(sc->sc_udev, &req, __UNCONST(buf));
-#endif
 }
 
 static int
@@ -1084,8 +1109,25 @@
 {
        int error = 0;
 
-       for (; count > 0 && error == 0; count--, reg += 4)
-               error = run_write(sc, reg, val);
+       if (sc->sc_flags & RUN_USE_BLOCK_WRITE) {
+               while (count > 0) {
+                       int i, delta;
+                       uint32_t tmp[16];
+
+                       delta = MIN(count, __arraycount(tmp));
+                       for (i = 0; i < delta; i++)
+                               tmp[i] = htole32(val);
+                       error = run_write_region_1(sc, reg, (uint8_t *)tmp,
+                           delta * sizeof(uint32_t));
+                       if (error != 0)
+                               break;
+                       reg += delta * sizeof(uint32_t);
+                       count -= delta;
+               }
+       } else {
+               for (; count > 0 && error == 0; count--, reg += 4)
+                       error = run_write(sc, reg, val);
+       }
        return error;
 }
 
diff -r dc84bfb7ca39 -r 187bdd5dd71c sys/dev/usb/if_runvar.h
--- a/sys/dev/usb/if_runvar.h   Sat Jun 06 10:22:45 2020 +0000
+++ b/sys/dev/usb/if_runvar.h   Sat Jun 06 13:53:43 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_runvar.h,v 1.8 2020/03/15 23:04:51 thorpej Exp $    */
+/*     $NetBSD: if_runvar.h,v 1.9 2020/06/06 13:53:43 gson Exp $       */
 /*     $OpenBSD: if_runvar.h,v 1.8 2010/02/08 18:46:47 damien Exp $    */
 
 /*-
@@ -201,8 +201,9 @@
        int                             sc_tx_timer;
        struct ieee80211_beacon_offsets sc_bo;
        int                             sc_flags;
-#define RUN_FWLOADED   (1 << 0)
-#define RUN_DETACHING  (1 << 1)
+#define RUN_FWLOADED           (1 << 0)
+#define RUN_DETACHING          (1 << 1)
+#define RUN_USE_BLOCK_WRITE    (1 << 2)
 
        struct bpf_if *                 sc_drvbpf;
 



Home | Main Index | Thread Index | Old Index