1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-19 10:53:58 +00:00

iwm(4) synchronize driver to DragonFlyBSD version and recent f/w update.

Submitted by:	Kevin Bowling (kevin.bowling@kev009.com)
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D6967
This commit is contained in:
Sean Bruno 2016-07-26 00:02:17 +00:00
parent 33c7715f9b
commit 6a5bc1d1ee
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=303327
15 changed files with 3257 additions and 734 deletions

File diff suppressed because it is too large Load Diff

View File

@ -148,13 +148,13 @@ iwm_mvm_led_disable(struct iwm_softc *sc)
IWM_WRITE(sc, IWM_CSR_LED_REG, IWM_CSR_LED_REG_TURN_OFF);
}
int
static int
iwm_mvm_led_is_enabled(struct iwm_softc *sc)
{
return (IWM_READ(sc, IWM_CSR_LED_REG) == IWM_CSR_LED_REG_TURN_ON);
}
void
static void
iwm_led_blink_timeout(void *arg)
{
struct iwm_softc *sc = arg;
@ -177,6 +177,6 @@ iwm_led_blink_start(struct iwm_softc *sc)
void
iwm_led_blink_stop(struct iwm_softc *sc)
{
callout_drain(&sc->sc_led_blink_to);
callout_stop(&sc->sc_led_blink_to);
iwm_mvm_led_disable(sc);
}

View File

@ -91,11 +91,9 @@
#ifndef __IF_IWM_LED_H__
#define __IF_IWM_LED_H__
void iwm_mvm_led_enable(struct iwm_softc *);
void iwm_mvm_led_disable(struct iwm_softc *);
int iwm_mvm_led_is_enabled(struct iwm_softc *);
void iwm_led_blink_timeout(void *);
void iwm_led_blink_start(struct iwm_softc *);
void iwm_led_blink_stop(struct iwm_softc *);
extern void iwm_mvm_led_enable(struct iwm_softc *);
extern void iwm_mvm_led_disable(struct iwm_softc *);
extern void iwm_led_blink_start(struct iwm_softc *);
extern void iwm_led_blink_stop(struct iwm_softc *);
#endif /* __IF_IWM_LED_H__ */

View File

@ -280,12 +280,24 @@ iwm_mvm_mac_ctxt_cmd_common(struct iwm_softc *sc, struct iwm_node *in,
/*
* XXX should we error out if in_assoc is 1 and ni == NULL?
*/
#if 0
if (in->in_assoc) {
IEEE80211_ADDR_COPY(cmd->bssid_addr, ni->ni_bssid);
} else {
/* eth broadcast address */
memset(cmd->bssid_addr, 0xff, sizeof(cmd->bssid_addr));
IEEE80211_ADDR_COPY(cmd->bssid_addr, ieee80211broadcastaddr);
}
#else
/*
* XXX This workaround makes the firmware behave more correctly once
* we are associated, regularly giving us statistics notifications,
* as well as signaling missed beacons to us.
* Since we only call iwm_mvm_mac_ctxt_add() and
* iwm_mvm_mac_ctxt_changed() when already authenticating or
* associating, ni->ni_bssid should always make sense here.
*/
IEEE80211_ADDR_COPY(cmd->bssid_addr, ni->ni_bssid);
#endif
/*
* Default to 2ghz if no node information is given.
@ -457,13 +469,7 @@ static int
iwm_mvm_mac_ctx_send(struct iwm_softc *sc, struct ieee80211vap *vap,
uint32_t action)
{
int ret;
ret = iwm_mvm_mac_ctxt_cmd_station(sc, vap, action);
if (ret)
return (ret);
return (0);
return iwm_mvm_mac_ctxt_cmd_station(sc, vap, action);
}
int
@ -489,17 +495,13 @@ int
iwm_mvm_mac_ctxt_changed(struct iwm_softc *sc, struct ieee80211vap *vap)
{
struct iwm_vap *iv = IWM_VAP(vap);
int ret;
if (iv->is_uploaded == 0) {
device_printf(sc->sc_dev, "%s: called; uploaded = 0\n",
__func__);
return (EIO);
}
ret = iwm_mvm_mac_ctx_send(sc, vap, IWM_FW_CTXT_ACTION_MODIFY);
if (ret)
return (ret);
return (0);
return iwm_mvm_mac_ctx_send(sc, vap, IWM_FW_CTXT_ACTION_MODIFY);
}
#if 0

View File

@ -256,13 +256,18 @@ iwm_nic_lock(struct iwm_softc *sc)
IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
if (sc->sc_device_family == IWM_DEVICE_FAMILY_8000)
DELAY(2);
if (iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
| IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP, 15000)) {
rv = 1;
rv = 1;
} else {
/* jolt */
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
"%s: resetting device via NMI\n", __func__);
IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_FORCE_NMI);
}
@ -343,13 +348,20 @@ iwm_check_rfkill(struct iwm_softc *sc)
int
iwm_set_hw_ready(struct iwm_softc *sc)
{
int ready;
IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
return iwm_poll_bit(sc, IWM_CSR_HW_IF_CONFIG_REG,
ready = iwm_poll_bit(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
IWM_HW_READY_TIMEOUT);
if (ready) {
IWM_SETBITS(sc, IWM_CSR_MBOX_SET_REG,
IWM_CSR_MBOX_SET_REG_OS_ALIVE);
}
return ready;
}
#undef IWM_HW_READY_TIMEOUT
@ -413,8 +425,10 @@ iwm_apm_init(struct iwm_softc *sc)
IWM_DPRINTF(sc, IWM_DEBUG_RESET, "iwm apm start\n");
/* Disable L0S exit timer (platform NMI Work/Around) */
IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,
IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
if (sc->sc_device_family != IWM_DEVICE_FAMILY_8000) {
IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,
IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
}
/*
* Disable L0s without affecting L1;
@ -435,7 +449,7 @@ iwm_apm_init(struct iwm_softc *sc)
iwm_apm_config(sc);
#if 0 /* not for 7k */
#if 0 /* not for 7k/8k */
/* Configure analog phase-lock-loop before activating to D0A */
if (trans->cfg->base_params->pll_cfg_val)
IWM_SETBITS(trans, IWM_CSR_ANA_PLL_CFG,
@ -491,18 +505,19 @@ iwm_apm_init(struct iwm_softc *sc)
* do not disable clocks. This preserves any hardware bits already
* set by default in "CLK_CTRL_REG" after reset.
*/
iwm_write_prph(sc, IWM_APMG_CLK_EN_REG, IWM_APMG_CLK_VAL_DMA_CLK_RQT);
//kpause("iwmapm", 0, mstohz(20), NULL);
DELAY(20);
if (sc->sc_device_family == IWM_DEVICE_FAMILY_7000) {
iwm_write_prph(sc, IWM_APMG_CLK_EN_REG,
IWM_APMG_CLK_VAL_DMA_CLK_RQT);
DELAY(20);
/* Disable L1-Active */
iwm_set_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,
IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
/* Clear the interrupt in APMG if the NIC is in RFKILL */
iwm_write_prph(sc, IWM_APMG_RTC_INT_STT_REG,
IWM_APMG_RTC_INT_STT_RFKILL);
/* Disable L1-Active */
iwm_set_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,
IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
/* Clear the interrupt in APMG if the NIC is in RFKILL */
iwm_write_prph(sc, IWM_APMG_RTC_INT_STT_REG,
IWM_APMG_RTC_INT_STT_RFKILL);
}
out:
if (error)
device_printf(sc->sc_dev, "apm init error %d\n", error);
@ -533,9 +548,7 @@ iwm_start_hw(struct iwm_softc *sc)
return error;
/* Reset the entire device */
IWM_WRITE(sc, IWM_CSR_RESET,
IWM_CSR_RESET_REG_FLAG_SW_RESET |
IWM_CSR_RESET_REG_FLAG_NEVO_RESET);
IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET);
DELAY(10);
if ((error = iwm_apm_init(sc)) != 0)

View File

@ -202,8 +202,8 @@ iwm_mvm_phy_ctxt_cmd_data(struct iwm_softc *sc,
ieee80211_chan2ieee(ic, chan),
chains_static,
chains_dynamic,
IWM_FW_VALID_RX_ANT(sc),
IWM_FW_VALID_TX_ANT(sc));
iwm_fw_valid_rx_ant(sc),
iwm_fw_valid_tx_ant(sc));
cmd->ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
@ -217,13 +217,13 @@ iwm_mvm_phy_ctxt_cmd_data(struct iwm_softc *sc,
idle_cnt = chains_static;
active_cnt = chains_dynamic;
cmd->rxchain_info = htole32(IWM_FW_VALID_RX_ANT(sc) <<
cmd->rxchain_info = htole32(iwm_fw_valid_rx_ant(sc) <<
IWM_PHY_RX_CHAIN_VALID_POS);
cmd->rxchain_info |= htole32(idle_cnt << IWM_PHY_RX_CHAIN_CNT_POS);
cmd->rxchain_info |= htole32(active_cnt <<
IWM_PHY_RX_CHAIN_MIMO_CNT_POS);
cmd->txchain_info = htole32(IWM_FW_VALID_TX_ANT(sc));
cmd->txchain_info = htole32(iwm_fw_valid_tx_ant(sc));
}
/*

View File

@ -343,7 +343,6 @@ iwm_send_phy_db_cmd(struct iwm_softc *sc, uint16_t type,
cmd.len[0] = sizeof(struct iwm_phy_db_cmd);
cmd.data[1] = data;
cmd.len[1] = length;
cmd.dataflags[1] = IWM_HCMD_DFL_NOCOPY;
return iwm_send_cmd(sc, &cmd);
}
@ -374,6 +373,7 @@ iwm_phy_db_send_all_channel_groups(struct iwm_softc *sc,
return err;
}
DELAY(1000);
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"Sent PHY_DB HCMD, type = %d num = %d\n", type, i);
}

View File

@ -335,14 +335,3 @@ iwm_mvm_disable_beacon_filter(struct iwm_softc *sc)
return ret;
}
#if 0
static int
iwm_mvm_update_beacon_filter(struct iwm_softc *sc, struct iwm_node *in)
{
if (!sc->sc_bf.bf_enabled)
return 0;
return iwm_mvm_enable_beacon_filter(sc, in);
}
#endif

View File

@ -172,7 +172,7 @@ iwm_mvm_scan_rx_chain(struct iwm_softc *sc)
uint16_t rx_chain;
uint8_t rx_ant;
rx_ant = IWM_FW_VALID_RX_ANT(sc);
rx_ant = iwm_fw_valid_rx_ant(sc);
rx_chain = rx_ant << IWM_PHY_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_SEL_POS;
@ -180,6 +180,7 @@ iwm_mvm_scan_rx_chain(struct iwm_softc *sc)
return htole16(rx_chain);
}
#if 0
static uint32_t
iwm_mvm_scan_max_out_time(struct iwm_softc *sc, uint32_t flags, int is_assoc)
{
@ -197,15 +198,7 @@ iwm_mvm_scan_suspend_time(struct iwm_softc *sc, int is_assoc)
return 0;
return htole32(SUSPEND_TIME_PERIOD);
}
static uint32_t
iwm_mvm_scan_rxon_flags(struct iwm_softc *sc, int flags)
{
if (flags & IEEE80211_CHAN_2GHZ)
return htole32(IWM_PHY_BAND_24);
else
return htole32(IWM_PHY_BAND_5);
}
#endif
static uint32_t
iwm_mvm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck)
@ -216,7 +209,7 @@ iwm_mvm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck)
for (i = 0, ind = sc->sc_scan_last_antenna;
i < IWM_RATE_MCS_ANT_NUM; i++) {
ind = (ind + 1) % IWM_RATE_MCS_ANT_NUM;
if (IWM_FW_VALID_TX_ANT(sc) & (1 << ind)) {
if (iwm_fw_valid_tx_ant(sc) & (1 << ind)) {
sc->sc_scan_last_antenna = ind;
break;
}
@ -230,6 +223,7 @@ iwm_mvm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck)
return htole32(IWM_RATE_6M_PLCP | tx_ant);
}
#if 0
/*
* If req->n_ssids > 0, it means we should do an active scan.
* In case of active scan w/o directed scan, we receive a zero-length SSID
@ -253,24 +247,30 @@ iwm_mvm_get_passive_dwell(struct iwm_softc *sc, int flags)
{
return (flags & IEEE80211_CHAN_2GHZ) ? 100 + 20 : 100 + 10;
}
#endif
static int
iwm_mvm_scan_fill_channels(struct iwm_softc *sc, struct iwm_scan_cmd *cmd,
int flags, int n_ssids, int basic_ssid)
iwm_mvm_scan_skip_channel(struct ieee80211_channel *c)
{
if (IEEE80211_IS_CHAN_2GHZ(c) && IEEE80211_IS_CHAN_B(c))
return 0;
else if (IEEE80211_IS_CHAN_5GHZ(c) && IEEE80211_IS_CHAN_A(c))
return 0;
else
return 1;
}
static uint8_t
iwm_mvm_lmac_scan_fill_channels(struct iwm_softc *sc,
struct iwm_scan_channel_cfg_lmac *chan, int n_ssids)
{
struct ieee80211com *ic = &sc->sc_ic;
uint16_t passive_dwell = iwm_mvm_get_passive_dwell(sc, flags);
uint16_t active_dwell = iwm_mvm_get_active_dwell(sc, flags, n_ssids);
struct iwm_scan_channel *chan = (struct iwm_scan_channel *)
(cmd->data + le16toh(cmd->tx_cmd.len));
int type = (1 << n_ssids) - 1;
struct ieee80211_channel *c;
int nchan, j;
uint8_t nchan;
int j;
if (!basic_ssid)
type |= (1 << n_ssids);
for (nchan = j = 0; j < ic->ic_nchans; j++) {
for (nchan = j = 0;
j < ic->ic_nchans && nchan < sc->sc_capa_n_scan_channels; j++) {
c = &ic->ic_channels[j];
/* For 2GHz, only populate 11b channels */
/* For 5GHz, only populate 11a channels */
@ -278,175 +278,458 @@ iwm_mvm_scan_fill_channels(struct iwm_softc *sc, struct iwm_scan_cmd *cmd,
* Catch other channels, in case we have 900MHz channels or
* something in the chanlist.
*/
if ((flags & IEEE80211_CHAN_2GHZ) && (! IEEE80211_IS_CHAN_B(c))) {
continue;
} else if ((flags & IEEE80211_CHAN_5GHZ) && (! IEEE80211_IS_CHAN_A(c))) {
continue;
} else {
if (iwm_mvm_scan_skip_channel(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);
__func__, c->ic_freq, c->ic_ieee, c->ic_flags);
continue;
}
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM,
"Adding channel %d (%d Mhz) to the list\n",
nchan, c->ic_freq);
chan->channel = htole16(ieee80211_mhz2ieee(c->ic_freq, flags));
chan->type = htole32(type);
if (c->ic_flags & IEEE80211_CHAN_PASSIVE)
chan->type &= htole32(~IWM_SCAN_CHANNEL_TYPE_ACTIVE);
chan->active_dwell = htole16(active_dwell);
chan->passive_dwell = htole16(passive_dwell);
chan->iteration_count = htole16(1);
nchan, c->ic_freq);
chan->channel_num = htole16(ieee80211_mhz2ieee(c->ic_freq, 0));
chan->iter_count = htole16(1);
chan->iter_interval = htole32(0);
chan->flags = htole32(IWM_UNIFIED_SCAN_CHANNEL_PARTIAL);
#if 0 /* makes scanning while associated less useful */
if (n_ssids != 0)
chan->flags |= htole32(1 << 1); /* select SSID 0 */
#endif
chan++;
nchan++;
}
if (nchan == 0)
device_printf(sc->sc_dev,
"%s: NO CHANNEL!\n", __func__);
return nchan;
}
/*
* Fill in probe request with the following parameters:
* TA is our vif HW address, which mac80211 ensures we have.
* Packet is broadcasted, so this is both SA and DA.
* The probe request IE is made out of two: first comes the most prioritized
* SSID if a directed scan is requested. Second comes whatever extra
* information was given to us as the scan request IE.
*/
static uint16_t
iwm_mvm_fill_probe_req(struct iwm_softc *sc, struct ieee80211_frame *frame,
const uint8_t *ta, int n_ssids, const uint8_t *ssid, int ssid_len,
const uint8_t *ie, int ie_len, int left)
static uint8_t
iwm_mvm_umac_scan_fill_channels(struct iwm_softc *sc,
struct iwm_scan_channel_cfg_umac *chan, int n_ssids)
{
uint8_t *pos = NULL;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *c;
uint8_t nchan;
int j;
/* Make sure there is enough space for the probe request,
* two mandatory IEs and the data */
left -= sizeof(*frame);
if (left < 0)
return 0;
for (nchan = j = 0;
j < ic->ic_nchans && nchan < sc->sc_capa_n_scan_channels; j++) {
c = &ic->ic_channels[j];
/* For 2GHz, only populate 11b channels */
/* For 5GHz, only populate 11a channels */
/*
* Catch other channels, in case we have 900MHz channels or
* something in the chanlist.
*/
if (iwm_mvm_scan_skip_channel(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);
continue;
}
frame->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
frame->i_fc[1] = IEEE80211_FC1_DIR_NODS;
IEEE80211_ADDR_COPY(frame->i_addr1, ieee80211broadcastaddr);
IEEE80211_ADDR_COPY(frame->i_addr2, ta);
IEEE80211_ADDR_COPY(frame->i_addr3, ieee80211broadcastaddr);
/* for passive scans, no need to fill anything */
if (n_ssids == 0)
return sizeof(*frame);
/* points to the payload of the request */
pos = (uint8_t *)frame + sizeof(*frame);
/* fill in our SSID IE */
left -= ssid_len + 2;
if (left < 0)
return 0;
pos = ieee80211_add_ssid(pos, ssid, ssid_len);
if (ie && ie_len && left >= ie_len) {
memcpy(pos, ie, ie_len);
pos += ie_len;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM,
"Adding channel %d (%d Mhz) to the list\n",
nchan, c->ic_freq);
chan->channel_num = ieee80211_mhz2ieee(c->ic_freq, 0);
chan->iter_count = 1;
chan->iter_interval = htole16(0);
chan->flags = htole32(0);
#if 0 /* makes scanning while associated less useful */
if (n_ssids != 0)
chan->flags = htole32(1 << 0); /* select SSID 0 */
#endif
chan++;
nchan++;
}
return pos - (uint8_t *)frame;
return nchan;
}
static int
iwm_mvm_fill_probe_req(struct iwm_softc *sc, struct iwm_scan_probe_req *preq)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_frame *wh = (struct ieee80211_frame *)preq->buf;
struct ieee80211_rateset *rs;
size_t remain = sizeof(preq->buf);
uint8_t *frm, *pos;
int ssid_len = 0;
const uint8_t *ssid = NULL;
memset(preq, 0, sizeof(*preq));
/* Ensure enough space for header and SSID IE. */
if (remain < sizeof(*wh) + 2 + ssid_len)
return ENOBUFS;
/*
* Build a probe request frame. Most of the following code is a
* copy & paste of what is done in net80211.
*/
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr);
IEEE80211_ADDR_COPY(wh->i_addr2, vap ? vap->iv_myaddr : ic->ic_macaddr);
IEEE80211_ADDR_COPY(wh->i_addr3, ieee80211broadcastaddr);
*(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */
*(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */
frm = (uint8_t *)(wh + 1);
frm = ieee80211_add_ssid(frm, ssid, ssid_len);
/* Tell the firmware where the MAC header is. */
preq->mac_header.offset = 0;
preq->mac_header.len = htole16(frm - (uint8_t *)wh);
remain -= frm - (uint8_t *)wh;
/* Fill in 2GHz IEs and tell firmware where they are. */
rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];
if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
if (remain < 4 + rs->rs_nrates)
return ENOBUFS;
} else if (remain < 2 + rs->rs_nrates) {
return ENOBUFS;
}
preq->band_data[0].offset = htole16(frm - (uint8_t *)wh);
pos = frm;
frm = ieee80211_add_rates(frm, rs);
if (rs->rs_nrates > IEEE80211_RATE_SIZE)
frm = ieee80211_add_xrates(frm, rs);
preq->band_data[0].len = htole16(frm - pos);
remain -= frm - pos;
if (isset(sc->sc_enabled_capa,
IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) {
if (remain < 3)
return ENOBUFS;
*frm++ = IEEE80211_ELEMID_DSPARMS;
*frm++ = 1;
*frm++ = 0;
remain -= 3;
}
if (sc->sc_nvm.sku_cap_band_52GHz_enable) {
/* Fill in 5GHz IEs. */
rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];
if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
if (remain < 4 + rs->rs_nrates)
return ENOBUFS;
} else if (remain < 2 + rs->rs_nrates) {
return ENOBUFS;
}
preq->band_data[1].offset = htole16(frm - (uint8_t *)wh);
pos = frm;
frm = ieee80211_add_rates(frm, rs);
if (rs->rs_nrates > IEEE80211_RATE_SIZE)
frm = ieee80211_add_xrates(frm, rs);
preq->band_data[1].len = htole16(frm - pos);
remain -= frm - pos;
}
/* Send 11n IEs on both 2GHz and 5GHz bands. */
preq->common_data.offset = htole16(frm - (uint8_t *)wh);
pos = frm;
#if 0
if (ic->ic_flags & IEEE80211_F_HTON) {
if (remain < 28)
return ENOBUFS;
frm = ieee80211_add_htcaps(frm, ic);
/* XXX add WME info? */
}
#endif
preq->common_data.len = htole16(frm - pos);
return 0;
}
int
iwm_mvm_scan_request(struct iwm_softc *sc, int flags,
int n_ssids, uint8_t *ssid, int ssid_len)
iwm_mvm_config_umac_scan(struct iwm_softc *sc)
{
struct iwm_host_cmd hcmd = {
.id = IWM_SCAN_REQUEST_CMD,
.len = { 0, },
.data = { sc->sc_scan_cmd, },
.flags = IWM_CMD_SYNC,
.dataflags = { IWM_HCMD_DFL_NOCOPY, },
};
struct iwm_scan_cmd *cmd = sc->sc_scan_cmd;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int is_assoc = 0;
int ret;
uint32_t status;
int basic_ssid =
!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_NO_BASIC_SSID);
sc->sc_scanband = flags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ);
struct iwm_scan_config *scan_config;
int ret, j, nchan;
size_t cmd_size;
struct ieee80211_channel *c;
struct iwm_host_cmd hcmd = {
.id = iwm_cmd_id(IWM_SCAN_CFG_CMD, IWM_ALWAYS_LONG_GROUP, 0),
.flags = IWM_CMD_SYNC,
};
static const uint32_t rates = (IWM_SCAN_CONFIG_RATE_1M |
IWM_SCAN_CONFIG_RATE_2M | IWM_SCAN_CONFIG_RATE_5M |
IWM_SCAN_CONFIG_RATE_11M | IWM_SCAN_CONFIG_RATE_6M |
IWM_SCAN_CONFIG_RATE_9M | IWM_SCAN_CONFIG_RATE_12M |
IWM_SCAN_CONFIG_RATE_18M | IWM_SCAN_CONFIG_RATE_24M |
IWM_SCAN_CONFIG_RATE_36M | IWM_SCAN_CONFIG_RATE_48M |
IWM_SCAN_CONFIG_RATE_54M);
cmd_size = sizeof(*scan_config) + sc->sc_capa_n_scan_channels;
scan_config = malloc(cmd_size, M_DEVBUF, M_NOWAIT | M_ZERO);
if (scan_config == NULL)
return ENOMEM;
scan_config->tx_chains = htole32(iwm_fw_valid_tx_ant(sc));
scan_config->rx_chains = htole32(iwm_fw_valid_rx_ant(sc));
scan_config->legacy_rates = htole32(rates |
IWM_SCAN_CONFIG_SUPPORTED_RATE(rates));
/* These timings correspond to iwlwifi's UNASSOC scan. */
scan_config->dwell_active = 10;
scan_config->dwell_passive = 110;
scan_config->dwell_fragmented = 44;
scan_config->dwell_extended = 90;
scan_config->out_of_channel_time = htole32(0);
scan_config->suspend_time = htole32(0);
IEEE80211_ADDR_COPY(scan_config->mac_addr,
vap ? vap->iv_myaddr : ic->ic_macaddr);
scan_config->bcast_sta_id = sc->sc_aux_sta.sta_id;
scan_config->channel_flags = IWM_CHANNEL_FLAG_EBS |
IWM_CHANNEL_FLAG_ACCURATE_EBS | IWM_CHANNEL_FLAG_EBS_ADD |
IWM_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;
for (nchan = j = 0;
j < ic->ic_nchans && nchan < sc->sc_capa_n_scan_channels; j++) {
c = &ic->ic_channels[j];
/* For 2GHz, only populate 11b channels */
/* For 5GHz, only populate 11a channels */
/*
* Catch other channels, in case we have 900MHz channels or
* something in the chanlist.
*/
if (iwm_mvm_scan_skip_channel(c))
continue;
scan_config->channel_array[nchan++] =
ieee80211_mhz2ieee(c->ic_freq, 0);
}
scan_config->flags = htole32(IWM_SCAN_CONFIG_FLAG_ACTIVATE |
IWM_SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |
IWM_SCAN_CONFIG_FLAG_SET_TX_CHAINS |
IWM_SCAN_CONFIG_FLAG_SET_RX_CHAINS |
IWM_SCAN_CONFIG_FLAG_SET_AUX_STA_ID |
IWM_SCAN_CONFIG_FLAG_SET_ALL_TIMES |
IWM_SCAN_CONFIG_FLAG_SET_LEGACY_RATES |
IWM_SCAN_CONFIG_FLAG_SET_MAC_ADDR |
IWM_SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
IWM_SCAN_CONFIG_N_CHANNELS(nchan) |
IWM_SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED);
hcmd.data[0] = scan_config;
hcmd.len[0] = cmd_size;
IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Sending UMAC scan config\n");
ret = iwm_send_cmd(sc, &hcmd);
if (!ret)
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"UMAC scan config was sent successfully\n");
free(scan_config, M_DEVBUF);
return ret;
}
int
iwm_mvm_umac_scan(struct iwm_softc *sc)
{
struct iwm_host_cmd hcmd = {
.id = iwm_cmd_id(IWM_SCAN_REQ_UMAC, IWM_ALWAYS_LONG_GROUP, 0),
.len = { 0, },
.data = { NULL, },
.flags = IWM_CMD_SYNC,
};
struct iwm_scan_req_umac *req;
struct iwm_scan_req_umac_tail *tail;
size_t req_len;
int ssid_len = 0;
const uint8_t *ssid = NULL;
int ret;
req_len = sizeof(struct iwm_scan_req_umac) +
(sizeof(struct iwm_scan_channel_cfg_umac) *
sc->sc_capa_n_scan_channels) +
sizeof(struct iwm_scan_req_umac_tail);
if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE)
return ENOMEM;
req = malloc(req_len, M_DEVBUF, M_NOWAIT | M_ZERO);
if (req == NULL)
return ENOMEM;
hcmd.len[0] = (uint16_t)req_len;
hcmd.data[0] = (void *)req;
IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Handling ieee80211 scan request\n");
/* These timings correspond to iwlwifi's UNASSOC scan. */
req->active_dwell = 10;
req->passive_dwell = 110;
req->fragmented_dwell = 44;
req->extended_dwell = 90;
req->max_out_time = 0;
req->suspend_time = 0;
req->scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH);
req->ooc_priority = htole32(IWM_SCAN_PRIORITY_HIGH);
req->n_channels = iwm_mvm_umac_scan_fill_channels(sc,
(struct iwm_scan_channel_cfg_umac *)req->data, ssid_len != 0);
req->general_flags = htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL |
IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE |
IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL);
tail = (void *)((char *)&req->data +
sizeof(struct iwm_scan_channel_cfg_umac) *
sc->sc_capa_n_scan_channels);
/* Check if we're doing an active directed scan. */
if (ssid_len != 0) {
tail->direct_scan[0].id = IEEE80211_ELEMID_SSID;
tail->direct_scan[0].len = ssid_len;
memcpy(tail->direct_scan[0].ssid, ssid, ssid_len);
req->general_flags |=
htole32(IWM_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT);
} else {
req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE);
}
if (isset(sc->sc_enabled_capa,
IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT))
req->general_flags |=
htole32(IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED);
ret = iwm_mvm_fill_probe_req(sc, &tail->preq);
if (ret) {
free(req, M_DEVBUF);
return ret;
}
/* Specify the scan plan: We'll do one iteration. */
tail->schedule[0].interval = 0;
tail->schedule[0].iter_count = 1;
ret = iwm_send_cmd(sc, &hcmd);
if (!ret)
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"Scan request was sent successfully\n");
free(req, M_DEVBUF);
return ret;
}
int
iwm_mvm_lmac_scan(struct iwm_softc *sc)
{
struct iwm_host_cmd hcmd = {
.id = IWM_SCAN_OFFLOAD_REQUEST_CMD,
.len = { 0, },
.data = { NULL, },
.flags = IWM_CMD_SYNC,
};
struct iwm_scan_req_lmac *req;
size_t req_len;
int ret;
int ssid_len = 0;
const uint8_t *ssid = NULL;
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"Handling ieee80211 scan request\n");
memset(cmd, 0, sc->sc_scan_cmd_len);
cmd->quiet_time = htole16(IWM_ACTIVE_QUIET_TIME);
cmd->quiet_plcp_th = htole16(IWM_PLCP_QUIET_THRESH);
cmd->rxchain_sel_flags = iwm_mvm_scan_rx_chain(sc);
cmd->max_out_time = iwm_mvm_scan_max_out_time(sc, 0, is_assoc);
cmd->suspend_time = iwm_mvm_scan_suspend_time(sc, is_assoc);
cmd->rxon_flags = iwm_mvm_scan_rxon_flags(sc, flags);
cmd->filter_flags = htole32(IWM_MAC_FILTER_ACCEPT_GRP |
IWM_MAC_FILTER_IN_BEACON);
req_len = sizeof(struct iwm_scan_req_lmac) +
(sizeof(struct iwm_scan_channel_cfg_lmac) *
sc->sc_capa_n_scan_channels) + sizeof(struct iwm_scan_probe_req);
if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE)
return ENOMEM;
req = malloc(req_len, M_DEVBUF, M_NOWAIT | M_ZERO);
if (req == NULL)
return ENOMEM;
cmd->type = htole32(IWM_SCAN_TYPE_FORCED);
cmd->repeats = htole32(1);
hcmd.len[0] = (uint16_t)req_len;
hcmd.data[0] = (void *)req;
/*
* If the user asked for passive scan, don't change to active scan if
* you see any activity on the channel - remain passive.
*/
if (n_ssids > 0) {
cmd->passive2active = htole16(1);
cmd->scan_flags |= IWM_SCAN_FLAGS_PASSIVE2ACTIVE;
#if 0
if (basic_ssid) {
ssid = req->ssids[0].ssid;
ssid_len = req->ssids[0].ssid_len;
}
#endif
} else {
cmd->passive2active = 0;
cmd->scan_flags &= ~IWM_SCAN_FLAGS_PASSIVE2ACTIVE;
/* These timings correspond to iwlwifi's UNASSOC scan. */
req->active_dwell = 10;
req->passive_dwell = 110;
req->fragmented_dwell = 44;
req->extended_dwell = 90;
req->max_out_time = 0;
req->suspend_time = 0;
req->scan_prio = htole32(IWM_SCAN_PRIORITY_HIGH);
req->rx_chain_select = iwm_mvm_scan_rx_chain(sc);
req->iter_num = htole32(1);
req->delay = 0;
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 (ssid_len == 0)
req->scan_flags |= htole32(IWM_MVM_LMAC_SCAN_FLAG_PASSIVE);
else
req->scan_flags |=
htole32(IWM_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION);
if (isset(sc->sc_enabled_capa,
IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT))
req->scan_flags |= htole32(IWM_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED);
req->flags = htole32(IWM_PHY_BAND_24);
if (sc->sc_nvm.sku_cap_band_52GHz_enable)
req->flags |= htole32(IWM_PHY_BAND_5);
req->filter_flags =
htole32(IWM_MAC_FILTER_ACCEPT_GRP | IWM_MAC_FILTER_IN_BEACON);
/* Tx flags 2 GHz. */
req->tx_cmd[0].tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |
IWM_TX_CMD_FLG_BT_DIS);
req->tx_cmd[0].rate_n_flags =
iwm_mvm_scan_rate_n_flags(sc, IEEE80211_CHAN_2GHZ, 1/*XXX*/);
req->tx_cmd[0].sta_id = sc->sc_aux_sta.sta_id;
/* Tx flags 5 GHz. */
req->tx_cmd[1].tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |
IWM_TX_CMD_FLG_BT_DIS);
req->tx_cmd[1].rate_n_flags =
iwm_mvm_scan_rate_n_flags(sc, IEEE80211_CHAN_5GHZ, 1/*XXX*/);
req->tx_cmd[1].sta_id = sc->sc_aux_sta.sta_id;
/* Check if we're doing an active directed scan. */
if (ssid_len != 0) {
req->direct_scan[0].id = IEEE80211_ELEMID_SSID;
req->direct_scan[0].len = ssid_len;
memcpy(req->direct_scan[0].ssid, ssid, ssid_len);
}
cmd->tx_cmd.tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |
IWM_TX_CMD_FLG_BT_DIS);
cmd->tx_cmd.sta_id = sc->sc_aux_sta.sta_id;
cmd->tx_cmd.life_time = htole32(IWM_TX_CMD_LIFE_TIME_INFINITE);
cmd->tx_cmd.rate_n_flags = iwm_mvm_scan_rate_n_flags(sc, flags, 1/*XXX*/);
req->n_channels = iwm_mvm_lmac_scan_fill_channels(sc,
(struct iwm_scan_channel_cfg_lmac *)req->data,
ssid_len != 0);
cmd->tx_cmd.len = htole16(iwm_mvm_fill_probe_req(sc,
(struct ieee80211_frame *)cmd->data,
vap ? vap->iv_myaddr : ic->ic_macaddr, n_ssids,
ssid, ssid_len, NULL, 0,
sc->sc_capa_max_probe_len));
ret = iwm_mvm_fill_probe_req(sc,
(struct iwm_scan_probe_req *)(req->data +
(sizeof(struct iwm_scan_channel_cfg_lmac) *
sc->sc_capa_n_scan_channels)));
if (ret) {
free(req, M_DEVBUF);
return ret;
}
cmd->channel_count
= iwm_mvm_scan_fill_channels(sc, cmd, flags, n_ssids, basic_ssid);
/* Specify the scan plan: We'll do one iteration. */
req->schedule[0].iterations = 1;
req->schedule[0].full_scan_mul = 1;
cmd->len = htole16(sizeof(struct iwm_scan_cmd) +
le16toh(cmd->tx_cmd.len) +
(cmd->channel_count * sizeof(struct iwm_scan_channel)));
hcmd.len[0] = le16toh(cmd->len);
/* Disable EBS. */
req->channel_opt[0].non_ebs_ratio = 1;
req->channel_opt[1].non_ebs_ratio = 1;
status = IWM_SCAN_RESPONSE_OK;
ret = iwm_mvm_send_cmd_status(sc, &hcmd, &status);
if (!ret && status == IWM_SCAN_RESPONSE_OK) {
ret = iwm_send_cmd(sc, &hcmd);
if (!ret) {
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"Scan request was sent successfully\n");
} else {
/*
* If the scan failed, it usually means that the FW was unable
* to allocate the time events. Warn on it, but maybe we
* should try to send the command again with different params.
*/
ret = EIO;
}
free(req, M_DEVBUF);
return ret;
}

View File

@ -106,8 +106,8 @@
#ifndef __IF_IWN_SCAN_H__
#define __IF_IWN_SCAN_H__
extern int
iwm_mvm_scan_request(struct iwm_softc *sc, int flags,
int n_ssids, uint8_t *ssid, int ssid_len);
extern int iwm_mvm_lmac_scan(struct iwm_softc *sc);
extern int iwm_mvm_config_umac_scan(struct iwm_softc *);
extern int iwm_mvm_umac_scan(struct iwm_softc *);
#endif /* __IF_IWN_SCAN_H__ */

View File

@ -257,8 +257,7 @@ iwm_mvm_protect_session(struct iwm_softc *sc, struct iwm_node *in,
htole32(IWM_FW_CMD_ID_AND_COLOR(IWM_DEFAULT_MACID, IWM_DEFAULT_COLOR));
time_cmd.id = htole32(IWM_TE_BSS_STA_AGGRESSIVE_ASSOC);
time_cmd.apply_time = htole32(iwm_read_prph(sc,
IWM_DEVICE_SYSTEM_TIME_REG));
time_cmd.apply_time = htole32(0);
time_cmd.max_frags = IWM_TE_V2_FRAG_NONE;
time_cmd.max_delay = htole32(max_delay);
@ -268,7 +267,8 @@ iwm_mvm_protect_session(struct iwm_softc *sc, struct iwm_node *in,
time_cmd.repeat = 1;
time_cmd.policy
= htole32(IWM_TE_V2_NOTIF_HOST_EVENT_START |
IWM_TE_V2_NOTIF_HOST_EVENT_END);
IWM_TE_V2_NOTIF_HOST_EVENT_END |
IWM_T2_V2_START_IMMEDIATELY);
iwm_mvm_time_event_send_add(sc, in, /*te_data*/NULL, &time_cmd);
}

View File

@ -169,7 +169,7 @@ iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
{
struct iwm_tx_ring *ring = &sc->txq[IWM_MVM_CMD_QUEUE];
struct iwm_tfd *desc;
struct iwm_tx_data *data;
struct iwm_tx_data *txdata = NULL;
struct iwm_device_cmd *cmd;
struct mbuf *m;
bus_dma_segment_t seg;
@ -178,11 +178,15 @@ iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
int error = 0, i, paylen, off;
int code;
int async, wantresp;
int group_id;
int nsegs;
size_t hdrlen, datasz;
uint8_t *data;
code = hcmd->id;
async = hcmd->flags & IWM_CMD_ASYNC;
wantresp = hcmd->flags & IWM_CMD_WANT_SKB;
data = NULL;
for (i = 0, paylen = 0; i < nitems(hcmd->len); i++) {
paylen += hcmd->len[i];
@ -207,17 +211,27 @@ iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
}
desc = &ring->desc[ring->cur];
data = &ring->data[ring->cur];
txdata = &ring->data[ring->cur];
if (paylen > sizeof(cmd->data)) {
group_id = iwm_cmd_groupid(code);
if (group_id != 0) {
hdrlen = sizeof(cmd->hdr_wide);
datasz = sizeof(cmd->data_wide);
} else {
hdrlen = sizeof(cmd->hdr);
datasz = sizeof(cmd->data);
}
if (paylen > datasz) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"large command paylen=%u len0=%u\n",
paylen, hcmd->len[0]);
/* Command is too large */
size_t totlen = hdrlen + paylen;
if (paylen > IWM_MAX_CMD_PAYLOAD_SIZE) {
device_printf(sc->sc_dev,
"firmware command too long (%zd bytes)\n",
paylen + sizeof(cmd->hdr));
totlen);
error = EINVAL;
goto out;
}
@ -229,30 +243,41 @@ iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
error = bus_dmamap_load_mbuf_sg(ring->data_dmat,
data->map, m, &seg, &nsegs, BUS_DMA_NOWAIT);
txdata->map, m, &seg, &nsegs, BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(sc->sc_dev,
"%s: can't map mbuf, error %d\n", __func__, error);
m_freem(m);
goto out;
}
data->m = m; /* mbuf will be freed in iwm_cmd_done() */
txdata->m = m; /* mbuf will be freed in iwm_cmd_done() */
cmd = mtod(m, struct iwm_device_cmd *);
paddr = seg.ds_addr;
} else {
cmd = &ring->cmd[ring->cur];
paddr = data->cmd_paddr;
paddr = txdata->cmd_paddr;
}
cmd->hdr.code = code;
cmd->hdr.flags = 0;
cmd->hdr.qid = ring->qid;
cmd->hdr.idx = ring->cur;
if (group_id != 0) {
cmd->hdr_wide.opcode = iwm_cmd_opcode(code);
cmd->hdr_wide.group_id = group_id;
cmd->hdr_wide.qid = ring->qid;
cmd->hdr_wide.idx = ring->cur;
cmd->hdr_wide.length = htole16(paylen);
cmd->hdr_wide.version = iwm_cmd_version(code);
data = cmd->data_wide;
} else {
cmd->hdr.code = iwm_cmd_opcode(code);
cmd->hdr.flags = 0;
cmd->hdr.qid = ring->qid;
cmd->hdr.idx = ring->cur;
data = cmd->data;
}
for (i = 0, off = 0; i < nitems(hcmd->data); i++) {
if (hcmd->len[i] == 0)
continue;
memcpy(cmd->data + off, hcmd->data[i], hcmd->len[i]);
memcpy(data + off, hcmd->data[i], hcmd->len[i]);
off += hcmd->len[i];
}
KASSERT(off == paylen, ("off %d != paylen %d", off, paylen));
@ -261,18 +286,17 @@ iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
addr_lo = htole32((uint32_t)paddr);
memcpy(&desc->tbs[0].lo, &addr_lo, sizeof(uint32_t));
desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(paddr)
| ((sizeof(cmd->hdr) + paylen) << 4));
| ((hdrlen + paylen) << 4));
desc->num_tbs = 1;
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"%s: iwm_send_cmd 0x%x size=%lu %s\n",
__func__,
"iwm_send_cmd 0x%x size=%lu %s\n",
code,
(unsigned long) (hcmd->len[0] + hcmd->len[1] + sizeof(cmd->hdr)),
(unsigned long) (hcmd->len[0] + hcmd->len[1] + hdrlen),
async ? " (async)" : "");
if (paylen > sizeof(cmd->data)) {
bus_dmamap_sync(ring->data_dmat, data->map,
if (paylen > datasz) {
bus_dmamap_sync(ring->data_dmat, txdata->map,
BUS_DMASYNC_PREWRITE);
} else {
bus_dmamap_sync(ring->cmd_dma.tag, ring->cmd_dma.map,
@ -404,3 +428,31 @@ iwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
sc->sc_wantresp = -1;
wakeup(&sc->sc_wantresp);
}
uint8_t
iwm_fw_valid_tx_ant(struct iwm_softc *sc)
{
uint8_t tx_ant;
tx_ant = ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_TX_CHAIN)
>> IWM_FW_PHY_CFG_TX_CHAIN_POS);
if (sc->sc_nvm.valid_tx_ant)
tx_ant &= sc->sc_nvm.valid_tx_ant;
return tx_ant;
}
uint8_t
iwm_fw_valid_rx_ant(struct iwm_softc *sc)
{
uint8_t rx_ant;
rx_ant = ((sc->sc_fw_phy_config & IWM_FW_PHY_CFG_RX_CHAIN)
>> IWM_FW_PHY_CFG_RX_CHAIN_POS);
if (sc->sc_nvm.valid_rx_ant)
rx_ant &= sc->sc_nvm.valid_rx_ant;
return rx_ant;
}

View File

@ -116,4 +116,7 @@ extern int iwm_mvm_send_cmd_pdu_status(struct iwm_softc *sc, uint8_t id,
uint16_t len, const void *data, uint32_t *status);
extern void iwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd);
extern uint8_t iwm_fw_valid_tx_ant(struct iwm_softc *sc);
extern uint8_t iwm_fw_valid_rx_ant(struct iwm_softc *sc);
#endif /* __IF_IWM_UTIL_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -137,8 +137,9 @@ struct iwm_tx_radiotap_header {
(1 << IEEE80211_RADIOTAP_CHANNEL))
#define IWM_UCODE_SECT_MAX 6
#define IWM_UCODE_SECT_MAX 16
#define IWM_FWDMASEGSZ (192*1024)
#define IWM_FWDMASEGSZ_8000 (320*1024)
/* sanity check value */
#define IWM_FWMAXSIZE (2*1024*1024)
@ -152,9 +153,10 @@ struct iwm_tx_radiotap_header {
#define IWM_FW_STATUS_DONE 2
enum iwm_ucode_type {
IWM_UCODE_TYPE_INIT,
IWM_UCODE_TYPE_REGULAR,
IWM_UCODE_TYPE_INIT,
IWM_UCODE_TYPE_WOW,
IWM_UCODE_TYPE_REGULAR_USNIFFER,
IWM_UCODE_TYPE_MAX
};
@ -197,8 +199,9 @@ struct iwm_nvm_data {
uint8_t radio_cfg_pnum;
uint8_t valid_tx_ant, valid_rx_ant;
#define IWM_NUM_CHANNELS 39
#define IWM_NUM_CHANNELS_8000 51
uint16_t nvm_ch_flags[IWM_NUM_CHANNELS];
uint16_t nvm_ch_flags[IWM_NUM_CHANNELS_8000];
uint16_t nvm_version;
uint8_t max_tx_pwr_half_dbm;
@ -216,9 +219,9 @@ struct iwm_host_cmd {
int handler_status;
uint32_t flags;
uint32_t id;
uint16_t len[IWM_MAX_CMD_TBS_PER_TFD];
uint8_t dataflags[IWM_MAX_CMD_TBS_PER_TFD];
uint8_t id;
};
/*
@ -269,13 +272,6 @@ struct iwm_tx_ring {
#define IWM_MAX_SCATTER 20
struct iwm_softc;
struct iwm_rbuf {
struct iwm_softc *sc;
void *vaddr;
bus_addr_t paddr;
};
struct iwm_rx_data {
struct mbuf *m;
bus_dmamap_t map;
@ -296,6 +292,7 @@ struct iwm_rx_ring {
struct iwm_ucode_status {
uint32_t uc_error_event_table;
uint32_t uc_umac_error_event_table;
uint32_t uc_log_event_table;
int uc_ok;
@ -304,7 +301,9 @@ struct iwm_ucode_status {
#define IWM_CMD_RESP_MAX PAGE_SIZE
#define IWM_OTP_LOW_IMAGE_SIZE 2048
/* lower blocks contain EEPROM image and calibration data */
#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000 16384
#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_8000 32768
#define IWM_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS 500
#define IWM_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS 400
@ -329,7 +328,7 @@ enum iwm_hcmd_dataflag {
* iwlwifi/iwl-phy-db
*/
#define IWM_NUM_PAPD_CH_GROUPS 4
#define IWM_NUM_PAPD_CH_GROUPS 9
#define IWM_NUM_TXP_CH_GROUPS 9
struct iwm_phy_db_entry {
@ -386,6 +385,7 @@ struct iwm_node {
#define IWM_NODE(_ni) ((struct iwm_node *)(_ni))
#define IWM_STATION_ID 0
#define IWM_AUX_STA_ID 1
#define IWM_DEFAULT_MACID 0
#define IWM_DEFAULT_COLOR 0
@ -409,7 +409,7 @@ struct iwm_softc {
#define IWM_FLAG_STOPPED (1 << 2)
#define IWM_FLAG_RFKILL (1 << 3)
#define IWM_FLAG_BUSY (1 << 4)
#define IWM_FLAG_DORESUME (1 << 5)
#define IWM_FLAG_SCANNING (1 << 5)
struct intr_config_hook sc_preinit_hook;
struct callout sc_watchdog_to;
@ -441,7 +441,14 @@ struct iwm_softc {
int ict_cur;
int sc_hw_rev;
#define IWM_SILICON_A_STEP 0
#define IWM_SILICON_B_STEP 1
#define IWM_SILICON_C_STEP 2
#define IWM_SILICON_D_STEP 3
int sc_hw_id;
int sc_device_family;
#define IWM_DEVICE_FAMILY_7000 1
#define IWM_DEVICE_FAMILY_8000 2
struct iwm_dma_info kw_dma;
struct iwm_dma_info fw_dma;
@ -451,10 +458,14 @@ struct iwm_softc {
struct iwm_ucode_status sc_uc;
enum iwm_ucode_type sc_uc_current;
int sc_fwver;
char sc_fwver[32];
int sc_capaflags;
int sc_capa_max_probe_len;
int sc_capa_n_scan_channels;
uint32_t sc_ucode_api;
uint8_t sc_enabled_capa[howmany(IWM_NUM_UCODE_TLV_CAPA, NBBY)];
char sc_fw_mcc[3];
int sc_intmask;
@ -482,10 +493,7 @@ struct iwm_softc {
int sc_tx_timer;
struct iwm_scan_cmd *sc_scan_cmd;
size_t sc_scan_cmd_len;
int sc_scan_last_antenna;
int sc_scanband;
int sc_fixed_ridx;