Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Add apmg_wake_up_wa support from DragonFly BSD.



details:   https://anonhg.NetBSD.org/src/rev/4eb95998f9cc
branches:  trunk
changeset: 820456:4eb95998f9cc
user:      nonaka <nonaka%NetBSD.org@localhost>
date:      Tue Jan 10 07:34:04 2017 +0000

description:
Add apmg_wake_up_wa support from DragonFly BSD.

diffstat:

 sys/dev/pci/if_iwm.c    |  95 +++++++++++++++++++++++++++++++++++++++++-------
 sys/dev/pci/if_iwmvar.h |   8 +++-
 2 files changed, 88 insertions(+), 15 deletions(-)

diffs (217 lines):

diff -r 8860b5ad18b5 -r 4eb95998f9cc sys/dev/pci/if_iwm.c
--- a/sys/dev/pci/if_iwm.c      Tue Jan 10 06:28:46 2017 +0000
+++ b/sys/dev/pci/if_iwm.c      Tue Jan 10 07:34:04 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_iwm.c,v 1.58 2017/01/10 05:54:03 nonaka Exp $       */
+/*     $NetBSD: if_iwm.c,v 1.59 2017/01/10 07:34:04 nonaka Exp $       */
 /*     OpenBSD: if_iwm.c,v 1.148 2016/11/19 21:07:08 stsp Exp  */
 #define IEEE80211_NO_HT
 /*
@@ -107,7 +107,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.58 2017/01/10 05:54:03 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.59 2017/01/10 07:34:04 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -1003,6 +1003,9 @@
 {
        int rv = 0;
 
+       if (sc->sc_cmd_hold_nic_awake)
+               return 1;
+
        IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
            IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 
@@ -1025,6 +1028,10 @@
 static void
 iwm_nic_unlock(struct iwm_softc *sc)
 {
+
+       if (sc->sc_cmd_hold_nic_awake)
+               return;
+
        IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
            IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 }
@@ -1284,6 +1291,57 @@
 }
 
 static void
+iwm_clear_cmd_in_flight(struct iwm_softc *sc)
+{
+
+       if (!sc->apmg_wake_up_wa)
+               return;
+
+       if (!sc->sc_cmd_hold_nic_awake) {
+               aprint_error_dev(sc->sc_dev,
+                   "cmd_hold_nic_awake not set\n");
+               return;
+       }
+
+       sc->sc_cmd_hold_nic_awake = 0;
+       IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
+           IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+}
+
+static int
+iwm_set_cmd_in_flight(struct iwm_softc *sc)
+{
+       int ret;
+
+       /*
+        * wake up the NIC to make sure that the firmware will see the host
+        * command - we will let the NIC sleep once all the host commands
+        * returned. This needs to be done only on NICs that have
+        * apmg_wake_up_wa set.
+        */
+       if (sc->apmg_wake_up_wa && !sc->sc_cmd_hold_nic_awake) {
+
+               IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
+                   IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
+               ret = iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
+                   IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
+                   (IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
+                    IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
+                   15000);
+               if (ret == 0) {
+                       IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
+                           IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+                       aprint_error_dev(sc->sc_dev,
+                           "failed to wake NIC for hcmd\n");
+                       return EIO;
+               }
+               sc->sc_cmd_hold_nic_awake = 1;
+       }
+
+       return 0;
+}
+static void
 iwm_reset_tx_ring(struct iwm_softc *sc, struct iwm_tx_ring *ring)
 {
        int i;
@@ -1306,6 +1364,9 @@
        sc->qfullmsk &= ~(1 << ring->qid);
        ring->queued = 0;
        ring->cur = 0;
+
+       if (ring->qid == IWM_CMD_QUEUE && sc->sc_cmd_hold_nic_awake)
+               iwm_clear_cmd_in_flight(sc);
 }
 
 static void
@@ -3861,16 +3922,10 @@
            (char *)(void *)desc - (char *)(void *)ring->desc_dma.vaddr,
            sizeof(*desc), BUS_DMASYNC_PREWRITE);
 
-       IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
-           IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-       if (!iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
-           IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
-           (IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
-            IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000)) {
-               aprint_error_dev(sc->sc_dev, "acquiring device failed\n");
-               err = EBUSY;
+       err = iwm_set_cmd_in_flight(sc);
+       if (err)
                goto out;
-       }
+       ring->queued++;
 
 #if 0
        iwm_update_sched(sc, ring->qid, ring->cur, 0, 0);
@@ -3999,6 +4054,16 @@
                data->m = NULL;
        }
        wakeup(&ring->desc[idx]);
+
+       if (((idx + ring->queued) % IWM_TX_RING_COUNT) != ring->cur) {
+               aprint_error_dev(sc->sc_dev,
+                   "Some HCMDs skipped?: idx=%d queued=%d cur=%d\n",
+                   idx, ring->queued, ring->cur);
+       }
+
+       KASSERT(ring->queued > 0);
+       if (--ring->queued == 0)
+               iwm_clear_cmd_in_flight(sc);
 }
 
 #if 0
@@ -7001,9 +7066,6 @@
                ADVANCE_RXQ(sc);
        }
 
-       IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
-           IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
        /*
         * Seems like the hardware gets upset unless we align the write by 8??
         */
@@ -7349,6 +7411,7 @@
        case PCI_PRODUCT_INTEL_WIFI_LINK_3160_2:
                sc->sc_fwname = "iwlwifi-3160-16.ucode";
                sc->host_interrupt_operation_mode = 1;
+               sc->apmg_wake_up_wa = 1;
                sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
                sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
                break;
@@ -7356,6 +7419,7 @@
        case PCI_PRODUCT_INTEL_WIFI_LINK_3165_2:
                sc->sc_fwname = "iwlwifi-7265D-16.ucode";
                sc->host_interrupt_operation_mode = 0;
+               sc->apmg_wake_up_wa = 1;
                sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
                sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
                break;
@@ -7363,6 +7427,7 @@
        case PCI_PRODUCT_INTEL_WIFI_LINK_7260_2:
                sc->sc_fwname = "iwlwifi-7260-16.ucode";
                sc->host_interrupt_operation_mode = 1;
+               sc->apmg_wake_up_wa = 1;
                sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
                sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
                break;
@@ -7372,6 +7437,7 @@
                    IWM_CSR_HW_REV_TYPE_7265D ?
                    "iwlwifi-7265D-16.ucode": "iwlwifi-7265-16.ucode";
                sc->host_interrupt_operation_mode = 0;
+               sc->apmg_wake_up_wa = 1;
                sc->sc_device_family = IWM_DEVICE_FAMILY_7000;
                sc->sc_fwdmasegsz = IWM_FWDMASEGSZ;
                break;
@@ -7381,6 +7447,7 @@
        case PCI_PRODUCT_INTEL_WIFI_LINK_4165_2:
                sc->sc_fwname = "iwlwifi-8000C-16.ucode";
                sc->host_interrupt_operation_mode = 0;
+               sc->apmg_wake_up_wa = 0;
                sc->sc_device_family = IWM_DEVICE_FAMILY_8000;
                sc->sc_fwdmasegsz = IWM_FWDMASEGSZ_8000;
                break;
diff -r 8860b5ad18b5 -r 4eb95998f9cc sys/dev/pci/if_iwmvar.h
--- a/sys/dev/pci/if_iwmvar.h   Tue Jan 10 06:28:46 2017 +0000
+++ b/sys/dev/pci/if_iwmvar.h   Tue Jan 10 07:34:04 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_iwmvar.h,v 1.12 2017/01/10 05:54:03 nonaka Exp $    */
+/*     $NetBSD: if_iwmvar.h,v 1.13 2017/01/10 07:34:04 nonaka Exp $    */
 /*     OpenBSD: if_iwmvar.h,v 1.24 2016/09/21 13:53:18 stsp Exp        */
 
 /*
@@ -466,7 +466,13 @@
        struct iwm_notif_statistics sc_stats;
        int sc_noise;
 
+       int sc_cmd_hold_nic_awake;
+
+       /* device needs host interrupt operation mode set */
        int host_interrupt_operation_mode;
+       /* should the MAC access REQ be asserted when a command is in flight.
+        * This is due to a HW bug in 7260, 3160 and 7265. */
+       int apmg_wake_up_wa;
 
        struct sysctllog *sc_clog;
 



Home | Main Index | Thread Index | Old Index