aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/iwm
diff options
context:
space:
mode:
authorAdrian Chadd <adrian@FreeBSD.org>2017-06-04 21:10:14 +0000
committerAdrian Chadd <adrian@FreeBSD.org>2017-06-04 21:10:14 +0000
commit19d956ec90801250cecbb72f8eca0a2c4bb2369d (patch)
treeea6c6f3a7b5bddd6d928c26512a705c95b118cff /sys/dev/iwm
parentcd684deca9360b81fd2e83aa0d6d50e01e38768c (diff)
downloadsrc-19d956ec90801250cecbb72f8eca0a2c4bb2369d.tar.gz
src-19d956ec90801250cecbb72f8eca0a2c4bb2369d.zip
[iwm] Check for lar_disable tunable, and lar_enabled flag from NVM.
* LAR can be disabled with the hw.iwm.lar.disable tunable now. * On Family 8000 devices we need to check the lar_enabled flag from nvm_data in addition to the TLV_CAPA_LAR_SUPPORT flag from the firmware. * Add a separate IWM_DEBUG_LAR debugging flag. Obtained from: dragonflybsd.git 0593e39cb295aa996ecf789ed4990c3b255f1770
Notes
Notes: svn path=/head/; revision=319578
Diffstat (limited to 'sys/dev/iwm')
-rw-r--r--sys/dev/iwm/if_iwm.c66
-rw-r--r--sys/dev/iwm/if_iwm_debug.h1
-rw-r--r--sys/dev/iwm/if_iwmvar.h1
3 files changed, 59 insertions, 9 deletions
diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c
index 3231f2d663f9..d6475cf518a3 100644
--- a/sys/dev/iwm/if_iwm.c
+++ b/sys/dev/iwm/if_iwm.c
@@ -356,6 +356,8 @@ static int iwm_media_change(struct ifnet *);
static int iwm_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static void iwm_endscan_cb(void *, int);
static int iwm_send_bt_init_conf(struct iwm_softc *);
+static boolean_t iwm_mvm_is_lar_supported(struct iwm_softc *);
+static boolean_t iwm_mvm_is_wifi_mcc_supported(struct iwm_softc *);
static int iwm_send_update_mcc_cmd(struct iwm_softc *, const char *);
static void iwm_mvm_tt_tx_backoff(struct iwm_softc *, uint32_t);
static int iwm_init_hw(struct iwm_softc *);
@@ -394,6 +396,9 @@ static void iwm_scan_curchan(struct ieee80211_scan_state *, unsigned long);
static void iwm_scan_mindwell(struct ieee80211_scan_state *);
static int iwm_detach(device_t);
+static int iwm_lar_disable = 0;
+TUNABLE_INT("hw.iwm.lar.disable", &iwm_lar_disable);
+
/*
* Firmware parser.
*/
@@ -2186,6 +2191,7 @@ iwm_parse_nvm_data(struct iwm_softc *sc,
{
struct iwm_nvm_data *data;
uint32_t sku, radio_cfg;
+ uint16_t lar_config;
if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) {
data = malloc(sizeof(*data) +
@@ -2211,6 +2217,16 @@ iwm_parse_nvm_data(struct iwm_softc *sc,
data->n_hw_addrs = iwm_get_n_hw_addrs(sc, nvm_sw);
+ if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) {
+ uint16_t lar_offset = data->nvm_version < 0xE39 ?
+ IWM_NVM_LAR_OFFSET_8000_OLD :
+ IWM_NVM_LAR_OFFSET_8000;
+
+ lar_config = le16_to_cpup(regulatory + lar_offset);
+ data->lar_enabled = !!(lar_config &
+ IWM_NVM_LAR_ENABLED_8000);
+ }
+
/* If no valid mac address was found - bail out */
if (iwm_set_hw_address(sc, data, nvm_hw, mac_override)) {
free(data, M_DEVBUF);
@@ -4507,6 +4523,35 @@ iwm_send_bt_init_conf(struct iwm_softc *sc)
&bt_cmd);
}
+static boolean_t
+iwm_mvm_is_lar_supported(struct iwm_softc *sc)
+{
+ boolean_t nvm_lar = sc->nvm_data->lar_enabled;
+ boolean_t tlv_lar = fw_has_capa(&sc->ucode_capa,
+ IWM_UCODE_TLV_CAPA_LAR_SUPPORT);
+
+ if (iwm_lar_disable)
+ return FALSE;
+
+ /*
+ * Enable LAR only if it is supported by the FW (TLV) &&
+ * enabled in the NVM
+ */
+ if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000)
+ return nvm_lar && tlv_lar;
+ else
+ return tlv_lar;
+}
+
+static boolean_t
+iwm_mvm_is_wifi_mcc_supported(struct iwm_softc *sc)
+{
+ return fw_has_api(&sc->ucode_capa,
+ IWM_UCODE_TLV_API_WIFI_MCC_UPDATE) ||
+ fw_has_capa(&sc->ucode_capa,
+ IWM_UCODE_TLV_CAPA_LAR_MULTI_MCC);
+}
+
static int
iwm_send_update_mcc_cmd(struct iwm_softc *sc, const char *alpha2)
{
@@ -4527,10 +4572,15 @@ iwm_send_update_mcc_cmd(struct iwm_softc *sc, const char *alpha2)
int resp_v2 = fw_has_capa(&sc->ucode_capa,
IWM_UCODE_TLV_CAPA_LAR_SUPPORT_V2);
+ if (!iwm_mvm_is_lar_supported(sc)) {
+ IWM_DPRINTF(sc, IWM_DEBUG_LAR, "%s: no LAR support\n",
+ __func__);
+ return 0;
+ }
+
memset(&mcc_cmd, 0, sizeof(mcc_cmd));
mcc_cmd.mcc = htole16(alpha2[0] << 8 | alpha2[1]);
- if (fw_has_api(&sc->ucode_capa, IWM_UCODE_TLV_API_WIFI_MCC_UPDATE) ||
- fw_has_capa(&sc->ucode_capa, IWM_UCODE_TLV_CAPA_LAR_MULTI_MCC))
+ if (iwm_mvm_is_wifi_mcc_supported(sc))
mcc_cmd.source_id = IWM_MCC_SOURCE_GET_CURRENT;
else
mcc_cmd.source_id = IWM_MCC_SOURCE_OLD_FW;
@@ -4540,7 +4590,7 @@ iwm_send_update_mcc_cmd(struct iwm_softc *sc, const char *alpha2)
else
hcmd.len[0] = sizeof(struct iwm_mcc_update_cmd_v1);
- IWM_DPRINTF(sc, IWM_DEBUG_NODE,
+ IWM_DPRINTF(sc, IWM_DEBUG_LAR,
"send MCC update to FW with '%c%c' src = %d\n",
alpha2[0], alpha2[1], mcc_cmd.source_id);
@@ -4566,7 +4616,7 @@ iwm_send_update_mcc_cmd(struct iwm_softc *sc, const char *alpha2)
if (mcc == 0)
mcc = 0x3030; /* "00" - world */
- IWM_DPRINTF(sc, IWM_DEBUG_NODE,
+ IWM_DPRINTF(sc, IWM_DEBUG_LAR,
"regulatory domain '%c%c' (%d channels available)\n",
mcc >> 8, mcc & 0xff, n_channels);
#endif
@@ -4675,10 +4725,8 @@ iwm_init_hw(struct iwm_softc *sc)
if (error)
goto error;
- if (fw_has_capa(&sc->ucode_capa, IWM_UCODE_TLV_CAPA_LAR_SUPPORT)) {
- if ((error = iwm_send_update_mcc_cmd(sc, "ZZ")) != 0)
- goto error;
- }
+ if ((error = iwm_send_update_mcc_cmd(sc, "ZZ")) != 0)
+ goto error;
if (fw_has_capa(&sc->ucode_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) {
if ((error = iwm_mvm_config_umac_scan(sc)) != 0)
@@ -5275,7 +5323,7 @@ iwm_handle_rxb(struct iwm_softc *sc, struct mbuf *m)
sc->sc_fw_mcc[0] = (notif->mcc & 0xff00) >> 8;
sc->sc_fw_mcc[1] = notif->mcc & 0xff;
sc->sc_fw_mcc[2] = '\0';
- IWM_DPRINTF(sc, IWM_DEBUG_RESET,
+ IWM_DPRINTF(sc, IWM_DEBUG_LAR,
"fw source %d sent CC '%s'\n",
notif->source_id, sc->sc_fw_mcc);
break;
diff --git a/sys/dev/iwm/if_iwm_debug.h b/sys/dev/iwm/if_iwm_debug.h
index 94101eaf1736..2a2ac731288d 100644
--- a/sys/dev/iwm/if_iwm_debug.h
+++ b/sys/dev/iwm/if_iwm_debug.h
@@ -43,6 +43,7 @@ enum {
IWM_DEBUG_EEPROM = 0x00080000, /* EEPROM/channel information */
IWM_DEBUG_TEMP = 0x00100000, /* Thermal Sensor handling */
IWM_DEBUG_FW = 0x00200000, /* Firmware management */
+ IWM_DEBUG_LAR = 0x00400000, /* Location Aware Regulatory */
IWM_DEBUG_REGISTER = 0x20000000, /* print chipset register */
IWM_DEBUG_TRACE = 0x40000000, /* Print begin and start driver function */
IWM_DEBUG_FATAL = 0x80000000, /* fatal errors */
diff --git a/sys/dev/iwm/if_iwmvar.h b/sys/dev/iwm/if_iwmvar.h
index 6d6b477006a4..d2bf48d6ab44 100644
--- a/sys/dev/iwm/if_iwmvar.h
+++ b/sys/dev/iwm/if_iwmvar.h
@@ -232,6 +232,7 @@ struct iwm_nvm_data {
uint16_t nvm_version;
uint8_t max_tx_pwr_half_dbm;
+ boolean_t lar_enabled;
uint16_t nvm_ch_flags[];
};