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 ;
# 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 ;
# 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_power.c
if_iwm_scan.c
if_iwm_sf.c
if_iwm_sta.c
if_iwm_time_event.c
if_iwm_util.c
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#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_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_power.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_pcie_trans.h>
@@ -230,8 +231,8 @@ struct iwm_nvm_section {
uint8_t *data;
};
#define IWM_MVM_UCODE_ALIVE_TIMEOUT (10*hz)
#define IWM_MVM_UCODE_CALIB_TIMEOUT (2*hz)
#define IWM_MVM_UCODE_ALIVE_TIMEOUT (5*hz)
#define IWM_MVM_UCODE_CALIB_TIMEOUT (10*hz)
struct iwm_mvm_alive_data {
int valid;
@@ -348,7 +349,6 @@ static int iwm_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int iwm_mvm_update_quotas(struct iwm_softc *, struct iwm_vap *);
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 struct ieee80211_node *
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_newstate(struct ieee80211vap *, enum ieee80211_state, 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 boolean_t iwm_mvm_is_lar_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;
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;
enum iwm_ucode_tlv_type tlv_type;
const struct firmware *fwp;
const uint8_t *data;
uint32_t tlv_len;
uint32_t usniffer_img;
const uint8_t *tlv_data;
uint32_t paging_mem_size;
int num_of_cpus;
int error = 0;
@@ -605,24 +603,20 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
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_MINOR(le32toh(uhdr->ver)),
IWM_UCODE_API(le32toh(uhdr->ver)));
data = uhdr->data;
len = fw->fw_fp->datasize - sizeof(*uhdr);
while (len >= sizeof(tlv)) {
size_t tlv_len;
const void *tlv_data;
while (len >= sizeof(*tlv)) {
len -= sizeof(*tlv);
tlv = (const void *)data;
memcpy(&tlv, data, sizeof(tlv));
tlv_len = le32toh(tlv.length);
tlv_type = le32toh(tlv.type);
len -= sizeof(tlv);
data += sizeof(tlv);
tlv_data = data;
tlv_len = le32toh(tlv->length);
tlv_type = le32toh(tlv->type);
tlv_data = tlv->data;
if (len < tlv_len) {
device_printf(sc->sc_dev,
@@ -631,19 +625,21 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
error = EINVAL;
goto parse_out;
}
len -= roundup2(tlv_len, 4);
data += sizeof(tlv) + roundup2(tlv_len, 4);
switch ((int)tlv_type) {
case IWM_UCODE_TLV_PROBE_MAX_LEN:
if (tlv_len < sizeof(uint32_t)) {
if (tlv_len != sizeof(uint32_t)) {
device_printf(sc->sc_dev,
"%s: PROBE_MAX_LEN (%d) < sizeof(uint32_t)\n",
"%s: PROBE_MAX_LEN (%d) != sizeof(uint32_t)\n",
__func__,
(int) tlv_len);
error = EINVAL;
goto parse_out;
}
capa->max_probe_length =
le32toh(*(const uint32_t *)tlv_data);
le32_to_cpup((const uint32_t *)tlv_data);
/* limit it to something sensible */
if (capa->max_probe_length >
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;
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
* 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
* ==> 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;
case IWM_UCODE_TLV_CSCHEME:
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;
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) {
fw->fw_sects[IWM_UCODE_REGULAR].is_dual_cpus =
TRUE;
@@ -780,7 +784,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
goto parse_out;
}
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 &
IWM_FW_PHY_CFG_TX_CHAIN) >>
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;
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,
"%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;
}
capa->n_scan_channels =
le32toh(*(const uint32_t *)tlv_data);
le32_to_cpup((const uint32_t *)tlv_data);
break;
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;
goto parse_out;
}
len -= roundup(tlv_len, 4);
data += roundup(tlv_len, 4);
}
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_FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
IWM_FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | /* HW bug */
//#ifdef __HAIKU__
#ifdef __HAIKU__
/* multi-frame RX seems to cause UAFs and double-frees */
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_RX_CONFIG_REG_VAL_RB_SIZE_4K |
(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;
}
/* Init Smart FIFO. */
ret = iwm_mvm_sf_config(sc, IWM_SF_INIT_OFF);
if (ret)
goto error;
/* Send TX valid antennas before triggering calibrations */
ret = iwm_send_tx_ant_cfg(sc, iwm_mvm_get_valid_tx_ant(sc));
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 */
rxs.c_rssi = rssi * 2;
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;
}
if (ieee80211_radiotap_active_vap(vap)) {
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;
fail: counter_u64_add(ic->ic_ierrors, 1);
fail:
counter_u64_add(ic->ic_ierrors, 1);
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->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);
IWM_DPRINTF(sc, IWM_DEBUG_TXRATE,
"%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);
IWM_DPRINTF(sc, IWM_DEBUG_TXRATE,
"%s: FIXED_RATE (%d)\n", __func__, tp->ucastrate);
} else if (m->m_flags & M_EAPOL) {
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) {
} else {
int i;
/* 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,
"%s: start with i=%d, txrate %d\n",
__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,
@@ -4016,10 +4010,6 @@ iwm_auth(struct ieee80211vap *vap, struct iwm_softc *sc)
goto out;
}
error = iwm_mvm_sf_config(sc, IWM_SF_FULL_ON);
if (error != 0)
return error;
error = iwm_allow_mcast(vap, sc);
if (error) {
device_printf(sc->sc_dev,
@@ -4048,55 +4038,45 @@ iwm_auth(struct ieee80211vap *vap, struct iwm_softc *sc)
"%s: failed to update MAC\n", __func__);
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 update phy ctxt\n", __func__);
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 update cmd\n", __func__);
goto out;
}
if ((error = iwm_mvm_update_sta(sc, in)) != 0) {
device_printf(sc->sc_dev,
"%s: failed to update sta\n", __func__);
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_power_update_mac(sc)) != 0) {
device_printf(sc->sc_dev,
"%s: failed to update power management\n",
__func__);
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) {
device_printf(sc->sc_dev,
"%s: failed to add sta\n", __func__);
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 update phy ctxt\n", __func__);
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 update cmd\n", __func__);
goto out;
}
/*
* Authentication becomes unreliable when powersaving is left enabled
* here. Powersaving will be activated again when association has
* finished or is aborted.
*/
iv->ps_disabled = TRUE;
error = iwm_mvm_power_update_mac(sc);
iv->ps_disabled = FALSE;
if (error != 0) {
device_printf(sc->sc_dev,
"%s: failed to update power management\n",
__func__);
goto out;
}
if ((error = iwm_mvm_add_sta(sc, in)) != 0) {
device_printf(sc->sc_dev,
"%s: failed to add sta\n", __func__);
goto out;
}
/*
@@ -4114,28 +4094,6 @@ out:
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
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);
}
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);
IEEE80211_LOCK(ic);
return myerr;
@@ -4483,33 +4447,38 @@ iwm_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
device_printf(sc->sc_dev,
"%s: could not move to auth state: %d\n",
__func__, error);
break;
}
break;
case IEEE80211_S_ASSOC:
if ((error = iwm_assoc(vap, sc)) != 0) {
device_printf(sc->sc_dev,
"%s: failed to associate: %d\n", __func__,
error);
break;
}
/*
* EBS may be disabled due to previous failures reported by FW.
* Reset EBS status here assuming environment has been changed.
*/
sc->last_ebs_successful = TRUE;
break;
case IEEE80211_S_RUN:
in = IWM_NODE(vap->iv_bss);
/* Update the association state, now we have it all */
/* (eg associd comes in at this point */
error = iwm_assoc(vap, sc);
error = iwm_mvm_update_sta(sc, in);
if (error != 0) {
device_printf(sc->sc_dev,
"%s: failed to update association state: %d\n",
__func__,
error);
break;
"%s: failed to update STA\n", __func__);
IWM_UNLOCK(sc);
IEEE80211_LOCK(ic);
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_enable_beacon_filter(sc, in);
iwm_mvm_sf_update(sc, vap, FALSE);
iwm_mvm_enable_beacon_filter(sc, ivp);
iwm_mvm_power_update_mac(sc);
iwm_mvm_update_quotas(sc, ivp);
iwm_setrates(sc, in);
@@ -4544,142 +4513,6 @@ iwm_endscan_cb(void *arg, int pending)
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
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;
int error, i, ac;
sc->sf_state = IWM_SF_UNINIT;
if ((error = iwm_start_hw(sc)) != 0) {
printf("iwm_start_hw: failed %d\n", error);
return error;
@@ -4843,6 +4678,10 @@ iwm_init_hw(struct iwm_softc *sc)
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) {
device_printf(sc->sc_dev, "bt init conf failed\n");
goto error;
@@ -5543,36 +5382,27 @@ iwm_handle_rxb(struct iwm_softc *sc, struct mbuf *m)
case IWM_INIT_COMPLETE_NOTIF:
break;
case IWM_SCAN_OFFLOAD_COMPLETE: {
struct iwm_periodic_scan_complete *notif;
notif = (void *)pkt->data;
case IWM_SCAN_OFFLOAD_COMPLETE:
iwm_mvm_rx_lmac_scan_complete_notif(sc, pkt);
if (sc->sc_flags & IWM_FLAG_SCAN_RUNNING) {
sc->sc_flags &= ~IWM_FLAG_SCAN_RUNNING;
ieee80211_runtask(ic, &sc->sc_es_task);
}
break;
}
case IWM_SCAN_ITERATION_COMPLETE: {
struct iwm_lmac_scan_complete_notif *notif;
notif = (void *)pkt->data;
ieee80211_runtask(&sc->sc_ic, &sc->sc_es_task);
break;
break;
}
case IWM_SCAN_COMPLETE_UMAC: {
struct iwm_umac_scan_complete *notif;
notif = (void *)pkt->data;
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"UMAC scan complete, status=0x%x\n",
notif->status);
case IWM_SCAN_COMPLETE_UMAC:
iwm_mvm_rx_umac_scan_complete_notif(sc, pkt);
if (sc->sc_flags & IWM_FLAG_SCAN_RUNNING) {
sc->sc_flags &= ~IWM_FLAG_SCAN_RUNNING;
ieee80211_runtask(ic, &sc->sc_es_task);
}
break;
}
case IWM_SCAN_ITERATION_COMPLETE_UMAC: {
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 "
"complete, status=0x%x, %d channels scanned\n",
notif->status, notif->scanned_channels);
ieee80211_runtask(&sc->sc_ic, &sc->sc_es_task);
break;
}
@@ -5868,6 +5697,7 @@ iwm_intr(void *arg)
#define PCI_PRODUCT_INTEL_WL_3160_2 0x08b4
#define PCI_PRODUCT_INTEL_WL_3165_1 0x3165
#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_2 0x08b2
#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_3165_1, &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_2, &iwm7260_cfg },
{ PCI_PRODUCT_INTEL_WL_7265_1, &iwm7265_cfg },
@@ -6026,6 +5857,8 @@ iwm_attach(device_t dev)
goto fail;
}
sc->sf_state = IWM_SF_UNINIT;
/* Init phy db */
sc->sc_phy_db = iwm_phy_db_init(sc);
if (!sc->sc_phy_db) {
@@ -6033,6 +5866,9 @@ iwm_attach(device_t dev)
goto fail;
}
/* Set EBS as successful as long as not stated otherwise by the FW. */
sc->last_ebs_successful = TRUE;
/* PCI attach */
error = iwm_pci_attach(dev);
if (error != 0)
@@ -6165,9 +6001,7 @@ iwm_attach(device_t dev)
// IEEE80211_C_BGSCAN /* capable of bg scanning */
;
/* Advertise full-offload scanning */
#ifndef __HAIKU__
ic->ic_flags_ext = IEEE80211_FEXT_SCAN_OFFLOAD;
#endif
for (i = 0; i < nitems(sc->sc_phyctxt); i++) {
sc->sc_phyctxt[i].id = i;
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 */
struct iwm_softc *sc = ic->ic_softc;
struct chanAccParams chp;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwm_vap *ivp = IWM_VAP(vap);
struct iwm_node *in;
@@ -6231,9 +6066,11 @@ iwm_wme_update(struct ieee80211com *ic)
if (vap == NULL)
return (0);
ieee80211_wme_ic_getparams(ic, &chp);
IEEE80211_LOCK(ic);
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);
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->have_wme = FALSE;
ivp->ps_disabled = FALSE;
ieee80211_ratectl_init(vap);
/* Complete setup. */
@@ -6637,6 +6475,8 @@ static driver_t iwm_pci_driver = {
static devclass_t iwm_devclass;
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, pci, 1, 1, 1);
MODULE_DEPEND(iwm, wlan, 1, 1, 1);
@@ -70,7 +70,7 @@
*****************************************************************************/
#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_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 IWM3160_FW "iwm3160fw"
#define IWM3168_FW "iwm3168fw"
#define IWM7265_FW "iwm7265fw"
#define IWM7265D_FW "iwm7265Dfw"
@@ -113,6 +114,13 @@ const struct iwm_cfg iwm3165_cfg = {
.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 = {
.name = "Intel(R) Dual Band Wireless AC 7265",
.fw_name = IWM7265_FW,
@@ -69,7 +69,7 @@
*****************************************************************************/
#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_iwm.h"
@@ -87,7 +87,7 @@
*/
#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_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_util.h>
#include <dev/iwm/if_iwm_binding.h>
#include <dev/iwm/if_iwm_sf.h>
/*
* 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)
return EINVAL;
#ifdef notyet
/*
* 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.
*/
if (iwm_mvm_sf_update(sc, ivp, FALSE))
if (iwm_mvm_sf_update(sc, &ivp->iv_vap, FALSE))
return EINVAL;
#endif
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);
#ifdef notyet
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,
"Failed to update SF state\n");
}
#endif
return ret;
}
@@ -1,5 +1,5 @@
/* $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 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__
@@ -128,6 +128,7 @@ struct iwm_cfg {
extern const struct iwm_cfg iwm7260_cfg;
extern const struct iwm_cfg iwm3160_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 iwm7265d_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
#define __IF_IWM_CONSTANTS_H
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* 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__
@@ -51,7 +51,7 @@ enum {
};
#define IWM_DPRINTF(sc, m, fmt, ...) do { \
if (sc->sc_debug & (m)) \
if (sc->sc_debug & (m)) \
device_printf(sc->sc_dev, fmt, ##__VA_ARGS__); \
} while (0)
#else
@@ -71,7 +71,7 @@
*/
#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_iwm.h"
@@ -71,7 +71,7 @@
* 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__
#define __IF_IWM_FW_H__
@@ -87,7 +87,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#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_iwm.h"
@@ -86,7 +86,7 @@
* (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/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__
#define __IF_IWM_LED_H__
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#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_iwm.h"
@@ -1,5 +1,5 @@
/* $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>
@@ -67,7 +67,7 @@
*****************************************************************************/
#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_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__
#define __IF_IWN_NOTIF_WAIT_H__
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#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_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 Fixup Software Ltd.
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#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_iwm.h"
@@ -1,5 +1,5 @@
/* $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>
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#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_iwm.h"
@@ -1,5 +1,5 @@
/* $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>
@@ -87,7 +87,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#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_iwm.h"
@@ -201,7 +201,7 @@ iwm_mvm_beacon_filter_send_cmd(struct iwm_softc *sc,
static void
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);
}
@@ -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,
"Sending power table command on mac id 0x%X for "
"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,
"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
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 ieee80211_node *ni = &in->in_ni;
struct ieee80211vap *vap = &ivp->iv_vap;
struct ieee80211_node *ni = vap->iv_bss;
int dtimper, dtimper_msec;
int keep_alive;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwm_vap *ivp = IWM_VAP(vap);
boolean_t bss_conf_ps = FALSE;
cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ivp->id,
ivp->color));
@@ -308,6 +307,14 @@ iwm_mvm_power_build_cmd(struct iwm_softc *sc, struct iwm_node *in,
return;
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);
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
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 = {};
iwm_mvm_power_build_cmd(sc, in, &cmd);
iwm_mvm_power_build_cmd(sc, ivp, &cmd);
iwm_mvm_power_log(sc, &cmd);
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
_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)
{
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);
if (!ret)
@@ -346,14 +353,14 @@ _iwm_mvm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_node *in,
}
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 = {
IWM_BF_CMD_CONFIG_DEFAULTS,
.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
@@ -372,15 +379,18 @@ iwm_mvm_disable_beacon_filter(struct iwm_softc *sc)
static int
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;
int ret;
/* disable PS if CAM */
disable_ps = (iwm_power_scheme == IWM_POWER_SCHEME_CAM);
/* ...or if any of the vifs require PS to be off */
if (vap != NULL && (vap->iv_flags & IEEE80211_F_PMGTON) == 0)
disable_ps = TRUE;
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;
}
/* update device power state if it has changed */
if (sc->sc_ps_disabled != disable_ps) {
@@ -398,19 +408,26 @@ iwm_mvm_power_set_ps(struct iwm_softc *sc)
}
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 = {
IWM_BF_CMD_CONFIG_DEFAULTS,
.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)
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
@@ -424,7 +441,7 @@ iwm_mvm_power_update_ps(struct iwm_softc *sc)
return ret;
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;
}
@@ -440,13 +457,13 @@ iwm_mvm_power_update_mac(struct iwm_softc *sc)
return ret;
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)
return ret;
}
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;
}
@@ -1,5 +1,5 @@
/* $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>
@@ -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_ps(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);
#endif /* __IF_IWM_POWER_H__ */
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#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_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
*/
#define IWM_DENSE_EBS_SCAN_RATIO 5
#define IWM_SPARSE_EBS_SCAN_RATIO 1
static uint16_t
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);
}
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
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);
}
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
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;
for (nchan = j = 0;
j < ic->ic_nchans && nchan < sc->ucode_capa.n_scan_channels; j++) {
c = &ic->ic_channels[j];
/* For 2GHz, only populate 11b channels */
/* For 5GHz, only populate 11a channels */
j < ss->ss_last && nchan < sc->ucode_capa.n_scan_channels; j++) {
c = ss->ss_chans[j];
/*
* Catch other channels, in case we have 900MHz channels or
* 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,
"%s: skipping channel (freq=%d, ieee=%d, flags=0x%08x)\n",
__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 ieee80211com *ic = &sc->sc_ic;
struct ieee80211_scan_state *ss = ic->ic_scan;
struct ieee80211_channel *c;
uint8_t nchan;
int j;
for (nchan = j = 0;
j < ic->ic_nchans && nchan < sc->ucode_capa.n_scan_channels; j++) {
c = &ic->ic_channels[j];
/* For 2GHz, only populate 11b channels */
/* For 5GHz, only populate 11a channels */
j < ss->ss_last && nchan < sc->ucode_capa.n_scan_channels; j++) {
c = ss->ss_chans[j];
/*
* Catch other channels, in case we have 900MHz channels or
* 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,
"%s: skipping channel (freq=%d, ieee=%d, flags=0x%08x)\n",
__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);
remain -= frm - pos;
if (fw_has_capa(&sc->ucode_capa,
IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) {
if (iwm_mvm_rrm_scan_needed(sc)) {
if (remain < 3)
return ENOBUFS;
*frm++ = IEEE80211_ELEMID_DSPARMS;
@@ -481,6 +563,21 @@ iwm_mvm_config_umac_scan(struct iwm_softc *sc)
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
iwm_mvm_umac_scan(struct iwm_softc *sc)
{
@@ -550,8 +647,12 @@ iwm_mvm_umac_scan(struct iwm_softc *sc)
} else
req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE);
if (fw_has_capa(&sc->ucode_capa,
IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT))
if (iwm_mvm_scan_use_ebs(sc))
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 |=
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 |
IWM_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE |
IWM_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL);
if (fw_has_capa(&sc->ucode_capa,
IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT))
if (iwm_mvm_rrm_scan_needed(sc))
req->scan_flags |= htole32(IWM_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED);
req->flags = htole32(IWM_PHY_BAND_24);
if (sc->nvm_data->sku_cap_band_52GHz_enable)
req->flags |= htole32(IWM_PHY_BAND_5);
req->flags = iwm_mvm_scan_rxon_flags(sc->sc_ic.ic_scan->ss_chans[0]);
req->filter_flags =
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].full_scan_mul = 1;
/* Disable EBS. */
req->channel_opt[0].non_ebs_ratio = 1;
req->channel_opt[1].non_ebs_ratio = 1;
if (iwm_mvm_scan_use_ebs(sc)) {
req->channel_opt[0].flags =
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);
if (!ret) {
@@ -1,5 +1,5 @@
/* $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>
@@ -106,9 +106,13 @@
#ifndef __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_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__ */
@@ -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>
__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_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__
#define __IF_IWM_STA_H__
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#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_iwm.h"
@@ -1,5 +1,5 @@
/* $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>
@@ -103,7 +103,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#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_iwm.h"
@@ -225,12 +225,11 @@ iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
}
if (paylen > datasz) {
size_t totlen;
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"large command paylen=%u len0=%u\n",
paylen, hcmd->len[0]);
/* Command is too large */
totlen = hdrlen + paylen;
size_t totlen = hdrlen + paylen;
if (paylen > IWM_MAX_CMD_PAYLOAD_SIZE) {
device_printf(sc->sc_dev,
"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 $ */
/* $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>
@@ -1,5 +1,5 @@
/* $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 {
uint8_t size;
struct iwm_fw_cipher_scheme cs[0];
struct iwm_fw_cipher_scheme cs[];
} __packed;
/*
@@ -2012,7 +2012,7 @@ struct iwm_nvm_access_cmd {
uint16_t type;
uint16_t offset;
uint16_t length;
uint8_t data[0];
uint8_t data[];
} __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 */
@@ -2066,7 +2066,7 @@ struct iwm_nvm_access_resp {
uint16_t length;
uint16_t type;
uint16_t status;
uint8_t data[0];
uint8_t data[];
} __packed; /* IWM_NVM_ACCESS_CMD_RESP_API_S_VER_2 */
/* IWM_MVM_ALIVE 0x1 */
@@ -4932,7 +4932,7 @@ struct iwm_scan_req_lmac {
uint32_t delay;
struct iwm_scan_schedule_lmac schedule[IWM_MAX_SCHED_SCAN_PLANS];
struct iwm_scan_channel_opt channel_opt[2];
uint8_t data[0];
uint8_t data[];
} __packed;
/**
@@ -5082,6 +5082,13 @@ enum iwm_scan_offload_complete_status {
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)
* SCAN_COMPLETE_NTF_API_S_VER_3
@@ -5100,7 +5107,7 @@ struct iwm_lmac_scan_complete_notif {
uint8_t last_channel;
uint32_t tsf_low;
uint32_t tsf_high;
struct iwm_scan_results_notif results[0];
struct iwm_scan_results_notif results[];
} __packed;
@@ -5203,7 +5210,7 @@ struct iwm_scan_config {
uint8_t mac_addr[IEEE80211_ADDR_LEN];
uint8_t bcast_sta_id;
uint8_t channel_flags;
uint8_t channel_array[0];
uint8_t channel_array[];
} __packed; /* SCAN_CONFIG_DB_CMD_API_S */
/**
@@ -5322,7 +5329,7 @@ struct iwm_scan_req_umac {
uint8_t channel_flags;
uint8_t n_channels;
uint16_t reserved;
uint8_t data[0];
uint8_t data[];
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */
/**
@@ -5419,7 +5426,7 @@ struct iwm_umac_scan_iter_complete_notif {
uint8_t last_channel;
uint32_t tsf_low;
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 */
/* Please keep this enum *SORTED* by hex value.
@@ -6086,7 +6093,7 @@ struct iwm_rx_packet {
*/
uint32_t len_n_flags;
struct iwm_cmd_header hdr;
uint8_t data[0];
uint8_t data[];
} __packed;
#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 $ */
/* $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>
@@ -233,7 +233,7 @@ struct iwm_nvm_data {
uint8_t max_tx_pwr_half_dbm;
boolean_t lar_enabled;
uint16_t nvm_ch_flags[0];
uint16_t nvm_ch_flags[];
};
/* max bufs per tfd the driver will use */
@@ -391,6 +391,9 @@ struct iwm_vap {
uint16_t edca_txop;
uint8_t aifsn;
} 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))
@@ -554,11 +557,18 @@ struct iwm_softc {
uint16_t num_of_paging_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 */
boolean_t sc_ps_disabled;
#ifdef __HAIKU__
uint32_t sc_intr_status_1;
uint32_t sc_intr_status_2;
#endif
};
#define IWM_LOCK_INIT(_sc) \