svn commit: r343379 - head/sys/dev/iwm

Kyle Evans kevans at FreeBSD.org
Thu Jan 24 03:44:50 UTC 2019


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 <waddlesplash at 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) \


More information about the svn-src-head mailing list