svn commit: r330175 - stable/11/sys/dev/iwm
Eitan Adler
eadler at FreeBSD.org
Thu Mar 1 05:53:14 UTC 2018
Author: eadler
Date: Thu Mar 1 05:53:12 2018
New Revision: 330175
URL: https://svnweb.freebsd.org/changeset/base/330175
Log:
MFC r313415:
[iwm] Implement apmg_wake_up_wa workaround properly for 7000 family.
* Add iwm_pcie_set_cmd_in_flight() and iwm_pcie_clear_cmd_in_flight()
helper methods.
* Use ring->queued tracking in the command queue to set/clear the
cmd_hold_nic_awake bit at the right points.
Modified:
stable/11/sys/dev/iwm/if_iwm.c
stable/11/sys/dev/iwm/if_iwm_pcie_trans.c
stable/11/sys/dev/iwm/if_iwm_pcie_trans.h
stable/11/sys/dev/iwm/if_iwm_util.c
stable/11/sys/dev/iwm/if_iwmvar.h
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/dev/iwm/if_iwm.c
==============================================================================
--- stable/11/sys/dev/iwm/if_iwm.c Thu Mar 1 05:52:27 2018 (r330174)
+++ stable/11/sys/dev/iwm/if_iwm.c Thu Mar 1 05:53:12 2018 (r330175)
@@ -182,7 +182,8 @@ __FBSDID("$FreeBSD$");
#define IWM_DEVICE_7000_COMMON \
.device_family = IWM_DEVICE_FAMILY_7000, \
.eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000, \
- .nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_7000
+ .nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_7000, \
+ .apmg_wake_up_wa = 1
const struct iwm_cfg iwm7260_cfg = {
.fw_name = IWM7260_FW,
@@ -1251,6 +1252,9 @@ iwm_reset_tx_ring(struct iwm_softc *sc, struct iwm_tx_
sc->qfullmsk &= ~(1 << ring->qid);
ring->queued = 0;
ring->cur = 0;
+
+ if (ring->qid == IWM_MVM_CMD_QUEUE && sc->cmd_hold_nic_awake)
+ iwm_pcie_clear_cmd_in_flight(sc);
}
static void
@@ -3312,6 +3316,18 @@ iwm_cmd_done(struct iwm_softc *sc, struct iwm_rx_packe
data->m = NULL;
}
wakeup(&ring->desc[pkt->hdr.idx]);
+
+ if (((pkt->hdr.idx + ring->queued) % IWM_TX_RING_COUNT) != ring->cur) {
+ device_printf(sc->sc_dev,
+ "%s: Some HCMDs skipped?: idx=%d queued=%d cur=%d\n",
+ __func__, pkt->hdr.idx, ring->queued, ring->cur);
+ /* XXX call iwm_force_nmi() */
+ }
+
+ KASSERT(ring->queued > 0, ("ring->queued is empty?"));
+ ring->queued--;
+ if (ring->queued == 0)
+ iwm_pcie_clear_cmd_in_flight(sc);
}
#if 0
@@ -5553,9 +5569,6 @@ iwm_notif_intr(struct iwm_softc *sc)
ADVANCE_RXQ(sc);
}
-
- IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
- IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/*
* Tell the firmware what we have processed.
Modified: stable/11/sys/dev/iwm/if_iwm_pcie_trans.c
==============================================================================
--- stable/11/sys/dev/iwm/if_iwm_pcie_trans.c Thu Mar 1 05:52:27 2018 (r330174)
+++ stable/11/sys/dev/iwm/if_iwm_pcie_trans.c Thu Mar 1 05:53:12 2018 (r330175)
@@ -253,6 +253,9 @@ iwm_nic_lock(struct iwm_softc *sc)
{
int rv = 0;
+ if (sc->cmd_hold_nic_awake)
+ return 1;
+
IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
@@ -277,6 +280,9 @@ iwm_nic_lock(struct iwm_softc *sc)
void
iwm_nic_unlock(struct iwm_softc *sc)
{
+ if (sc->cmd_hold_nic_awake)
+ return;
+
IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
}
@@ -582,4 +588,56 @@ iwm_pcie_rx_stop(struct iwm_softc *sc)
iwm_nic_unlock(sc);
}
return ret;
+}
+
+void
+iwm_pcie_clear_cmd_in_flight(struct iwm_softc *sc)
+{
+ if (!sc->cfg->apmg_wake_up_wa)
+ return;
+
+ if (!sc->cmd_hold_nic_awake) {
+ device_printf(sc->sc_dev,
+ "%s: cmd_hold_nic_awake not set\n", __func__);
+ return;
+ }
+
+ sc->cmd_hold_nic_awake = 0;
+ IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
+ IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+}
+
+int
+iwm_pcie_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->cfg->apmg_wake_up_wa &&
+ !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);
+ device_printf(sc->sc_dev,
+ "%s: Failed to wake NIC for hcmd\n", __func__);
+ return EIO;
+ }
+ sc->cmd_hold_nic_awake = 1;
+ }
+
+ return 0;
}
Modified: stable/11/sys/dev/iwm/if_iwm_pcie_trans.h
==============================================================================
--- stable/11/sys/dev/iwm/if_iwm_pcie_trans.h Thu Mar 1 05:52:27 2018 (r330174)
+++ stable/11/sys/dev/iwm/if_iwm_pcie_trans.h Thu Mar 1 05:53:12 2018 (r330175)
@@ -129,4 +129,7 @@ extern int iwm_start_hw(struct iwm_softc *sc);
extern void iwm_set_pwr(struct iwm_softc *sc);
extern int iwm_pcie_rx_stop(struct iwm_softc *sc);
+extern int iwm_pcie_set_cmd_in_flight(struct iwm_softc *sc);
+extern void iwm_pcie_clear_cmd_in_flight(struct iwm_softc *sc);
+
#endif
Modified: stable/11/sys/dev/iwm/if_iwm_util.c
==============================================================================
--- stable/11/sys/dev/iwm/if_iwm_util.c Thu Mar 1 05:52:27 2018 (r330174)
+++ stable/11/sys/dev/iwm/if_iwm_util.c Thu Mar 1 05:53:12 2018 (r330175)
@@ -305,17 +305,10 @@ iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd
bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
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)) {
- device_printf(sc->sc_dev,
- "%s: acquiring device failed\n", __func__);
- error = EBUSY;
+ error = iwm_pcie_set_cmd_in_flight(sc);
+ if (error)
goto out;
- }
+ ring->queued++;
#if 0
iwm_update_sched(sc, ring->qid, ring->cur, 0, 0);
Modified: stable/11/sys/dev/iwm/if_iwmvar.h
==============================================================================
--- stable/11/sys/dev/iwm/if_iwmvar.h Thu Mar 1 05:52:27 2018 (r330174)
+++ stable/11/sys/dev/iwm/if_iwmvar.h Thu Mar 1 05:53:12 2018 (r330175)
@@ -389,6 +389,8 @@ enum iwm_device_family {
* @host_interrupt_operation_mode: device needs host interrupt operation
* mode set
* @nvm_hw_section_num: the ID of the HW NVM section
+ * @apmg_wake_up_wa: 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.
*/
struct iwm_cfg {
const char *fw_name;
@@ -396,6 +398,7 @@ struct iwm_cfg {
enum iwm_device_family device_family;
int host_interrupt_operation_mode;
uint8_t nvm_hw_section_num;
+ int apmg_wake_up_wa;
};
struct iwm_softc {
@@ -520,6 +523,8 @@ struct iwm_softc {
int sc_max_rssi;
struct iwm_notif_wait_data *sc_notif_wait;
+
+ int cmd_hold_nic_awake;
};
#define IWM_LOCK_INIT(_sc) \
More information about the svn-src-stable-11
mailing list