idualwifi7260: Upgrade to FreeBSD 12.

Tested on a 7265D.
This commit is contained in:
Augustin Cavalier
2019-01-07 20:17:53 -05:00
parent bf3654699e
commit 86734cc40e
38 changed files with 794 additions and 386 deletions
@@ -14,5 +14,7 @@ SubInclude HAIKU_TOP src add-ons kernel drivers network wlan realtekwifi ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wlan wavelanwifi ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan wavelanwifi ;
# FreeBSD 11.2 drivers # FreeBSD 11.2 drivers
SubInclude HAIKU_TOP src add-ons kernel drivers network wlan idualwifi7260 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi2200 ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi2200 ;
# FreeBSD 12 drivers
SubInclude HAIKU_TOP src add-ons kernel drivers network wlan idualwifi7260 ;
@@ -28,6 +28,7 @@ KernelAddon idualwifi7260 :
if_iwm_phy_db.c if_iwm_phy_db.c
if_iwm_power.c if_iwm_power.c
if_iwm_scan.c if_iwm_scan.c
if_iwm_sf.c
if_iwm_sta.c if_iwm_sta.c
if_iwm_time_event.c if_iwm_time_event.c
if_iwm_util.c if_iwm_util.c
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm.c 330784 2018-03-11 22:49:46Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm.c 339038 2018-10-01 10:44:33Z bz $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -164,6 +164,7 @@ __FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm.c 330784 2018-03-11 22:49:46Z
#include <dev/iwm/if_iwm_time_event.h> #include <dev/iwm/if_iwm_time_event.h>
#include <dev/iwm/if_iwm_power.h> #include <dev/iwm/if_iwm_power.h>
#include <dev/iwm/if_iwm_scan.h> #include <dev/iwm/if_iwm_scan.h>
#include <dev/iwm/if_iwm_sf.h>
#include <dev/iwm/if_iwm_sta.h> #include <dev/iwm/if_iwm_sta.h>
#include <dev/iwm/if_iwm_pcie_trans.h> #include <dev/iwm/if_iwm_pcie_trans.h>
@@ -230,8 +231,8 @@ struct iwm_nvm_section {
uint8_t *data; uint8_t *data;
}; };
#define IWM_MVM_UCODE_ALIVE_TIMEOUT (10*hz) #define IWM_MVM_UCODE_ALIVE_TIMEOUT (5*hz)
#define IWM_MVM_UCODE_CALIB_TIMEOUT (2*hz) #define IWM_MVM_UCODE_CALIB_TIMEOUT (10*hz)
struct iwm_mvm_alive_data { struct iwm_mvm_alive_data {
int valid; int valid;
@@ -348,7 +349,6 @@ static int iwm_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *); const struct ieee80211_bpf_params *);
static int iwm_mvm_update_quotas(struct iwm_softc *, struct iwm_vap *); static int iwm_mvm_update_quotas(struct iwm_softc *, struct iwm_vap *);
static int iwm_auth(struct ieee80211vap *, struct iwm_softc *); static int iwm_auth(struct ieee80211vap *, struct iwm_softc *);
static int iwm_assoc(struct ieee80211vap *, struct iwm_softc *);
static int iwm_release(struct iwm_softc *, struct iwm_node *); static int iwm_release(struct iwm_softc *, struct iwm_node *);
static struct ieee80211_node * static struct ieee80211_node *
iwm_node_alloc(struct ieee80211vap *, iwm_node_alloc(struct ieee80211vap *,
@@ -357,10 +357,6 @@ static void iwm_setrates(struct iwm_softc *, struct iwm_node *);
static int iwm_media_change(struct ifnet *); static int iwm_media_change(struct ifnet *);
static int iwm_newstate(struct ieee80211vap *, enum ieee80211_state, int); static int iwm_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static void iwm_endscan_cb(void *, int); static void iwm_endscan_cb(void *, int);
static void iwm_mvm_fill_sf_command(struct iwm_softc *,
struct iwm_sf_cfg_cmd *,
struct ieee80211_node *);
static int iwm_mvm_sf_config(struct iwm_softc *, enum iwm_sf_state);
static int iwm_send_bt_init_conf(struct iwm_softc *); 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_lar_supported(struct iwm_softc *);
static boolean_t iwm_mvm_is_wifi_mcc_supported(struct iwm_softc *); static boolean_t iwm_mvm_is_wifi_mcc_supported(struct iwm_softc *);
@@ -547,12 +543,14 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
{ {
struct iwm_fw_info *fw = &sc->sc_fw; struct iwm_fw_info *fw = &sc->sc_fw;
const struct iwm_tlv_ucode_header *uhdr; const struct iwm_tlv_ucode_header *uhdr;
struct iwm_ucode_tlv tlv; const struct iwm_ucode_tlv *tlv;
struct iwm_ucode_capabilities *capa = &sc->ucode_capa; struct iwm_ucode_capabilities *capa = &sc->ucode_capa;
enum iwm_ucode_tlv_type tlv_type; enum iwm_ucode_tlv_type tlv_type;
const struct firmware *fwp; const struct firmware *fwp;
const uint8_t *data; const uint8_t *data;
uint32_t tlv_len;
uint32_t usniffer_img; uint32_t usniffer_img;
const uint8_t *tlv_data;
uint32_t paging_mem_size; uint32_t paging_mem_size;
int num_of_cpus; int num_of_cpus;
int error = 0; int error = 0;
@@ -605,24 +603,20 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
goto out; goto out;
} }
snprintf(sc->sc_fwver, sizeof(sc->sc_fwver), "%d.%d (API ver %d)", snprintf(sc->sc_fwver, sizeof(sc->sc_fwver), "%u.%u (API ver %u)",
IWM_UCODE_MAJOR(le32toh(uhdr->ver)), IWM_UCODE_MAJOR(le32toh(uhdr->ver)),
IWM_UCODE_MINOR(le32toh(uhdr->ver)), IWM_UCODE_MINOR(le32toh(uhdr->ver)),
IWM_UCODE_API(le32toh(uhdr->ver))); IWM_UCODE_API(le32toh(uhdr->ver)));
data = uhdr->data; data = uhdr->data;
len = fw->fw_fp->datasize - sizeof(*uhdr); len = fw->fw_fp->datasize - sizeof(*uhdr);
while (len >= sizeof(tlv)) { while (len >= sizeof(*tlv)) {
size_t tlv_len; len -= sizeof(*tlv);
const void *tlv_data; tlv = (const void *)data;
memcpy(&tlv, data, sizeof(tlv)); tlv_len = le32toh(tlv->length);
tlv_len = le32toh(tlv.length); tlv_type = le32toh(tlv->type);
tlv_type = le32toh(tlv.type); tlv_data = tlv->data;
len -= sizeof(tlv);
data += sizeof(tlv);
tlv_data = data;
if (len < tlv_len) { if (len < tlv_len) {
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
@@ -631,19 +625,21 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
error = EINVAL; error = EINVAL;
goto parse_out; goto parse_out;
} }
len -= roundup2(tlv_len, 4);
data += sizeof(tlv) + roundup2(tlv_len, 4);
switch ((int)tlv_type) { switch ((int)tlv_type) {
case IWM_UCODE_TLV_PROBE_MAX_LEN: case IWM_UCODE_TLV_PROBE_MAX_LEN:
if (tlv_len < sizeof(uint32_t)) { if (tlv_len != sizeof(uint32_t)) {
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
"%s: PROBE_MAX_LEN (%d) < sizeof(uint32_t)\n", "%s: PROBE_MAX_LEN (%d) != sizeof(uint32_t)\n",
__func__, __func__,
(int) tlv_len); (int) tlv_len);
error = EINVAL; error = EINVAL;
goto parse_out; goto parse_out;
} }
capa->max_probe_length = capa->max_probe_length =
le32toh(*(const uint32_t *)tlv_data); le32_to_cpup((const uint32_t *)tlv_data);
/* limit it to something sensible */ /* limit it to something sensible */
if (capa->max_probe_length > if (capa->max_probe_length >
IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE) { IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE) {
@@ -674,6 +670,14 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
error = EINVAL; error = EINVAL;
goto parse_out; goto parse_out;
} }
if (tlv_len % sizeof(uint32_t)) {
device_printf(sc->sc_dev,
"%s: IWM_UCODE_TLV_FLAGS: tlv_len (%d) %% sizeof(uint32_t)\n",
__func__,
(int) tlv_len);
error = EINVAL;
goto parse_out;
}
/* /*
* Apparently there can be many flags, but Linux driver * Apparently there can be many flags, but Linux driver
* parses only the first one, and so do we. * parses only the first one, and so do we.
@@ -685,7 +689,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
* 2) TLV_FLAGS contains TLV_FLAGS_PAN * 2) TLV_FLAGS contains TLV_FLAGS_PAN
* ==> this resets TLV_PAN to itself... hnnnk * ==> this resets TLV_PAN to itself... hnnnk
*/ */
capa->flags = le32toh(*(const uint32_t *)tlv_data); capa->flags = le32_to_cpup((const uint32_t *)tlv_data);
break; break;
case IWM_UCODE_TLV_CSCHEME: case IWM_UCODE_TLV_CSCHEME:
if ((error = iwm_store_cscheme(sc, if ((error = iwm_store_cscheme(sc,
@@ -706,7 +710,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
error = EINVAL; error = EINVAL;
goto parse_out; goto parse_out;
} }
num_of_cpus = le32toh(*(const uint32_t *)tlv_data); num_of_cpus = le32_to_cpup((const uint32_t *)tlv_data);
if (num_of_cpus == 2) { if (num_of_cpus == 2) {
fw->fw_sects[IWM_UCODE_REGULAR].is_dual_cpus = fw->fw_sects[IWM_UCODE_REGULAR].is_dual_cpus =
TRUE; TRUE;
@@ -780,7 +784,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
goto parse_out; goto parse_out;
} }
sc->sc_fw.phy_config = sc->sc_fw.phy_config =
le32toh(*(const uint32_t *)tlv_data); le32_to_cpup((const uint32_t *)tlv_data);
sc->sc_fw.valid_tx_ant = (sc->sc_fw.phy_config & sc->sc_fw.valid_tx_ant = (sc->sc_fw.phy_config &
IWM_FW_PHY_CFG_TX_CHAIN) >> IWM_FW_PHY_CFG_TX_CHAIN) >>
IWM_FW_PHY_CFG_TX_CHAIN_POS; IWM_FW_PHY_CFG_TX_CHAIN_POS;
@@ -831,7 +835,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
error = EINVAL; error = EINVAL;
goto parse_out; goto parse_out;
} }
paging_mem_size = le32toh(*(const uint32_t *)tlv_data); paging_mem_size = le32_to_cpup((const uint32_t *)tlv_data);
IWM_DPRINTF(sc, IWM_DEBUG_FIRMWARE_TLV, IWM_DPRINTF(sc, IWM_DEBUG_FIRMWARE_TLV,
"%s: Paging: paging enabled (size = %u bytes)\n", "%s: Paging: paging enabled (size = %u bytes)\n",
@@ -864,7 +868,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
goto parse_out; goto parse_out;
} }
capa->n_scan_channels = capa->n_scan_channels =
le32toh(*(const uint32_t *)tlv_data); le32_to_cpup((const uint32_t *)tlv_data);
break; break;
case IWM_UCODE_TLV_FW_VERSION: case IWM_UCODE_TLV_FW_VERSION:
@@ -889,9 +893,6 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
error = EINVAL; error = EINVAL;
goto parse_out; goto parse_out;
} }
len -= roundup(tlv_len, 4);
data += roundup(tlv_len, 4);
} }
KASSERT(error == 0, ("unhandled error")); KASSERT(error == 0, ("unhandled error"));
@@ -1439,10 +1440,10 @@ iwm_nic_rx_init(struct iwm_softc *sc)
IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG,
IWM_FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | IWM_FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
IWM_FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | /* HW bug */ IWM_FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | /* HW bug */
//#ifdef __HAIKU__ #ifdef __HAIKU__
/* multi-frame RX seems to cause UAFs and double-frees */ /* multi-frame RX seems to cause UAFs and double-frees */
IWM_FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | IWM_FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
//#endif #endif
IWM_FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | IWM_FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K | IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K |
(IWM_RX_RB_TIMEOUT << IWM_FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) | (IWM_RX_RB_TIMEOUT << IWM_FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) |
@@ -3004,11 +3005,6 @@ iwm_run_init_mvm_ucode(struct iwm_softc *sc, int justnvm)
goto error; goto error;
} }
/* Init Smart FIFO. */
ret = iwm_mvm_sf_config(sc, IWM_SF_INIT_OFF);
if (ret)
goto error;
/* Send TX valid antennas before triggering calibrations */ /* Send TX valid antennas before triggering calibrations */
ret = iwm_send_tx_ant_cfg(sc, iwm_mvm_get_valid_tx_ant(sc)); ret = iwm_send_tx_ant_cfg(sc, iwm_mvm_get_valid_tx_ant(sc));
if (ret) { if (ret) {
@@ -3265,8 +3261,11 @@ iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *m, uint32_t offset,
/* rssi is in 1/2db units */ /* rssi is in 1/2db units */
rxs.c_rssi = rssi * 2; rxs.c_rssi = rssi * 2;
rxs.c_nf = sc->sc_noise; rxs.c_nf = sc->sc_noise;
if (ieee80211_add_rx_params(m, &rxs) == 0) if (ieee80211_add_rx_params(m, &rxs) == 0) {
if (ni)
ieee80211_free_node(ni);
goto fail; goto fail;
}
if (ieee80211_radiotap_active_vap(vap)) { if (ieee80211_radiotap_active_vap(vap)) {
struct iwm_rx_radiotap_header *tap = &sc->sc_rxtap; struct iwm_rx_radiotap_header *tap = &sc->sc_rxtap;
@@ -3313,7 +3312,8 @@ iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *m, uint32_t offset,
return TRUE; return TRUE;
fail: counter_u64_add(ic->ic_ierrors, 1); fail:
counter_u64_add(ic->ic_ierrors, 1);
return FALSE; return FALSE;
} }
@@ -3557,7 +3557,9 @@ iwm_tx_fill_cmd(struct iwm_softc *sc, struct iwm_node *in,
tx->rts_retry_limit = IWM_RTS_DFAULT_RETRY_LIMIT; tx->rts_retry_limit = IWM_RTS_DFAULT_RETRY_LIMIT;
tx->data_retry_limit = IWM_DEFAULT_TX_RETRY; tx->data_retry_limit = IWM_DEFAULT_TX_RETRY;
if (type == IEEE80211_FC0_TYPE_MGT) { if (type == IEEE80211_FC0_TYPE_MGT ||
type == IEEE80211_FC0_TYPE_CTL ||
(m->m_flags & M_EAPOL) != 0) {
ridx = iwm_tx_rateidx_global_lookup(sc, tp->mgmtrate); ridx = iwm_tx_rateidx_global_lookup(sc, tp->mgmtrate);
IWM_DPRINTF(sc, IWM_DEBUG_TXRATE, IWM_DPRINTF(sc, IWM_DEBUG_TXRATE,
"%s: MGT (%d)\n", __func__, tp->mgmtrate); "%s: MGT (%d)\n", __func__, tp->mgmtrate);
@@ -3569,11 +3571,7 @@ iwm_tx_fill_cmd(struct iwm_softc *sc, struct iwm_node *in,
ridx = iwm_tx_rateidx_global_lookup(sc, tp->ucastrate); ridx = iwm_tx_rateidx_global_lookup(sc, tp->ucastrate);
IWM_DPRINTF(sc, IWM_DEBUG_TXRATE, IWM_DPRINTF(sc, IWM_DEBUG_TXRATE,
"%s: FIXED_RATE (%d)\n", __func__, tp->ucastrate); "%s: FIXED_RATE (%d)\n", __func__, tp->ucastrate);
} else if (m->m_flags & M_EAPOL) { } else {
ridx = iwm_tx_rateidx_global_lookup(sc, tp->mgmtrate);
IWM_DPRINTF(sc, IWM_DEBUG_TXRATE,
"%s: EAPOL\n", __func__);
} else if (type == IEEE80211_FC0_TYPE_DATA) {
int i; int i;
/* for data frames, use RS table */ /* for data frames, use RS table */
@@ -3590,10 +3588,6 @@ iwm_tx_fill_cmd(struct iwm_softc *sc, struct iwm_node *in,
IWM_DPRINTF(sc, IWM_DEBUG_XMIT | IWM_DEBUG_TXRATE, IWM_DPRINTF(sc, IWM_DEBUG_XMIT | IWM_DEBUG_TXRATE,
"%s: start with i=%d, txrate %d\n", "%s: start with i=%d, txrate %d\n",
__func__, i, iwm_rates[ridx].rate); __func__, i, iwm_rates[ridx].rate);
} else {
ridx = iwm_tx_rateidx_global_lookup(sc, tp->mgmtrate);
IWM_DPRINTF(sc, IWM_DEBUG_TXRATE, "%s: DEFAULT (%d)\n",
__func__, tp->mgmtrate);
} }
IWM_DPRINTF(sc, IWM_DEBUG_XMIT | IWM_DEBUG_TXRATE, IWM_DPRINTF(sc, IWM_DEBUG_XMIT | IWM_DEBUG_TXRATE,
@@ -4016,10 +4010,6 @@ iwm_auth(struct ieee80211vap *vap, struct iwm_softc *sc)
goto out; goto out;
} }
error = iwm_mvm_sf_config(sc, IWM_SF_FULL_ON);
if (error != 0)
return error;
error = iwm_allow_mcast(vap, sc); error = iwm_allow_mcast(vap, sc);
if (error) { if (error) {
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
@@ -4048,6 +4038,14 @@ iwm_auth(struct ieee80211vap *vap, struct iwm_softc *sc)
"%s: failed to update MAC\n", __func__); "%s: failed to update MAC\n", __func__);
goto out; goto out;
} }
} else {
if ((error = iwm_mvm_mac_ctxt_add(sc, vap)) != 0) {
device_printf(sc->sc_dev,
"%s: failed to add MAC\n", __func__);
goto out;
}
}
if ((error = iwm_mvm_phy_ctxt_changed(sc, &sc->sc_phyctxt[0], if ((error = iwm_mvm_phy_ctxt_changed(sc, &sc->sc_phyctxt[0],
in->in_ni.ni_chan, 1, 1)) != 0) { in->in_ni.ni_chan, 1, 1)) != 0) {
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
@@ -4061,43 +4059,25 @@ iwm_auth(struct ieee80211vap *vap, struct iwm_softc *sc)
"%s: binding update cmd\n", __func__); "%s: binding update cmd\n", __func__);
goto out; goto out;
} }
if ((error = iwm_mvm_update_sta(sc, in)) != 0) { /*
device_printf(sc->sc_dev, * Authentication becomes unreliable when powersaving is left enabled
"%s: failed to update sta\n", __func__); * here. Powersaving will be activated again when association has
goto out; * finished or is aborted.
} */
} else { iv->ps_disabled = TRUE;
if ((error = iwm_mvm_mac_ctxt_add(sc, vap)) != 0) { error = iwm_mvm_power_update_mac(sc);
device_printf(sc->sc_dev, iv->ps_disabled = FALSE;
"%s: failed to add MAC\n", __func__); if (error != 0) {
goto out;
}
if ((error = iwm_mvm_power_update_mac(sc)) != 0) {
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
"%s: failed to update power management\n", "%s: failed to update power management\n",
__func__); __func__);
goto out; goto out;
} }
if ((error = iwm_mvm_phy_ctxt_changed(sc, &sc->sc_phyctxt[0],
in->in_ni.ni_chan, 1, 1)) != 0) {
device_printf(sc->sc_dev,
"%s: failed add phy ctxt!\n", __func__);
error = ETIMEDOUT;
goto out;
}
iv->phy_ctxt = &sc->sc_phyctxt[0];
if ((error = iwm_mvm_binding_add_vif(sc, iv)) != 0) {
device_printf(sc->sc_dev,
"%s: binding add cmd\n", __func__);
goto out;
}
if ((error = iwm_mvm_add_sta(sc, in)) != 0) { if ((error = iwm_mvm_add_sta(sc, in)) != 0) {
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
"%s: failed to add sta\n", __func__); "%s: failed to add sta\n", __func__);
goto out; goto out;
} }
}
/* /*
* Prevent the FW from wandering off channel during association * Prevent the FW from wandering off channel during association
@@ -4114,28 +4094,6 @@ out:
return (error); return (error);
} }
static int
iwm_assoc(struct ieee80211vap *vap, struct iwm_softc *sc)
{
struct iwm_node *in = IWM_NODE(vap->iv_bss);
int error;
if ((error = iwm_mvm_update_sta(sc, in)) != 0) {
device_printf(sc->sc_dev,
"%s: failed to update STA\n", __func__);
return error;
}
in->in_assoc = 1;
if ((error = iwm_mvm_mac_ctxt_changed(sc, vap)) != 0) {
device_printf(sc->sc_dev,
"%s: failed to update MAC\n", __func__);
return error;
}
return 0;
}
static int static int
iwm_release(struct iwm_softc *sc, struct iwm_node *in) iwm_release(struct iwm_softc *sc, struct iwm_node *in)
{ {
@@ -4472,6 +4430,12 @@ iwm_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
__func__, error); __func__, error);
} }
ivp->phy_ctxt = NULL; ivp->phy_ctxt = NULL;
error = iwm_mvm_power_update_mac(sc);
if (error != 0) {
device_printf(sc->sc_dev,
"%s: failed to update power management\n",
__func__);
}
IWM_UNLOCK(sc); IWM_UNLOCK(sc);
IEEE80211_LOCK(ic); IEEE80211_LOCK(ic);
return myerr; return myerr;
@@ -4483,33 +4447,38 @@ iwm_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
"%s: could not move to auth state: %d\n", "%s: could not move to auth state: %d\n",
__func__, error); __func__, error);
break;
} }
break; break;
case IEEE80211_S_ASSOC: case IEEE80211_S_ASSOC:
if ((error = iwm_assoc(vap, sc)) != 0) { /*
device_printf(sc->sc_dev, * EBS may be disabled due to previous failures reported by FW.
"%s: failed to associate: %d\n", __func__, * Reset EBS status here assuming environment has been changed.
error); */
break; sc->last_ebs_successful = TRUE;
}
break; break;
case IEEE80211_S_RUN: case IEEE80211_S_RUN:
in = IWM_NODE(vap->iv_bss);
/* Update the association state, now we have it all */ /* Update the association state, now we have it all */
/* (eg associd comes in at this point */ /* (eg associd comes in at this point */
error = iwm_assoc(vap, sc); error = iwm_mvm_update_sta(sc, in);
if (error != 0) { if (error != 0) {
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
"%s: failed to update association state: %d\n", "%s: failed to update STA\n", __func__);
__func__, IWM_UNLOCK(sc);
error); IEEE80211_LOCK(ic);
break; return error;
}
in->in_assoc = 1;
error = iwm_mvm_mac_ctxt_changed(sc, vap);
if (error != 0) {
device_printf(sc->sc_dev,
"%s: failed to update MAC: %d\n", __func__, error);
} }
in = IWM_NODE(vap->iv_bss); iwm_mvm_sf_update(sc, vap, FALSE);
iwm_mvm_enable_beacon_filter(sc, in); iwm_mvm_enable_beacon_filter(sc, ivp);
iwm_mvm_power_update_mac(sc); iwm_mvm_power_update_mac(sc);
iwm_mvm_update_quotas(sc, ivp); iwm_mvm_update_quotas(sc, ivp);
iwm_setrates(sc, in); iwm_setrates(sc, in);
@@ -4544,142 +4513,6 @@ iwm_endscan_cb(void *arg, int pending)
ieee80211_scan_done(TAILQ_FIRST(&ic->ic_vaps)); ieee80211_scan_done(TAILQ_FIRST(&ic->ic_vaps));
} }
/*
* Aging and idle timeouts for the different possible scenarios
* in default configuration
*/
static const uint32_t
iwm_sf_full_timeout_def[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
{
htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER_DEF),
htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_AGG_UNICAST_AGING_TIMER_DEF),
htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_MCAST_AGING_TIMER_DEF),
htole32(IWM_SF_MCAST_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_BA_AGING_TIMER_DEF),
htole32(IWM_SF_BA_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_TX_RE_AGING_TIMER_DEF),
htole32(IWM_SF_TX_RE_IDLE_TIMER_DEF)
},
};
/*
* Aging and idle timeouts for the different possible scenarios
* in single BSS MAC configuration.
*/
static const uint32_t
iwm_sf_full_timeout[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
{
htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER),
htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER)
},
{
htole32(IWM_SF_AGG_UNICAST_AGING_TIMER),
htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER)
},
{
htole32(IWM_SF_MCAST_AGING_TIMER),
htole32(IWM_SF_MCAST_IDLE_TIMER)
},
{
htole32(IWM_SF_BA_AGING_TIMER),
htole32(IWM_SF_BA_IDLE_TIMER)
},
{
htole32(IWM_SF_TX_RE_AGING_TIMER),
htole32(IWM_SF_TX_RE_IDLE_TIMER)
},
};
static void
iwm_mvm_fill_sf_command(struct iwm_softc *sc, struct iwm_sf_cfg_cmd *sf_cmd,
struct ieee80211_node *ni)
{
int i, j, watermark;
sf_cmd->watermark[IWM_SF_LONG_DELAY_ON] = htole32(IWM_SF_W_MARK_SCAN);
/*
* If we are in association flow - check antenna configuration
* capabilities of the AP station, and choose the watermark accordingly.
*/
if (ni) {
if (ni->ni_flags & IEEE80211_NODE_HT) {
#ifdef notyet
if (ni->ni_rxmcs[2] != 0)
watermark = IWM_SF_W_MARK_MIMO3;
else if (ni->ni_rxmcs[1] != 0)
watermark = IWM_SF_W_MARK_MIMO2;
else
#endif
watermark = IWM_SF_W_MARK_SISO;
} else {
watermark = IWM_SF_W_MARK_LEGACY;
}
/* default watermark value for unassociated mode. */
} else {
watermark = IWM_SF_W_MARK_MIMO2;
}
sf_cmd->watermark[IWM_SF_FULL_ON] = htole32(watermark);
for (i = 0; i < IWM_SF_NUM_SCENARIO; i++) {
for (j = 0; j < IWM_SF_NUM_TIMEOUT_TYPES; j++) {
sf_cmd->long_delay_timeouts[i][j] =
htole32(IWM_SF_LONG_DELAY_AGING_TIMER);
}
}
if (ni) {
memcpy(sf_cmd->full_on_timeouts, iwm_sf_full_timeout,
sizeof(iwm_sf_full_timeout));
} else {
memcpy(sf_cmd->full_on_timeouts, iwm_sf_full_timeout_def,
sizeof(iwm_sf_full_timeout_def));
}
}
static int
iwm_mvm_sf_config(struct iwm_softc *sc, enum iwm_sf_state new_state)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwm_sf_cfg_cmd sf_cmd = {
.state = htole32(IWM_SF_FULL_ON),
};
int ret = 0;
if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000)
sf_cmd.state |= htole32(IWM_SF_CFG_DUMMY_NOTIF_OFF);
switch (new_state) {
case IWM_SF_UNINIT:
case IWM_SF_INIT_OFF:
iwm_mvm_fill_sf_command(sc, &sf_cmd, NULL);
break;
case IWM_SF_FULL_ON:
iwm_mvm_fill_sf_command(sc, &sf_cmd, vap->iv_bss);
break;
default:
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE,
"Invalid state: %d. not sending Smart Fifo cmd\n",
new_state);
return EINVAL;
}
ret = iwm_mvm_send_cmd_pdu(sc, IWM_REPLY_SF_CFG_CMD, IWM_CMD_ASYNC,
sizeof(sf_cmd), &sf_cmd);
return ret;
}
static int static int
iwm_send_bt_init_conf(struct iwm_softc *sc) iwm_send_bt_init_conf(struct iwm_softc *sc)
{ {
@@ -4815,6 +4648,8 @@ iwm_init_hw(struct iwm_softc *sc)
struct ieee80211com *ic = &sc->sc_ic; struct ieee80211com *ic = &sc->sc_ic;
int error, i, ac; int error, i, ac;
sc->sf_state = IWM_SF_UNINIT;
if ((error = iwm_start_hw(sc)) != 0) { if ((error = iwm_start_hw(sc)) != 0) {
printf("iwm_start_hw: failed %d\n", error); printf("iwm_start_hw: failed %d\n", error);
return error; return error;
@@ -4843,6 +4678,10 @@ iwm_init_hw(struct iwm_softc *sc)
goto error; goto error;
} }
error = iwm_mvm_sf_update(sc, NULL, FALSE);
if (error)
device_printf(sc->sc_dev, "Failed to initialize Smart Fifo\n");
if ((error = iwm_send_bt_init_conf(sc)) != 0) { if ((error = iwm_send_bt_init_conf(sc)) != 0) {
device_printf(sc->sc_dev, "bt init conf failed\n"); device_printf(sc->sc_dev, "bt init conf failed\n");
goto error; goto error;
@@ -5543,36 +5382,27 @@ iwm_handle_rxb(struct iwm_softc *sc, struct mbuf *m)
case IWM_INIT_COMPLETE_NOTIF: case IWM_INIT_COMPLETE_NOTIF:
break; break;
case IWM_SCAN_OFFLOAD_COMPLETE: { case IWM_SCAN_OFFLOAD_COMPLETE:
struct iwm_periodic_scan_complete *notif; iwm_mvm_rx_lmac_scan_complete_notif(sc, pkt);
notif = (void *)pkt->data;
if (sc->sc_flags & IWM_FLAG_SCAN_RUNNING) { if (sc->sc_flags & IWM_FLAG_SCAN_RUNNING) {
sc->sc_flags &= ~IWM_FLAG_SCAN_RUNNING; sc->sc_flags &= ~IWM_FLAG_SCAN_RUNNING;
ieee80211_runtask(ic, &sc->sc_es_task); ieee80211_runtask(ic, &sc->sc_es_task);
} }
break; break;
}
case IWM_SCAN_ITERATION_COMPLETE: { case IWM_SCAN_ITERATION_COMPLETE: {
struct iwm_lmac_scan_complete_notif *notif; struct iwm_lmac_scan_complete_notif *notif;
notif = (void *)pkt->data; notif = (void *)pkt->data;
ieee80211_runtask(&sc->sc_ic, &sc->sc_es_task);
break; break;
} }
case IWM_SCAN_COMPLETE_UMAC: { case IWM_SCAN_COMPLETE_UMAC:
struct iwm_umac_scan_complete *notif; iwm_mvm_rx_umac_scan_complete_notif(sc, pkt);
notif = (void *)pkt->data;
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"UMAC scan complete, status=0x%x\n",
notif->status);
if (sc->sc_flags & IWM_FLAG_SCAN_RUNNING) { if (sc->sc_flags & IWM_FLAG_SCAN_RUNNING) {
sc->sc_flags &= ~IWM_FLAG_SCAN_RUNNING; sc->sc_flags &= ~IWM_FLAG_SCAN_RUNNING;
ieee80211_runtask(ic, &sc->sc_es_task); ieee80211_runtask(ic, &sc->sc_es_task);
} }
break; break;
}
case IWM_SCAN_ITERATION_COMPLETE_UMAC: { case IWM_SCAN_ITERATION_COMPLETE_UMAC: {
struct iwm_umac_scan_iter_complete_notif *notif; struct iwm_umac_scan_iter_complete_notif *notif;
@@ -5581,7 +5411,6 @@ iwm_handle_rxb(struct iwm_softc *sc, struct mbuf *m)
IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "UMAC scan iteration " IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "UMAC scan iteration "
"complete, status=0x%x, %d channels scanned\n", "complete, status=0x%x, %d channels scanned\n",
notif->status, notif->scanned_channels); notif->status, notif->scanned_channels);
ieee80211_runtask(&sc->sc_ic, &sc->sc_es_task);
break; break;
} }
@@ -5868,6 +5697,7 @@ iwm_intr(void *arg)
#define PCI_PRODUCT_INTEL_WL_3160_2 0x08b4 #define PCI_PRODUCT_INTEL_WL_3160_2 0x08b4
#define PCI_PRODUCT_INTEL_WL_3165_1 0x3165 #define PCI_PRODUCT_INTEL_WL_3165_1 0x3165
#define PCI_PRODUCT_INTEL_WL_3165_2 0x3166 #define PCI_PRODUCT_INTEL_WL_3165_2 0x3166
#define PCI_PRODUCT_INTEL_WL_3168_1 0x24fb
#define PCI_PRODUCT_INTEL_WL_7260_1 0x08b1 #define PCI_PRODUCT_INTEL_WL_7260_1 0x08b1
#define PCI_PRODUCT_INTEL_WL_7260_2 0x08b2 #define PCI_PRODUCT_INTEL_WL_7260_2 0x08b2
#define PCI_PRODUCT_INTEL_WL_7265_1 0x095a #define PCI_PRODUCT_INTEL_WL_7265_1 0x095a
@@ -5884,6 +5714,7 @@ static const struct iwm_devices {
{ PCI_PRODUCT_INTEL_WL_3160_2, &iwm3160_cfg }, { PCI_PRODUCT_INTEL_WL_3160_2, &iwm3160_cfg },
{ PCI_PRODUCT_INTEL_WL_3165_1, &iwm3165_cfg }, { PCI_PRODUCT_INTEL_WL_3165_1, &iwm3165_cfg },
{ PCI_PRODUCT_INTEL_WL_3165_2, &iwm3165_cfg }, { PCI_PRODUCT_INTEL_WL_3165_2, &iwm3165_cfg },
{ PCI_PRODUCT_INTEL_WL_3168_1, &iwm3168_cfg },
{ PCI_PRODUCT_INTEL_WL_7260_1, &iwm7260_cfg }, { PCI_PRODUCT_INTEL_WL_7260_1, &iwm7260_cfg },
{ PCI_PRODUCT_INTEL_WL_7260_2, &iwm7260_cfg }, { PCI_PRODUCT_INTEL_WL_7260_2, &iwm7260_cfg },
{ PCI_PRODUCT_INTEL_WL_7265_1, &iwm7265_cfg }, { PCI_PRODUCT_INTEL_WL_7265_1, &iwm7265_cfg },
@@ -6026,6 +5857,8 @@ iwm_attach(device_t dev)
goto fail; goto fail;
} }
sc->sf_state = IWM_SF_UNINIT;
/* Init phy db */ /* Init phy db */
sc->sc_phy_db = iwm_phy_db_init(sc); sc->sc_phy_db = iwm_phy_db_init(sc);
if (!sc->sc_phy_db) { if (!sc->sc_phy_db) {
@@ -6033,6 +5866,9 @@ iwm_attach(device_t dev)
goto fail; goto fail;
} }
/* Set EBS as successful as long as not stated otherwise by the FW. */
sc->last_ebs_successful = TRUE;
/* PCI attach */ /* PCI attach */
error = iwm_pci_attach(dev); error = iwm_pci_attach(dev);
if (error != 0) if (error != 0)
@@ -6165,9 +6001,7 @@ iwm_attach(device_t dev)
// IEEE80211_C_BGSCAN /* capable of bg scanning */ // IEEE80211_C_BGSCAN /* capable of bg scanning */
; ;
/* Advertise full-offload scanning */ /* Advertise full-offload scanning */
#ifndef __HAIKU__
ic->ic_flags_ext = IEEE80211_FEXT_SCAN_OFFLOAD; ic->ic_flags_ext = IEEE80211_FEXT_SCAN_OFFLOAD;
#endif
for (i = 0; i < nitems(sc->sc_phyctxt); i++) { for (i = 0; i < nitems(sc->sc_phyctxt); i++) {
sc->sc_phyctxt[i].id = i; sc->sc_phyctxt[i].id = i;
sc->sc_phyctxt[i].color = 0; sc->sc_phyctxt[i].color = 0;
@@ -6222,6 +6056,7 @@ iwm_wme_update(struct ieee80211com *ic)
{ {
#define IWM_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */ #define IWM_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */
struct iwm_softc *sc = ic->ic_softc; struct iwm_softc *sc = ic->ic_softc;
struct chanAccParams chp;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwm_vap *ivp = IWM_VAP(vap); struct iwm_vap *ivp = IWM_VAP(vap);
struct iwm_node *in; struct iwm_node *in;
@@ -6231,9 +6066,11 @@ iwm_wme_update(struct ieee80211com *ic)
if (vap == NULL) if (vap == NULL)
return (0); return (0);
ieee80211_wme_ic_getparams(ic, &chp);
IEEE80211_LOCK(ic); IEEE80211_LOCK(ic);
for (aci = 0; aci < WME_NUM_AC; aci++) for (aci = 0; aci < WME_NUM_AC; aci++)
tmp[aci] = ic->ic_wme.wme_chanParams.cap_wmeParams[aci]; tmp[aci] = chp.cap_wmeParams[aci];
IEEE80211_UNLOCK(ic); IEEE80211_UNLOCK(ic);
IWM_LOCK(sc); IWM_LOCK(sc);
@@ -6376,6 +6213,7 @@ iwm_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ivp->color = IWM_DEFAULT_COLOR; ivp->color = IWM_DEFAULT_COLOR;
ivp->have_wme = FALSE; ivp->have_wme = FALSE;
ivp->ps_disabled = FALSE;
ieee80211_ratectl_init(vap); ieee80211_ratectl_init(vap);
/* Complete setup. */ /* Complete setup. */
@@ -6637,6 +6475,8 @@ static driver_t iwm_pci_driver = {
static devclass_t iwm_devclass; static devclass_t iwm_devclass;
DRIVER_MODULE(iwm, pci, iwm_pci_driver, iwm_devclass, NULL, NULL); DRIVER_MODULE(iwm, pci, iwm_pci_driver, iwm_devclass, NULL, NULL);
MODULE_PNP_INFO("U16:device;P:#;T:vendor=0x8086", pci, iwm_pci_driver,
iwm_devices, nitems(iwm_devices));
MODULE_DEPEND(iwm, firmware, 1, 1, 1); MODULE_DEPEND(iwm, firmware, 1, 1, 1);
MODULE_DEPEND(iwm, pci, 1, 1, 1); MODULE_DEPEND(iwm, pci, 1, 1, 1);
MODULE_DEPEND(iwm, wlan, 1, 1, 1); MODULE_DEPEND(iwm, wlan, 1, 1, 1);
@@ -70,7 +70,7 @@
*****************************************************************************/ *****************************************************************************/
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_7000.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_7000.c 331665 2018-03-28 07:59:16Z eadler $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -81,6 +81,7 @@ __FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_7000.c 330455 2018-03-05 08:0
#define IWM7260_FW "iwm7260fw" #define IWM7260_FW "iwm7260fw"
#define IWM3160_FW "iwm3160fw" #define IWM3160_FW "iwm3160fw"
#define IWM3168_FW "iwm3168fw"
#define IWM7265_FW "iwm7265fw" #define IWM7265_FW "iwm7265fw"
#define IWM7265D_FW "iwm7265Dfw" #define IWM7265D_FW "iwm7265Dfw"
@@ -113,6 +114,13 @@ const struct iwm_cfg iwm3165_cfg = {
.host_interrupt_operation_mode = 0, .host_interrupt_operation_mode = 0,
}; };
const struct iwm_cfg iwm3168_cfg = {
.name = "Intel(R) Dual Band Wireless AC 3168",
.fw_name = IWM3168_FW,
IWM_DEVICE_7000_COMMON,
.host_interrupt_operation_mode = 0,
};
const struct iwm_cfg iwm7265_cfg = { const struct iwm_cfg iwm7265_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7265", .name = "Intel(R) Dual Band Wireless AC 7265",
.fw_name = IWM7265_FW, .fw_name = IWM7265_FW,
@@ -69,7 +69,7 @@
*****************************************************************************/ *****************************************************************************/
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_8000.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_8000.c 324434 2017-10-09 15:48:56Z gnn $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -87,7 +87,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_binding.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_binding.c 319577 2017-06-04 21:05:58Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -140,6 +140,7 @@ __FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_binding.c 330455 2018-03-05 0
#include <dev/iwm/if_iwm_debug.h> #include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_util.h> #include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_binding.h> #include <dev/iwm/if_iwm_binding.h>
#include <dev/iwm/if_iwm_sf.h>
/* /*
* BEGIN iwlwifi/mvm/binding.c * BEGIN iwlwifi/mvm/binding.c
@@ -223,14 +224,12 @@ iwm_mvm_binding_add_vif(struct iwm_softc *sc, struct iwm_vap *ivp)
if (!ivp->phy_ctxt) if (!ivp->phy_ctxt)
return EINVAL; return EINVAL;
#ifdef notyet
/* /*
* Update SF - Disable if needed. if this fails, SF might still be on * Update SF - Disable if needed. if this fails, SF might still be on
* while many macs are bound, which is forbidden - so fail the binding. * while many macs are bound, which is forbidden - so fail the binding.
*/ */
if (iwm_mvm_sf_update(sc, ivp, FALSE)) if (iwm_mvm_sf_update(sc, &ivp->iv_vap, FALSE))
return EINVAL; return EINVAL;
#endif
return iwm_mvm_binding_update(sc, ivp, ivp->phy_ctxt, TRUE); return iwm_mvm_binding_update(sc, ivp, ivp->phy_ctxt, TRUE);
} }
@@ -245,13 +244,11 @@ iwm_mvm_binding_remove_vif(struct iwm_softc *sc, struct iwm_vap *ivp)
ret = iwm_mvm_binding_update(sc, ivp, ivp->phy_ctxt, FALSE); ret = iwm_mvm_binding_update(sc, ivp, ivp->phy_ctxt, FALSE);
#ifdef notyet
if (!ret) { if (!ret) {
if (iwm_mvm_sf_update(sc, ivp, TRUE)) if (iwm_mvm_sf_update(sc, &ivp->iv_vap, TRUE))
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
"Failed to update SF state\n"); "Failed to update SF state\n");
} }
#endif
return ret; return ret;
} }
@@ -1,5 +1,5 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */ /* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_binding.h 330204 2018-03-01 06:36:41Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_binding.h 318212 2017-05-12 05:19:08Z adrian $ */
/* /*
* Copyright (c) 2014 genua mbh <info@genua.de> * Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd. * Copyright (c) 2014 Fixup Software Ltd.
@@ -68,7 +68,7 @@
*****************************************************************************/ *****************************************************************************/
/* /*
* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_config.h 330227 2018-03-01 06:57:38Z eadler $ * $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_config.h 331665 2018-03-28 07:59:16Z eadler $
*/ */
#ifndef __IWM_CONFIG_H__ #ifndef __IWM_CONFIG_H__
@@ -128,6 +128,7 @@ struct iwm_cfg {
extern const struct iwm_cfg iwm7260_cfg; extern const struct iwm_cfg iwm7260_cfg;
extern const struct iwm_cfg iwm3160_cfg; extern const struct iwm_cfg iwm3160_cfg;
extern const struct iwm_cfg iwm3165_cfg; extern const struct iwm_cfg iwm3165_cfg;
extern const struct iwm_cfg iwm3168_cfg;
extern const struct iwm_cfg iwm7265_cfg; extern const struct iwm_cfg iwm7265_cfg;
extern const struct iwm_cfg iwm7265d_cfg; extern const struct iwm_cfg iwm7265d_cfg;
extern const struct iwm_cfg iwm8260_cfg; extern const struct iwm_cfg iwm8260_cfg;
@@ -69,7 +69,7 @@
* *
*****************************************************************************/ *****************************************************************************/
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_constants.h 330201 2018-03-01 06:34:21Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_constants.h 318005 2017-05-09 04:15:07Z adrian $ */
#ifndef __IF_IWM_CONSTANTS_H #ifndef __IF_IWM_CONSTANTS_H
#define __IF_IWM_CONSTANTS_H #define __IF_IWM_CONSTANTS_H
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* *
* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_debug.h 330217 2018-03-01 06:47:52Z eadler $ * $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_debug.h 319578 2017-06-04 21:10:14Z adrian $
*/ */
#ifndef __IF_IWM_DEBUG_H__ #ifndef __IF_IWM_DEBUG_H__
@@ -71,7 +71,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_fw.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_fw.c 318001 2017-05-09 02:38:23Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -71,7 +71,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* /*
* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_fw.h 330192 2018-03-01 06:22:14Z eadler $ * $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_fw.h 314209 2017-02-24 15:17:43Z adrian $
*/ */
#ifndef __IF_IWM_FW_H__ #ifndef __IF_IWM_FW_H__
#define __IF_IWM_FW_H__ #define __IF_IWM_FW_H__
@@ -87,7 +87,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_led.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_led.c 318001 2017-05-09 02:38:23Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -86,7 +86,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_led.h 303628 2016-08-01 17:51:35Z sbruno $ * $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_led.h 303327 2016-07-26 00:02:17Z sbruno $
*/ */
#ifndef __IF_IWM_LED_H__ #ifndef __IF_IWM_LED_H__
#define __IF_IWM_LED_H__ #define __IF_IWM_LED_H__
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_mac_ctxt.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_mac_ctxt.c 318219 2017-05-12 05:50:38Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -1,5 +1,5 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */ /* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_mac_ctxt.h 330209 2018-03-01 06:40:08Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_mac_ctxt.h 318219 2017-05-12 05:50:38Z adrian $ */
/* /*
* Copyright (c) 2014 genua mbh <info@genua.de> * Copyright (c) 2014 genua mbh <info@genua.de>
@@ -67,7 +67,7 @@
*****************************************************************************/ *****************************************************************************/
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_notif_wait.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_notif_wait.c 318001 2017-05-09 02:38:23Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -66,7 +66,7 @@
* *
*****************************************************************************/ *****************************************************************************/
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_notif_wait.h 330170 2018-03-01 05:48:20Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_notif_wait.h 313322 2017-02-06 05:27:07Z adrian $ */
#ifndef __IF_IWN_NOTIF_WAIT_H__ #ifndef __IF_IWN_NOTIF_WAIT_H__
#define __IF_IWN_NOTIF_WAIT_H__ #define __IF_IWN_NOTIF_WAIT_H__
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_pcie_trans.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_pcie_trans.c 318003 2017-05-09 02:42:53Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -1,4 +1,4 @@
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_pcie_trans.h 330175 2018-03-01 05:53:12Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_pcie_trans.h 313415 2017-02-08 06:53:23Z adrian $ */
/* /*
* Copyright (c) 2014 genua mbh <info@genua.de> * Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd. * Copyright (c) 2014 Fixup Software Ltd.
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_phy_ctxt.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_phy_ctxt.c 318012 2017-05-09 05:31:38Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -1,5 +1,5 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */ /* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_phy_ctxt.h 286441 2015-08-08 06:06:48Z rpaulo $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_phy_ctxt.h 286441 2015-08-08 06:06:48Z rpaulo $ */
/* /*
* Copyright (c) 2014 genua mbh <info@genua.de> * Copyright (c) 2014 genua mbh <info@genua.de>
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_phy_db.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_phy_db.c 319581 2017-06-04 21:13:13Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -1,5 +1,5 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */ /* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_phy_db.h 330169 2018-03-01 05:46:11Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_phy_db.h 313317 2017-02-06 05:09:42Z adrian $ */
/* /*
* Copyright (c) 2014 genua mbh <info@genua.de> * Copyright (c) 2014 genua mbh <info@genua.de>
@@ -87,7 +87,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_power.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_power.c 318228 2017-05-12 06:31:57Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -201,7 +201,7 @@ iwm_mvm_beacon_filter_send_cmd(struct iwm_softc *sc,
static void static void
iwm_mvm_beacon_filter_set_cqm_params(struct iwm_softc *sc, iwm_mvm_beacon_filter_set_cqm_params(struct iwm_softc *sc,
struct iwm_node *in, struct iwm_beacon_filter_cmd *cmd) struct iwm_vap *ivp, struct iwm_beacon_filter_cmd *cmd)
{ {
cmd->ba_enable_beacon_abort = htole32(sc->sc_bf.ba_enabled); cmd->ba_enable_beacon_abort = htole32(sc->sc_bf.ba_enabled);
} }
@@ -212,7 +212,7 @@ iwm_mvm_power_log(struct iwm_softc *sc, struct iwm_mac_power_cmd *cmd)
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD, IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Sending power table command on mac id 0x%X for " "Sending power table command on mac id 0x%X for "
"power level %d, flags = 0x%X\n", "power level %d, flags = 0x%X\n",
cmd->id_and_color, IWM_POWER_SCHEME_CAM, le16toh(cmd->flags)); cmd->id_and_color, iwm_power_scheme, le16toh(cmd->flags));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD, IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Keep alive = %u sec\n", le16toh(cmd->keep_alive_seconds)); "Keep alive = %u sec\n", le16toh(cmd->keep_alive_seconds));
@@ -278,15 +278,14 @@ iwm_mvm_power_config_skip_dtim(struct iwm_softc *sc,
} }
static void static void
iwm_mvm_power_build_cmd(struct iwm_softc *sc, struct iwm_node *in, iwm_mvm_power_build_cmd(struct iwm_softc *sc, struct iwm_vap *ivp,
struct iwm_mac_power_cmd *cmd) struct iwm_mac_power_cmd *cmd)
{ {
struct ieee80211_node *ni = &in->in_ni; struct ieee80211vap *vap = &ivp->iv_vap;
struct ieee80211_node *ni = vap->iv_bss;
int dtimper, dtimper_msec; int dtimper, dtimper_msec;
int keep_alive; int keep_alive;
struct ieee80211com *ic = &sc->sc_ic; boolean_t bss_conf_ps = FALSE;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwm_vap *ivp = IWM_VAP(vap);
cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ivp->id, cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ivp->id,
ivp->color)); ivp->color));
@@ -308,6 +307,14 @@ iwm_mvm_power_build_cmd(struct iwm_softc *sc, struct iwm_node *in,
return; return;
cmd->flags |= htole16(IWM_POWER_FLAGS_POWER_SAVE_ENA_MSK); cmd->flags |= htole16(IWM_POWER_FLAGS_POWER_SAVE_ENA_MSK);
if (IWM_NODE(ni)->in_assoc &&
(vap->iv_flags & IEEE80211_F_PMGTON) != 0) {
bss_conf_ps = TRUE;
}
if (!bss_conf_ps)
return;
cmd->flags |= htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); cmd->flags |= htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
iwm_mvm_power_config_skip_dtim(sc, cmd); iwm_mvm_power_config_skip_dtim(sc, cmd);
@@ -319,11 +326,11 @@ iwm_mvm_power_build_cmd(struct iwm_softc *sc, struct iwm_node *in,
} }
static int static int
iwm_mvm_power_send_cmd(struct iwm_softc *sc, struct iwm_node *in) iwm_mvm_power_send_cmd(struct iwm_softc *sc, struct iwm_vap *ivp)
{ {
struct iwm_mac_power_cmd cmd = {}; struct iwm_mac_power_cmd cmd = {};
iwm_mvm_power_build_cmd(sc, in, &cmd); iwm_mvm_power_build_cmd(sc, ivp, &cmd);
iwm_mvm_power_log(sc, &cmd); iwm_mvm_power_log(sc, &cmd);
return iwm_mvm_send_cmd_pdu(sc, IWM_MAC_PM_POWER_TABLE, 0, return iwm_mvm_send_cmd_pdu(sc, IWM_MAC_PM_POWER_TABLE, 0,
@@ -331,12 +338,12 @@ iwm_mvm_power_send_cmd(struct iwm_softc *sc, struct iwm_node *in)
} }
static int static int
_iwm_mvm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_node *in, _iwm_mvm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_vap *ivp,
struct iwm_beacon_filter_cmd *cmd) struct iwm_beacon_filter_cmd *cmd)
{ {
int ret; int ret;
iwm_mvm_beacon_filter_set_cqm_params(sc, in, cmd); iwm_mvm_beacon_filter_set_cqm_params(sc, ivp, cmd);
ret = iwm_mvm_beacon_filter_send_cmd(sc, cmd); ret = iwm_mvm_beacon_filter_send_cmd(sc, cmd);
if (!ret) if (!ret)
@@ -346,14 +353,14 @@ _iwm_mvm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_node *in,
} }
int int
iwm_mvm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_node *in) iwm_mvm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_vap *ivp)
{ {
struct iwm_beacon_filter_cmd cmd = { struct iwm_beacon_filter_cmd cmd = {
IWM_BF_CMD_CONFIG_DEFAULTS, IWM_BF_CMD_CONFIG_DEFAULTS,
.bf_enable_beacon_filter = htole32(1), .bf_enable_beacon_filter = htole32(1),
}; };
return _iwm_mvm_enable_beacon_filter(sc, in, &cmd); return _iwm_mvm_enable_beacon_filter(sc, ivp, &cmd);
} }
int int
@@ -372,15 +379,18 @@ iwm_mvm_disable_beacon_filter(struct iwm_softc *sc)
static int static int
iwm_mvm_power_set_ps(struct iwm_softc *sc) iwm_mvm_power_set_ps(struct iwm_softc *sc)
{ {
struct ieee80211vap *vap = TAILQ_FIRST(&sc->sc_ic.ic_vaps); struct ieee80211vap *vap;
boolean_t disable_ps; boolean_t disable_ps;
int ret; int ret;
/* disable PS if CAM */ /* disable PS if CAM */
disable_ps = (iwm_power_scheme == IWM_POWER_SCHEME_CAM); disable_ps = (iwm_power_scheme == IWM_POWER_SCHEME_CAM);
/* ...or if any of the vifs require PS to be off */ /* ...or if any of the vifs require PS to be off */
if (vap != NULL && (vap->iv_flags & IEEE80211_F_PMGTON) == 0) TAILQ_FOREACH(vap, &sc->sc_ic.ic_vaps, iv_next) {
struct iwm_vap *ivp = IWM_VAP(vap);
if (ivp->phy_ctxt != NULL && ivp->ps_disabled)
disable_ps = TRUE; disable_ps = TRUE;
}
/* update device power state if it has changed */ /* update device power state if it has changed */
if (sc->sc_ps_disabled != disable_ps) { if (sc->sc_ps_disabled != disable_ps) {
@@ -398,19 +408,26 @@ iwm_mvm_power_set_ps(struct iwm_softc *sc)
} }
static int static int
iwm_mvm_power_set_ba(struct iwm_softc *sc, struct iwm_node *in) iwm_mvm_power_set_ba(struct iwm_softc *sc, struct iwm_vap *ivp)
{ {
struct iwm_beacon_filter_cmd cmd = { struct iwm_beacon_filter_cmd cmd = {
IWM_BF_CMD_CONFIG_DEFAULTS, IWM_BF_CMD_CONFIG_DEFAULTS,
.bf_enable_beacon_filter = htole32(1), .bf_enable_beacon_filter = htole32(1),
}; };
struct ieee80211vap *vap = &ivp->iv_vap;
struct ieee80211_node *ni = vap->iv_bss;
boolean_t bss_conf_ps = FALSE;
if (!sc->sc_bf.bf_enabled) if (!sc->sc_bf.bf_enabled)
return 0; return 0;
sc->sc_bf.ba_enabled = !sc->sc_ps_disabled; if (ni != NULL && IWM_NODE(ni)->in_assoc &&
(vap->iv_flags & IEEE80211_F_PMGTON) != 0) {
bss_conf_ps = TRUE;
}
sc->sc_bf.ba_enabled = !sc->sc_ps_disabled && bss_conf_ps;
return _iwm_mvm_enable_beacon_filter(sc, in, &cmd); return _iwm_mvm_enable_beacon_filter(sc, ivp, &cmd);
} }
int int
@@ -424,7 +441,7 @@ iwm_mvm_power_update_ps(struct iwm_softc *sc)
return ret; return ret;
if (vap != NULL) if (vap != NULL)
return iwm_mvm_power_set_ba(sc, IWM_NODE(vap->iv_bss)); return iwm_mvm_power_set_ba(sc, IWM_VAP(vap));
return 0; return 0;
} }
@@ -440,13 +457,13 @@ iwm_mvm_power_update_mac(struct iwm_softc *sc)
return ret; return ret;
if (vap != NULL) { if (vap != NULL) {
ret = iwm_mvm_power_send_cmd(sc, IWM_NODE(vap->iv_bss)); ret = iwm_mvm_power_send_cmd(sc, IWM_VAP(vap));
if (ret) if (ret)
return ret; return ret;
} }
if (vap != NULL) if (vap != NULL)
return iwm_mvm_power_set_ba(sc, IWM_NODE(vap->iv_bss)); return iwm_mvm_power_set_ba(sc, IWM_VAP(vap));
return 0; return 0;
} }
@@ -1,5 +1,5 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */ /* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_power.h 330201 2018-03-01 06:34:21Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_power.h 318226 2017-05-12 06:30:06Z adrian $ */
/* /*
* Copyright (c) 2014 genua mbh <info@genua.de> * Copyright (c) 2014 genua mbh <info@genua.de>
@@ -94,7 +94,7 @@ extern int iwm_mvm_power_update_device(struct iwm_softc *sc);
extern int iwm_mvm_power_update_mac(struct iwm_softc *sc); extern int iwm_mvm_power_update_mac(struct iwm_softc *sc);
extern int iwm_mvm_power_update_ps(struct iwm_softc *sc); extern int iwm_mvm_power_update_ps(struct iwm_softc *sc);
extern int iwm_mvm_enable_beacon_filter(struct iwm_softc *sc, extern int iwm_mvm_enable_beacon_filter(struct iwm_softc *sc,
struct iwm_node *in); struct iwm_vap *ivp);
extern int iwm_mvm_disable_beacon_filter(struct iwm_softc *sc); extern int iwm_mvm_disable_beacon_filter(struct iwm_softc *sc);
#endif /* __IF_IWM_POWER_H__ */ #endif /* __IF_IWM_POWER_H__ */
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_scan.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_scan.c 321507 2017-07-26 05:26:01Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -162,6 +162,9 @@ __FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_scan.c 330455 2018-03-05 08:0
* BEGIN mvm/scan.c * BEGIN mvm/scan.c
*/ */
#define IWM_DENSE_EBS_SCAN_RATIO 5
#define IWM_SPARSE_EBS_SCAN_RATIO 1
static uint16_t static uint16_t
iwm_mvm_scan_rx_chain(struct iwm_softc *sc) iwm_mvm_scan_rx_chain(struct iwm_softc *sc)
{ {
@@ -176,6 +179,15 @@ iwm_mvm_scan_rx_chain(struct iwm_softc *sc)
return htole16(rx_chain); return htole16(rx_chain);
} }
static uint32_t
iwm_mvm_scan_rxon_flags(struct ieee80211_channel *c)
{
if (IEEE80211_IS_CHAN_2GHZ(c))
return htole32(IWM_PHY_BAND_24);
else
return htole32(IWM_PHY_BAND_5);
}
static uint32_t static uint32_t
iwm_mvm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck) iwm_mvm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck)
{ {
@@ -199,6 +211,80 @@ iwm_mvm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck)
return htole32(IWM_RATE_6M_PLCP | tx_ant); return htole32(IWM_RATE_6M_PLCP | tx_ant);
} }
static inline boolean_t
iwm_mvm_rrm_scan_needed(struct iwm_softc *sc)
{
/* require rrm scan whenever the fw supports it */
return fw_has_capa(&sc->ucode_capa,
IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT);
}
#ifdef IWM_DEBUG
static const char *
iwm_mvm_ebs_status_str(enum iwm_scan_ebs_status status)
{
switch (status) {
case IWM_SCAN_EBS_SUCCESS:
return "successful";
case IWM_SCAN_EBS_INACTIVE:
return "inactive";
case IWM_SCAN_EBS_FAILED:
case IWM_SCAN_EBS_CHAN_NOT_FOUND:
default:
return "failed";
}
}
static const char *
iwm_mvm_offload_status_str(enum iwm_scan_offload_complete_status status)
{
return (status == IWM_SCAN_OFFLOAD_ABORTED) ? "aborted" : "completed";
}
#endif
void
iwm_mvm_rx_lmac_scan_complete_notif(struct iwm_softc *sc,
struct iwm_rx_packet *pkt)
{
struct iwm_periodic_scan_complete *scan_notif = (void *)pkt->data;
/* If this happens, the firmware has mistakenly sent an LMAC
* notification during UMAC scans -- warn and ignore it.
*/
if (fw_has_capa(&sc->ucode_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) {
device_printf(sc->sc_dev,
"%s: Mistakenly got LMAC notification during UMAC scan\n",
__func__);
return;
}
IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Regular scan %s, EBS status %s (FW)\n",
iwm_mvm_offload_status_str(scan_notif->status),
iwm_mvm_ebs_status_str(scan_notif->ebs_status));
sc->last_ebs_successful =
scan_notif->ebs_status == IWM_SCAN_EBS_SUCCESS ||
scan_notif->ebs_status == IWM_SCAN_EBS_INACTIVE;
}
void
iwm_mvm_rx_umac_scan_complete_notif(struct iwm_softc *sc,
struct iwm_rx_packet *pkt)
{
struct iwm_umac_scan_complete *notif = (void *)pkt->data;
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"Scan completed, uid %u, status %s, EBS status %s\n",
le32toh(notif->uid),
iwm_mvm_offload_status_str(notif->status),
iwm_mvm_ebs_status_str(notif->ebs_status));
if (notif->ebs_status != IWM_SCAN_EBS_SUCCESS &&
notif->ebs_status != IWM_SCAN_EBS_INACTIVE)
sc->last_ebs_successful = FALSE;
}
static int static int
iwm_mvm_scan_skip_channel(struct ieee80211_channel *c) iwm_mvm_scan_skip_channel(struct ieee80211_channel *c)
{ {
@@ -221,15 +307,13 @@ iwm_mvm_lmac_scan_fill_channels(struct iwm_softc *sc,
int j; int j;
for (nchan = j = 0; for (nchan = j = 0;
j < ic->ic_nchans && nchan < sc->ucode_capa.n_scan_channels; j++) { j < ss->ss_last && nchan < sc->ucode_capa.n_scan_channels; j++) {
c = &ic->ic_channels[j]; c = ss->ss_chans[j];
/* For 2GHz, only populate 11b channels */
/* For 5GHz, only populate 11a channels */
/* /*
* Catch other channels, in case we have 900MHz channels or * Catch other channels, in case we have 900MHz channels or
* something in the chanlist. * something in the chanlist.
*/ */
if (iwm_mvm_scan_skip_channel(c)) { if (!IEEE80211_IS_CHAN_2GHZ(c) && !IEEE80211_IS_CHAN_5GHZ(c)) {
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM, IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM,
"%s: skipping channel (freq=%d, ieee=%d, flags=0x%08x)\n", "%s: skipping channel (freq=%d, ieee=%d, flags=0x%08x)\n",
__func__, c->ic_freq, c->ic_ieee, c->ic_flags); __func__, c->ic_freq, c->ic_ieee, c->ic_flags);
@@ -260,20 +344,19 @@ iwm_mvm_umac_scan_fill_channels(struct iwm_softc *sc,
struct iwm_scan_channel_cfg_umac *chan, int n_ssids) struct iwm_scan_channel_cfg_umac *chan, int n_ssids)
{ {
struct ieee80211com *ic = &sc->sc_ic; struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_scan_state *ss = ic->ic_scan;
struct ieee80211_channel *c; struct ieee80211_channel *c;
uint8_t nchan; uint8_t nchan;
int j; int j;
for (nchan = j = 0; for (nchan = j = 0;
j < ic->ic_nchans && nchan < sc->ucode_capa.n_scan_channels; j++) { j < ss->ss_last && nchan < sc->ucode_capa.n_scan_channels; j++) {
c = &ic->ic_channels[j]; c = ss->ss_chans[j];
/* For 2GHz, only populate 11b channels */
/* For 5GHz, only populate 11a channels */
/* /*
* Catch other channels, in case we have 900MHz channels or * Catch other channels, in case we have 900MHz channels or
* something in the chanlist. * something in the chanlist.
*/ */
if (iwm_mvm_scan_skip_channel(c)) { if (!IEEE80211_IS_CHAN_2GHZ(c) && !IEEE80211_IS_CHAN_5GHZ(c)) {
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM, IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM,
"%s: skipping channel (freq=%d, ieee=%d, flags=0x%08x)\n", "%s: skipping channel (freq=%d, ieee=%d, flags=0x%08x)\n",
__func__, c->ic_freq, c->ic_ieee, c->ic_flags); __func__, c->ic_freq, c->ic_ieee, c->ic_flags);
@@ -347,8 +430,7 @@ iwm_mvm_fill_probe_req(struct iwm_softc *sc, struct iwm_scan_probe_req *preq)
preq->band_data[0].len = htole16(frm - pos); preq->band_data[0].len = htole16(frm - pos);
remain -= frm - pos; remain -= frm - pos;
if (fw_has_capa(&sc->ucode_capa, if (iwm_mvm_rrm_scan_needed(sc)) {
IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) {
if (remain < 3) if (remain < 3)
return ENOBUFS; return ENOBUFS;
*frm++ = IEEE80211_ELEMID_DSPARMS; *frm++ = IEEE80211_ELEMID_DSPARMS;
@@ -481,6 +563,21 @@ iwm_mvm_config_umac_scan(struct iwm_softc *sc)
return ret; return ret;
} }
static boolean_t
iwm_mvm_scan_use_ebs(struct iwm_softc *sc)
{
const struct iwm_ucode_capabilities *capa = &sc->ucode_capa;
/* We can only use EBS if:
* 1. the feature is supported;
* 2. the last EBS was successful;
* 3. if only single scan, the single scan EBS API is supported;
* 4. it's not a p2p find operation.
*/
return ((capa->flags & IWM_UCODE_TLV_FLAGS_EBS_SUPPORT) &&
sc->last_ebs_successful);
}
int int
iwm_mvm_umac_scan(struct iwm_softc *sc) iwm_mvm_umac_scan(struct iwm_softc *sc)
{ {
@@ -550,8 +647,12 @@ iwm_mvm_umac_scan(struct iwm_softc *sc)
} else } else
req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE); req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE);
if (fw_has_capa(&sc->ucode_capa, if (iwm_mvm_scan_use_ebs(sc))
IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) req->channel_flags = IWM_SCAN_CHANNEL_FLAG_EBS |
IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
IWM_SCAN_CHANNEL_FLAG_CACHE_ADD;
if (iwm_mvm_rrm_scan_needed(sc))
req->general_flags |= req->general_flags |=
htole32(IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED); htole32(IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED);
@@ -619,13 +720,11 @@ iwm_mvm_lmac_scan(struct iwm_softc *sc)
req->scan_flags = htole32(IWM_MVM_LMAC_SCAN_FLAG_PASS_ALL | req->scan_flags = htole32(IWM_MVM_LMAC_SCAN_FLAG_PASS_ALL |
IWM_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE | IWM_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE |
IWM_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL); IWM_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL);
if (fw_has_capa(&sc->ucode_capa, if (iwm_mvm_rrm_scan_needed(sc))
IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT))
req->scan_flags |= htole32(IWM_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED); req->scan_flags |= htole32(IWM_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED);
req->flags = htole32(IWM_PHY_BAND_24); req->flags = iwm_mvm_scan_rxon_flags(sc->sc_ic.ic_scan->ss_chans[0]);
if (sc->nvm_data->sku_cap_band_52GHz_enable)
req->flags |= htole32(IWM_PHY_BAND_5);
req->filter_flags = req->filter_flags =
htole32(IWM_MAC_FILTER_ACCEPT_GRP | IWM_MAC_FILTER_IN_BEACON); htole32(IWM_MAC_FILTER_ACCEPT_GRP | IWM_MAC_FILTER_IN_BEACON);
@@ -675,9 +774,20 @@ iwm_mvm_lmac_scan(struct iwm_softc *sc)
req->schedule[0].iterations = 1; req->schedule[0].iterations = 1;
req->schedule[0].full_scan_mul = 1; req->schedule[0].full_scan_mul = 1;
/* Disable EBS. */ if (iwm_mvm_scan_use_ebs(sc)) {
req->channel_opt[0].non_ebs_ratio = 1; req->channel_opt[0].flags =
req->channel_opt[1].non_ebs_ratio = 1; htole16(IWM_SCAN_CHANNEL_FLAG_EBS |
IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
IWM_SCAN_CHANNEL_FLAG_CACHE_ADD);
req->channel_opt[0].non_ebs_ratio =
htole16(IWM_DENSE_EBS_SCAN_RATIO);
req->channel_opt[1].flags =
htole16(IWM_SCAN_CHANNEL_FLAG_EBS |
IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
IWM_SCAN_CHANNEL_FLAG_CACHE_ADD);
req->channel_opt[1].non_ebs_ratio =
htole16(IWM_SPARSE_EBS_SCAN_RATIO);
}
ret = iwm_send_cmd(sc, &hcmd); ret = iwm_send_cmd(sc, &hcmd);
if (!ret) { if (!ret) {
@@ -1,5 +1,5 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */ /* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_scan.h 330173 2018-03-01 05:51:35Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_scan.h 315925 2017-03-25 02:49:20Z adrian $ */
/* /*
* Copyright (c) 2014 genua mbh <info@genua.de> * Copyright (c) 2014 genua mbh <info@genua.de>
@@ -106,9 +106,13 @@
#ifndef __IF_IWN_SCAN_H__ #ifndef __IF_IWN_SCAN_H__
#define __IF_IWN_SCAN_H__ #define __IF_IWN_SCAN_H__
extern int iwm_mvm_lmac_scan(struct iwm_softc *sc); extern int iwm_mvm_lmac_scan(struct iwm_softc *);
extern int iwm_mvm_config_umac_scan(struct iwm_softc *); extern int iwm_mvm_config_umac_scan(struct iwm_softc *);
extern int iwm_mvm_umac_scan(struct iwm_softc *); extern int iwm_mvm_umac_scan(struct iwm_softc *);
extern int iwm_mvm_scan_stop_wait(struct iwm_softc *sc); extern int iwm_mvm_scan_stop_wait(struct iwm_softc *);
extern void iwm_mvm_rx_lmac_scan_complete_notif(struct iwm_softc *,
struct iwm_rx_packet *);
extern void iwm_mvm_rx_umac_scan_complete_notif(struct iwm_softc *,
struct iwm_rx_packet *);
#endif /* __IF_IWN_SCAN_H__ */ #endif /* __IF_IWN_SCAN_H__ */
@@ -0,0 +1,330 @@
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
*
******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_sf.c 319580 2017-06-04 21:12:11Z adrian $");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <net/bpf.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_config.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_sf.h>
/*
* Aging and idle timeouts for the different possible scenarios
* in default configuration
*/
static const uint32_t
sf_full_timeout_def[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
{
htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER_DEF),
htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_AGG_UNICAST_AGING_TIMER_DEF),
htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_MCAST_AGING_TIMER_DEF),
htole32(IWM_SF_MCAST_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_BA_AGING_TIMER_DEF),
htole32(IWM_SF_BA_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_TX_RE_AGING_TIMER_DEF),
htole32(IWM_SF_TX_RE_IDLE_TIMER_DEF)
},
};
/*
* Aging and idle timeouts for the different possible scenarios
* in single BSS MAC configuration.
*/
static const uint32_t
sf_full_timeout[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
{
htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER),
htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER)
},
{
htole32(IWM_SF_AGG_UNICAST_AGING_TIMER),
htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER)
},
{
htole32(IWM_SF_MCAST_AGING_TIMER),
htole32(IWM_SF_MCAST_IDLE_TIMER)
},
{
htole32(IWM_SF_BA_AGING_TIMER),
htole32(IWM_SF_BA_IDLE_TIMER)
},
{
htole32(IWM_SF_TX_RE_AGING_TIMER),
htole32(IWM_SF_TX_RE_IDLE_TIMER)
},
};
static void
iwm_mvm_fill_sf_command(struct iwm_softc *sc, struct iwm_sf_cfg_cmd *sf_cmd,
struct ieee80211_node *ni)
{
int i, j, watermark;
sf_cmd->watermark[IWM_SF_LONG_DELAY_ON] = htole32(IWM_SF_W_MARK_SCAN);
/*
* If we are in association flow - check antenna configuration
* capabilities of the AP station, and choose the watermark accordingly.
*/
if (ni) {
if (ni->ni_flags & IEEE80211_NODE_HT) {
watermark = IWM_SF_W_MARK_SISO;
} else {
watermark = IWM_SF_W_MARK_LEGACY;
}
/* default watermark value for unassociated mode. */
} else {
watermark = IWM_SF_W_MARK_MIMO2;
}
sf_cmd->watermark[IWM_SF_FULL_ON] = htole32(watermark);
for (i = 0; i < IWM_SF_NUM_SCENARIO; i++) {
for (j = 0; j < IWM_SF_NUM_TIMEOUT_TYPES; j++) {
sf_cmd->long_delay_timeouts[i][j] =
htole32(IWM_SF_LONG_DELAY_AGING_TIMER);
}
}
if (ni) {
_Static_assert(sizeof(sf_full_timeout) == sizeof(uint32_t) *
IWM_SF_NUM_SCENARIO * IWM_SF_NUM_TIMEOUT_TYPES,
"sf_full_timeout has wrong size");
memcpy(sf_cmd->full_on_timeouts, sf_full_timeout,
sizeof(sf_full_timeout));
} else {
_Static_assert(sizeof(sf_full_timeout_def) == sizeof(uint32_t) *
IWM_SF_NUM_SCENARIO * IWM_SF_NUM_TIMEOUT_TYPES,
"sf_full_timeout_def has wrong size");
memcpy(sf_cmd->full_on_timeouts, sf_full_timeout_def,
sizeof(sf_full_timeout_def));
}
}
static int
iwm_mvm_sf_config(struct iwm_softc *sc, struct ieee80211_node *ni,
enum iwm_sf_state new_state)
{
struct iwm_sf_cfg_cmd sf_cmd = {
.state = htole32(new_state),
};
int ret = 0;
#ifdef notyet /* only relevant for sdio variants */
if (sc->cfg->disable_dummy_notification)
sf_cmd.state |= htole32(IWM_SF_CFG_DUMMY_NOTIF_OFF);
#endif
/*
* If an associated AP sta changed its antenna configuration, the state
* will remain FULL_ON but SF parameters need to be reconsidered.
*/
if (new_state != IWM_SF_FULL_ON && sc->sf_state == new_state)
return 0;
switch (new_state) {
case IWM_SF_UNINIT:
iwm_mvm_fill_sf_command(sc, &sf_cmd, NULL);
break;
case IWM_SF_FULL_ON:
iwm_mvm_fill_sf_command(sc, &sf_cmd, ni);
break;
case IWM_SF_INIT_OFF:
iwm_mvm_fill_sf_command(sc, &sf_cmd, NULL);
break;
default:
device_printf(sc->sc_dev,
"Invalid state: %d. not sending Smart Fifo cmd\n",
new_state);
return EINVAL;
}
ret = iwm_mvm_send_cmd_pdu(sc, IWM_REPLY_SF_CFG_CMD, IWM_CMD_ASYNC,
sizeof(sf_cmd), &sf_cmd);
if (!ret)
sc->sf_state = new_state;
return ret;
}
/*
* Update Smart fifo:
* Count bound interfaces that are not to be removed, ignoring p2p devices,
* and set new state accordingly.
*/
int
iwm_mvm_sf_update(struct iwm_softc *sc, struct ieee80211vap *changed_vif,
boolean_t remove_vif)
{
enum iwm_sf_state new_state;
struct ieee80211_node *ni = NULL;
int num_active_macs = 0;
/* If changed_vif exists and is not to be removed, add to the count */
if (changed_vif && !remove_vif)
num_active_macs++;
switch (num_active_macs) {
case 0:
/* If there are no active macs - change state to SF_INIT_OFF */
new_state = IWM_SF_INIT_OFF;
break;
case 1:
if (!changed_vif)
return EINVAL;
ni = changed_vif->iv_bss;
if (ni != NULL && IWM_NODE(ni)->in_assoc &&
changed_vif->iv_dtim_period) {
new_state = IWM_SF_FULL_ON;
} else {
new_state = IWM_SF_INIT_OFF;
}
break;
default:
/* If there are multiple active macs - change to SF_UNINIT */
new_state = IWM_SF_UNINIT;
}
return iwm_mvm_sf_config(sc, ni, new_state);
}
@@ -0,0 +1,82 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_sf.h 319577 2017-06-04 21:05:58Z adrian $
*/
#ifndef __IF_IWM_SF_H__
#define __IF_IWM_SF_H__
extern int iwm_mvm_sf_update(struct iwm_softc *sc,
struct ieee80211vap *changed_vif,
boolean_t remove_vif);
#endif /* __IF_IWM_SF_H__ */
@@ -73,7 +73,7 @@
*****************************************************************************/ *****************************************************************************/
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_sta.c 330223 2018-03-01 06:55:46Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_sta.c 321508 2017-07-26 05:29:08Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -73,7 +73,7 @@
* *
*****************************************************************************/ *****************************************************************************/
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_sta.h 330213 2018-03-01 06:44:32Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_sta.h 318229 2017-05-12 06:33:07Z adrian $ */
#ifndef __IF_IWM_STA_H__ #ifndef __IF_IWM_STA_H__
#define __IF_IWM_STA_H__ #define __IF_IWM_STA_H__
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_time_event.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_time_event.c 318212 2017-05-12 05:19:08Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -1,5 +1,5 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */ /* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_time_event.h 330204 2018-03-01 06:36:41Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_time_event.h 318212 2017-05-12 05:19:08Z adrian $ */
/* /*
* Copyright (c) 2014 genua mbh <info@genua.de> * Copyright (c) 2014 genua mbh <info@genua.de>
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_util.c 330455 2018-03-05 08:05:30Z eadler $"); __FBSDID("$FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_util.c 321510 2017-07-26 05:51:31Z adrian $");
#include "opt_wlan.h" #include "opt_wlan.h"
#include "opt_iwm.h" #include "opt_iwm.h"
@@ -225,12 +225,11 @@ iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
} }
if (paylen > datasz) { if (paylen > datasz) {
size_t totlen;
IWM_DPRINTF(sc, IWM_DEBUG_CMD, IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"large command paylen=%u len0=%u\n", "large command paylen=%u len0=%u\n",
paylen, hcmd->len[0]); paylen, hcmd->len[0]);
/* Command is too large */ /* Command is too large */
totlen = hdrlen + paylen; size_t totlen = hdrlen + paylen;
if (paylen > IWM_MAX_CMD_PAYLOAD_SIZE) { if (paylen > IWM_MAX_CMD_PAYLOAD_SIZE) {
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
"firmware command too long (%zd bytes)\n", "firmware command too long (%zd bytes)\n",
@@ -1,5 +1,5 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */ /* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwm_util.h 330225 2018-03-01 06:56:34Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwm_util.h 321510 2017-07-26 05:51:31Z adrian $ */
/* /*
* Copyright (c) 2014 genua mbh <info@genua.de> * Copyright (c) 2014 genua mbh <info@genua.de>
@@ -1,5 +1,5 @@
/* $OpenBSD: if_iwmreg.h,v 1.4 2015/06/15 08:06:11 stsp Exp $ */ /* $OpenBSD: if_iwmreg.h,v 1.4 2015/06/15 08:06:11 stsp Exp $ */
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwmreg.h 330446 2018-03-05 06:59:30Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwmreg.h 327231 2017-12-27 03:23:21Z eadler $ */
/****************************************************************************** /******************************************************************************
* *
@@ -844,7 +844,7 @@ struct iwm_fw_cipher_scheme {
*/ */
struct iwm_fw_cscheme_list { struct iwm_fw_cscheme_list {
uint8_t size; uint8_t size;
struct iwm_fw_cipher_scheme cs[0]; struct iwm_fw_cipher_scheme cs[];
} __packed; } __packed;
/* /*
@@ -2012,7 +2012,7 @@ struct iwm_nvm_access_cmd {
uint16_t type; uint16_t type;
uint16_t offset; uint16_t offset;
uint16_t length; uint16_t length;
uint8_t data[0]; uint8_t data[];
} __packed; /* IWM_NVM_ACCESS_CMD_API_S_VER_2 */ } __packed; /* IWM_NVM_ACCESS_CMD_API_S_VER_2 */
#define IWM_NUM_OF_FW_PAGING_BLOCKS 33 /* 32 for data and 1 block for CSS */ #define IWM_NUM_OF_FW_PAGING_BLOCKS 33 /* 32 for data and 1 block for CSS */
@@ -2066,7 +2066,7 @@ struct iwm_nvm_access_resp {
uint16_t length; uint16_t length;
uint16_t type; uint16_t type;
uint16_t status; uint16_t status;
uint8_t data[0]; uint8_t data[];
} __packed; /* IWM_NVM_ACCESS_CMD_RESP_API_S_VER_2 */ } __packed; /* IWM_NVM_ACCESS_CMD_RESP_API_S_VER_2 */
/* IWM_MVM_ALIVE 0x1 */ /* IWM_MVM_ALIVE 0x1 */
@@ -4932,7 +4932,7 @@ struct iwm_scan_req_lmac {
uint32_t delay; uint32_t delay;
struct iwm_scan_schedule_lmac schedule[IWM_MAX_SCHED_SCAN_PLANS]; struct iwm_scan_schedule_lmac schedule[IWM_MAX_SCHED_SCAN_PLANS];
struct iwm_scan_channel_opt channel_opt[2]; struct iwm_scan_channel_opt channel_opt[2];
uint8_t data[0]; uint8_t data[];
} __packed; } __packed;
/** /**
@@ -5082,6 +5082,13 @@ enum iwm_scan_offload_complete_status {
IWM_SCAN_OFFLOAD_ABORTED = 2, IWM_SCAN_OFFLOAD_ABORTED = 2,
}; };
enum iwm_scan_ebs_status {
IWM_SCAN_EBS_SUCCESS,
IWM_SCAN_EBS_FAILED,
IWM_SCAN_EBS_CHAN_NOT_FOUND,
IWM_SCAN_EBS_INACTIVE,
};
/** /**
* struct iwm_lmac_scan_complete_notif - notifies end of scanning (all channels) * struct iwm_lmac_scan_complete_notif - notifies end of scanning (all channels)
* SCAN_COMPLETE_NTF_API_S_VER_3 * SCAN_COMPLETE_NTF_API_S_VER_3
@@ -5100,7 +5107,7 @@ struct iwm_lmac_scan_complete_notif {
uint8_t last_channel; uint8_t last_channel;
uint32_t tsf_low; uint32_t tsf_low;
uint32_t tsf_high; uint32_t tsf_high;
struct iwm_scan_results_notif results[0]; struct iwm_scan_results_notif results[];
} __packed; } __packed;
@@ -5203,7 +5210,7 @@ struct iwm_scan_config {
uint8_t mac_addr[IEEE80211_ADDR_LEN]; uint8_t mac_addr[IEEE80211_ADDR_LEN];
uint8_t bcast_sta_id; uint8_t bcast_sta_id;
uint8_t channel_flags; uint8_t channel_flags;
uint8_t channel_array[0]; uint8_t channel_array[];
} __packed; /* SCAN_CONFIG_DB_CMD_API_S */ } __packed; /* SCAN_CONFIG_DB_CMD_API_S */
/** /**
@@ -5322,7 +5329,7 @@ struct iwm_scan_req_umac {
uint8_t channel_flags; uint8_t channel_flags;
uint8_t n_channels; uint8_t n_channels;
uint16_t reserved; uint16_t reserved;
uint8_t data[0]; uint8_t data[];
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */ } __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */
/** /**
@@ -5419,7 +5426,7 @@ struct iwm_umac_scan_iter_complete_notif {
uint8_t last_channel; uint8_t last_channel;
uint32_t tsf_low; uint32_t tsf_low;
uint32_t tsf_high; uint32_t tsf_high;
struct iwm_scan_results_notif results[0]; struct iwm_scan_results_notif results[];
} __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_1 */ } __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_1 */
/* Please keep this enum *SORTED* by hex value. /* Please keep this enum *SORTED* by hex value.
@@ -6086,7 +6093,7 @@ struct iwm_rx_packet {
*/ */
uint32_t len_n_flags; uint32_t len_n_flags;
struct iwm_cmd_header hdr; struct iwm_cmd_header hdr;
uint8_t data[0]; uint8_t data[];
} __packed; } __packed;
#define IWM_FH_RSCSR_FRAME_SIZE_MSK 0x00003fff #define IWM_FH_RSCSR_FRAME_SIZE_MSK 0x00003fff
@@ -1,5 +1,5 @@
/* $OpenBSD: if_iwmvar.h,v 1.7 2015/03/02 13:51:10 jsg Exp $ */ /* $OpenBSD: if_iwmvar.h,v 1.7 2015/03/02 13:51:10 jsg Exp $ */
/* $FreeBSD: releng/11.2/sys/dev/iwm/if_iwmvar.h 330224 2018-03-01 06:56:10Z eadler $ */ /* $FreeBSD: releng/12.0/sys/dev/iwm/if_iwmvar.h 321509 2017-07-26 05:40:52Z adrian $ */
/* /*
* Copyright (c) 2014 genua mbh <info@genua.de> * Copyright (c) 2014 genua mbh <info@genua.de>
@@ -233,7 +233,7 @@ struct iwm_nvm_data {
uint8_t max_tx_pwr_half_dbm; uint8_t max_tx_pwr_half_dbm;
boolean_t lar_enabled; boolean_t lar_enabled;
uint16_t nvm_ch_flags[0]; uint16_t nvm_ch_flags[];
}; };
/* max bufs per tfd the driver will use */ /* max bufs per tfd the driver will use */
@@ -391,6 +391,9 @@ struct iwm_vap {
uint16_t edca_txop; uint16_t edca_txop;
uint8_t aifsn; uint8_t aifsn;
} queue_params[WME_NUM_AC]; } queue_params[WME_NUM_AC];
/* indicates that this interface requires PS to be disabled */
boolean_t ps_disabled;
}; };
#define IWM_VAP(_vap) ((struct iwm_vap *)(_vap)) #define IWM_VAP(_vap) ((struct iwm_vap *)(_vap))
@@ -554,11 +557,18 @@ struct iwm_softc {
uint16_t num_of_paging_blk; uint16_t num_of_paging_blk;
uint16_t num_of_pages_in_last_blk; uint16_t num_of_pages_in_last_blk;
boolean_t last_ebs_successful;
/* last smart fifo state that was successfully sent to firmware */
enum iwm_sf_state sf_state;
/* Indicate if device power save is allowed */ /* Indicate if device power save is allowed */
boolean_t sc_ps_disabled; boolean_t sc_ps_disabled;
#ifdef __HAIKU__
uint32_t sc_intr_status_1; uint32_t sc_intr_status_1;
uint32_t sc_intr_status_2; uint32_t sc_intr_status_2;
#endif
}; };
#define IWM_LOCK_INIT(_sc) \ #define IWM_LOCK_INIT(_sc) \