Author: kevans Date: Thu Jan 24 03:44:48 2019 New Revision: 343379 URL: https://svnweb.freebsd.org/changeset/base/343379
Log: if_iwm - Configure the PCIe LTR, fix PCI express capability accesses. Taken-From: Linux iwlwifi Submitted by: Augustin Cavalier <waddlespl...@gmail.com> (Haiku) Obtained from: DragonFlyBSD (08a7ad5a5ff65aaaf2df6a609be7a4e1df43efc3) Modified: head/sys/dev/iwm/if_iwm.c head/sys/dev/iwm/if_iwm_pcie_trans.c head/sys/dev/iwm/if_iwmreg.h head/sys/dev/iwm/if_iwmvar.h Modified: head/sys/dev/iwm/if_iwm.c ============================================================================== --- head/sys/dev/iwm/if_iwm.c Thu Jan 24 03:44:20 2019 (r343378) +++ head/sys/dev/iwm/if_iwm.c Thu Jan 24 03:44:48 2019 (r343379) @@ -320,6 +320,7 @@ static int iwm_send_phy_cfg_cmd(struct iwm_softc *); static int iwm_mvm_load_ucode_wait_alive(struct iwm_softc *, enum iwm_ucode_type); static int iwm_run_init_mvm_ucode(struct iwm_softc *, int); +static int iwm_mvm_config_ltr(struct iwm_softc *sc); static int iwm_rx_addbuf(struct iwm_softc *, int, int); static int iwm_mvm_get_signal_strength(struct iwm_softc *, struct iwm_rx_phy_info *); @@ -3000,6 +3001,19 @@ out: return ret; } +static int +iwm_mvm_config_ltr(struct iwm_softc *sc) +{ + struct iwm_ltr_config_cmd cmd = { + .flags = htole32(IWM_LTR_CFG_FLAG_FEATURE_ENABLE), + }; + + if (!sc->sc_ltr_enabled) + return 0; + + return iwm_mvm_send_cmd_pdu(sc, IWM_LTR_CONFIG, 0, sizeof(cmd), &cmd); +} + /* * receive side */ @@ -4665,6 +4679,9 @@ iwm_init_hw(struct iwm_softc *sc) if (sc->cfg->device_family == IWM_DEVICE_FAMILY_7000) iwm_mvm_tt_tx_backoff(sc, 0); + if (iwm_mvm_config_ltr(sc) != 0) + device_printf(sc->sc_dev, "PCIe LTR configuration failed\n"); + error = iwm_mvm_power_update_device(sc); if (error) goto error; @@ -5292,6 +5309,7 @@ iwm_handle_rxb(struct iwm_softc *sc, struct mbuf *m) case IWM_MAC_CONTEXT_CMD: case IWM_REPLY_SF_CFG_CMD: case IWM_POWER_TABLE_CMD: + case IWM_LTR_CONFIG: case IWM_PHY_CONTEXT_CMD: case IWM_BINDING_CONTEXT_CMD: case IWM_TIME_EVENT_CMD: Modified: head/sys/dev/iwm/if_iwm_pcie_trans.c ============================================================================== --- head/sys/dev/iwm/if_iwm_pcie_trans.c Thu Jan 24 03:44:20 2019 (r343378) +++ head/sys/dev/iwm/if_iwm_pcie_trans.c Thu Jan 24 03:44:48 2019 (r343379) @@ -406,18 +406,39 @@ iwm_prepare_card_hw(struct iwm_softc *sc) void iwm_apm_config(struct iwm_softc *sc) { - uint16_t reg; + uint16_t lctl, cap; + int pcie_ptr; - reg = pci_read_config(sc->sc_dev, PCIER_LINK_CTL, sizeof(reg)); - if (reg & PCIEM_LINK_CTL_ASPMC_L1) { - /* Um the Linux driver prints "Disabling L0S for this one ... */ + /* + * HW bug W/A for instability in PCIe bus L0S->L1 transition. + * Check if BIOS (or OS) enabled L1-ASPM on this device. + * If so (likely), disable L0S, so device moves directly L0->L1; + * costs negligible amount of power savings. + * If not (unlikely), enable L0S, so there is at least some + * power savings, even without L1. + */ + int error; + + error = pci_find_cap(sc->sc_dev, PCIY_EXPRESS, &pcie_ptr); + if (error != 0) + return; + lctl = pci_read_config(sc->sc_dev, pcie_ptr + PCIER_LINK_CTL, + sizeof(lctl)); + if (lctl & PCIEM_LINK_CTL_ASPMC_L1) { IWM_SETBITS(sc, IWM_CSR_GIO_REG, IWM_CSR_GIO_REG_VAL_L0S_ENABLED); } else { - /* ... and "Enabling" here */ IWM_CLRBITS(sc, IWM_CSR_GIO_REG, IWM_CSR_GIO_REG_VAL_L0S_ENABLED); } + + cap = pci_read_config(sc->sc_dev, pcie_ptr + PCIER_DEVICE_CTL2, + sizeof(cap)); + sc->sc_ltr_enabled = (cap & PCIEM_CTL2_LTR_ENABLE) ? 1 : 0; + IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_PWRSAVE, + "L1 %sabled - LTR %sabled\n", + (lctl & PCIEM_LINK_CTL_ASPMC_L1) ? "En" : "Dis", + sc->sc_ltr_enabled ? "En" : "Dis"); } /* Modified: head/sys/dev/iwm/if_iwmreg.h ============================================================================== --- head/sys/dev/iwm/if_iwmreg.h Thu Jan 24 03:44:20 2019 (r343378) +++ head/sys/dev/iwm/if_iwmreg.h Thu Jan 24 03:44:48 2019 (r343379) @@ -1790,6 +1790,7 @@ enum { /* Power - legacy power table command */ IWM_POWER_TABLE_CMD = 0x77, IWM_PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78, + IWM_LTR_CONFIG = 0xee, /* Thermal Throttling*/ IWM_REPLY_THERMAL_MNG_BACKOFF = 0x7e, @@ -3521,6 +3522,57 @@ struct iwm_nonqos_seq_query_cmd { */ /* Power Management Commands, Responses, Notifications */ + +/** + * enum iwm_ltr_config_flags - masks for LTR config command flags + * @IWM_LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status + * @IWM_LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow + * memory access + * @IWM_LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR + * reg change + * @IWM_LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from + * D0 to D3 + * @IWM_LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register + * @IWM_LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register + * @IWM_LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD + */ +enum iwm_ltr_config_flags { + IWM_LTR_CFG_FLAG_FEATURE_ENABLE = (1 << 0), + IWM_LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS = (1 << 1), + IWM_LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH = (1 << 2), + IWM_LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3 = (1 << 3), + IWM_LTR_CFG_FLAG_SW_SET_SHORT = (1 << 4), + IWM_LTR_CFG_FLAG_SW_SET_LONG = (1 << 5), + IWM_LTR_CFG_FLAG_DENIE_C10_ON_PD = (1 << 6), +}; + +/** + * struct iwm_ltr_config_cmd_v1 - configures the LTR + * @flags: See %enum iwm_ltr_config_flags + */ +struct iwm_ltr_config_cmd_v1 { + uint32_t flags; + uint32_t static_long; + uint32_t static_short; +} __packed; /* LTR_CAPABLE_API_S_VER_1 */ + +#define IWM_LTR_VALID_STATES_NUM 4 + +/** + * struct iwm_ltr_config_cmd - configures the LTR + * @flags: See %enum iwm_ltr_config_flags + * @static_long: + * @static_short: + * @ltr_cfg_values: + * @ltr_short_idle_timeout: + */ +struct iwm_ltr_config_cmd { + uint32_t flags; + uint32_t static_long; + uint32_t static_short; + uint32_t ltr_cfg_values[IWM_LTR_VALID_STATES_NUM]; + uint32_t ltr_short_idle_timeout; +} __packed; /* LTR_CAPABLE_API_S_VER_2 */ /* Radio LP RX Energy Threshold measured in dBm */ #define IWM_POWER_LPRX_RSSI_THRESHOLD 75 Modified: head/sys/dev/iwm/if_iwmvar.h ============================================================================== --- head/sys/dev/iwm/if_iwmvar.h Thu Jan 24 03:44:20 2019 (r343378) +++ head/sys/dev/iwm/if_iwmvar.h Thu Jan 24 03:44:48 2019 (r343379) @@ -556,6 +556,8 @@ struct iwm_softc { /* Indicate if device power save is allowed */ boolean_t sc_ps_disabled; + + int sc_ltr_enabled; }; #define IWM_LOCK_INIT(_sc) \ _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"