Add support for the new ADD_STA command API. Required for -34 firmware.
The significant changes are that the purpose of each STA in the firmware
table is now identified by an 'STA type' flag, and that the Rx block ack
window size is now specified in the command. The layout is backwards
compatible, so we can copy less data into the command's data buffer to
keep our current firmware images happy.
Please update your tree before applying this diff. I just committed
a bunch of fixes to the driver which this diff is built on top of.
ok?
diff ad75f5225873df6d70b1e074b9130e23531b6d7d
0181db2e1507c7a303c9d89a8410f8181993d536
blob - e03955bfd1ac8861d79049fc422828d1f264f777
blob + 73727efa2ad5d72670c6c2129ee76f4e77797652
--- sys/dev/pci/if_iwm.c
+++ sys/dev/pci/if_iwm.c
@@ -328,7 +328,7 @@ int iwm_ampdu_rx_start(struct ieee80211com *, struct i
void iwm_ampdu_rx_stop(struct ieee80211com *, struct ieee80211_node *,
uint8_t);
void iwm_sta_rx_agg(struct iwm_softc *, struct ieee80211_node *, uint8_t,
- uint16_t, int);
+ uint16_t, uint16_t, int);
#ifdef notyet
int iwm_ampdu_tx_start(struct ieee80211com *, struct ieee80211_node *,
uint8_t);
@@ -2575,13 +2575,14 @@ iwm_setup_ht_rates(struct iwm_softc *sc)
void
iwm_sta_rx_agg(struct iwm_softc *sc, struct ieee80211_node *ni, uint8_t tid,
- uint16_t ssn, int start)
+ uint16_t ssn, uint16_t winsize, int start)
{
struct ieee80211com *ic = &sc->sc_ic;
- struct iwm_add_sta_cmd_v7 cmd;
+ struct iwm_add_sta_cmd cmd;
struct iwm_node *in = (void *)ni;
int err, s;
uint32_t status;
+ size_t cmdsize;
if (start && sc->sc_rx_ba_sessions >= IWM_MAX_RX_BA_SESSIONS) {
ieee80211_addba_req_refuse(ic, ni, tid);
@@ -2598,6 +2599,7 @@ iwm_sta_rx_agg(struct iwm_softc *sc, struct ieee80211_
if (start) {
cmd.add_immediate_ba_tid = (uint8_t)tid;
cmd.add_immediate_ba_ssn = ssn;
+ cmd.rx_ba_window = winsize;
} else {
cmd.remove_immediate_ba_tid = (uint8_t)tid;
}
@@ -2605,7 +2607,11 @@ iwm_sta_rx_agg(struct iwm_softc *sc, struct ieee80211_
IWM_STA_MODIFY_REMOVE_BA_TID;
status = IWM_ADD_STA_SUCCESS;
- err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, sizeof(cmd), &cmd,
+ if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))
+ cmdsize = sizeof(cmd);
+ else
+ cmdsize = sizeof(struct iwm_add_sta_cmd_v7);
+ err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, cmdsize, &cmd,
&status);
s = splnet();
@@ -2673,9 +2679,10 @@ iwm_ba_task(void *arg)
}
if (sc->ba_start)
- iwm_sta_rx_agg(sc, ni, sc->ba_tid, sc->ba_ssn, 1);
+ iwm_sta_rx_agg(sc, ni, sc->ba_tid, sc->ba_ssn,
+ sc->ba_winsize, 1);
else
- iwm_sta_rx_agg(sc, ni, sc->ba_tid, 0, 0);
+ iwm_sta_rx_agg(sc, ni, sc->ba_tid, 0, 0, 0);
refcnt_rele_wake(&sc->task_refs);
splx(s);
@@ -2698,6 +2705,7 @@ iwm_ampdu_rx_start(struct ieee80211com *ic, struct iee
sc->ba_start = 1;
sc->ba_tid = tid;
sc->ba_ssn = htole16(ba->ba_winstart);
+ sc->ba_winsize = htole16(ba->ba_winsize);
iwm_add_task(sc, systq, &sc->ba_task);
return EBUSY;
@@ -4703,9 +4711,10 @@ iwm_disable_beacon_filter(struct iwm_softc *sc)
int
iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node *in, int update)
{
- struct iwm_add_sta_cmd_v7 add_sta_cmd;
+ struct iwm_add_sta_cmd add_sta_cmd;
int err;
uint32_t status;
+ size_t cmdsize;
struct ieee80211com *ic = &sc->sc_ic;
if (!update && (sc->sc_flags & IWM_FLAG_STA_ACTIVE))
@@ -4714,6 +4723,8 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));
add_sta_cmd.sta_id = IWM_STATION_ID;
+ if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))
+ add_sta_cmd.station_type = IWM_STA_LINK;
add_sta_cmd.mac_id_n_color
= htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id, in->in_color));
if (!update) {
@@ -4764,7 +4775,11 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
}
status = IWM_ADD_STA_SUCCESS;
- err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, sizeof(add_sta_cmd),
+ if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))
+ cmdsize = sizeof(add_sta_cmd);
+ else
+ cmdsize = sizeof(struct iwm_add_sta_cmd_v7);
+ err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, cmdsize,
&add_sta_cmd, &status);
if (!err && (status & IWM_ADD_STA_STATUS_MASK) != IWM_ADD_STA_SUCCESS)
err = EIO;
@@ -4775,9 +4790,10 @@ iwm_add_sta_cmd(struct iwm_softc *sc, struct iwm_node
int
iwm_add_aux_sta(struct iwm_softc *sc)
{
- struct iwm_add_sta_cmd_v7 cmd;
+ struct iwm_add_sta_cmd cmd;
int err, qid;
uint32_t status;
+ size_t cmdsize;
if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DQA_SUPPORT)) {
qid = IWM_DQA_AUX_QUEUE;
@@ -4792,13 +4808,19 @@ iwm_add_aux_sta(struct iwm_softc *sc)
memset(&cmd, 0, sizeof(cmd));
cmd.sta_id = IWM_AUX_STA_ID;
+ if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))
+ cmd.station_type = IWM_STA_AUX_ACTIVITY;
cmd.mac_id_n_color =
htole32(IWM_FW_CMD_ID_AND_COLOR(IWM_MAC_INDEX_AUX, 0));
cmd.tfd_queue_msk = htole32(1 << qid);
cmd.tid_disable_tx = htole16(0xffff);
status = IWM_ADD_STA_SUCCESS;
- err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, sizeof(cmd), &cmd,
+ if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_STA_TYPE))
+ cmdsize = sizeof(cmd);
+ else
+ cmdsize = sizeof(struct iwm_add_sta_cmd_v7);
+ err = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA, cmdsize, &cmd,
&status);
if (!err && (status & IWM_ADD_STA_STATUS_MASK) != IWM_ADD_STA_SUCCESS)
err = EIO;
blob - c0c739266566b29d9d9d90f4264a4272de92c7e3
blob + 8d0564aa8c5a74ad83853f409edd1845d86cae47
--- sys/dev/pci/if_iwmreg.h
+++ sys/dev/pci/if_iwmreg.h
@@ -3388,6 +3388,7 @@ struct iwm_sf_cfg_cmd {
* @dtim_interval: dtim transmit time in TU
* @dtim_reciprocal: 2^32 / dtim_interval
* @mcast_qid: queue ID for multicast traffic
+ * NOTE: obsolete from VER2 and on
* @beacon_template: beacon template ID
*/
struct iwm_mac_data_ap {
@@ -3399,7 +3400,7 @@ struct iwm_mac_data_ap {
uint32_t dtim_reciprocal;
uint32_t mcast_qid;
uint32_t beacon_template;
-} __packed; /* AP_MAC_DATA_API_S_VER_1 */
+} __packed; /* AP_MAC_DATA_API_S_VER_2 */
/**
* struct iwm_mac_data_ibss - configuration data for IBSS MAC context
@@ -5640,6 +5641,95 @@ struct iwm_add_sta_cmd_v7 {
uint16_t beamform_flags;
uint32_t tfd_queue_msk;
} __packed; /* ADD_STA_CMD_API_S_VER_7 */
+
+/**
+ * struct iwm_add_sta_cmd - Add/modify a station in the fw's sta table.
+ * ( REPLY_ADD_STA = 0x18 )
+ * @add_modify: see &enum iwl_sta_mode
+ * @awake_acs: ACs to transmit data on while station is sleeping (for U-APSD)
+ * @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable
+ * AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field.
+ * @mac_id_n_color: the Mac context this station belongs to,
+ * see &enum iwl_ctxt_id_and_color
+ * @addr: station's MAC address
+ * @reserved2: reserved
+ * @sta_id: index of station in uCode's station table
+ * @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave
+ * alone. 1 - modify, 0 - don't change.
+ * @reserved3: reserved
+ * @station_flags: look at &enum iwl_sta_flags
+ * @station_flags_msk: what of %station_flags have changed,
+ * also &enum iwl_sta_flags
+ * @add_immediate_ba_tid: tid for which to add block-ack support (Rx)
+ * Set %STA_MODIFY_ADD_BA_TID to use this field, and also set
+ * add_immediate_ba_ssn.
+ * @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx)
+ * Set %STA_MODIFY_REMOVE_BA_TID to use this field
+ * @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with
+ * add_immediate_ba_tid.
+ * @sleep_tx_count: number of packets to transmit to station even though it is
+ * asleep. Used to synchronise PS-poll and u-APSD responses while ucode
+ * keeps track of STA sleep state.
+ * @station_type: type of this station. See &enum iwl_sta_type.
+ * @sleep_state_flags: Look at &enum iwl_sta_sleep_flag.
+ * @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP
+ * mac-addr.
+ * @beamform_flags: beam forming controls
+ * @tfd_queue_msk: tfd queues used by this station.
+ * Obselete for new TX API (9 and above).
+ * @rx_ba_window: aggregation window size
+ * @sp_length: the size of the SP in actual number of frames
+ * @uapsd_acs: 4 LS bits are trigger enabled ACs, 4 MS bits are the deliver
+ * enabled ACs.
+ *
+ * The device contains an internal table of per-station information, with info
+ * on security keys, aggregation parameters, and Tx rates for initial Tx
+ * attempt and any retries (set by REPLY_TX_LINK_QUALITY_CMD).
+ *
+ * ADD_STA sets up the table entry for one station, either creating a new
+ * entry, or modifying a pre-existing one.
+ */
+struct iwm_add_sta_cmd {
+ uint8_t add_modify;
+ uint8_t awake_acs;
+ uint16_t tid_disable_tx;
+ uint32_t mac_id_n_color;
+ uint8_t addr[ETHER_ADDR_LEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */
+ uint16_t reserved2;
+ uint8_t sta_id;
+ uint8_t modify_mask;
+ uint16_t reserved3;
+ uint32_t station_flags;
+ uint32_t station_flags_msk;
+ uint8_t add_immediate_ba_tid;
+ uint8_t remove_immediate_ba_tid;
+ uint16_t add_immediate_ba_ssn;
+ uint16_t sleep_tx_count;
+ uint8_t sleep_state_flags;
+ uint8_t station_type;
+ uint16_t assoc_id;
+ uint16_t beamform_flags;
+ uint32_t tfd_queue_msk;
+ uint16_t rx_ba_window;
+ uint8_t sp_length;
+ uint8_t uapsd_acs;
+} __packed; /* ADD_STA_CMD_API_S_VER_10 */
+
+/**
+ * FW station types
+ * ( REPLY_ADD_STA = 0x18 )
+ * @IWM_STA_LINK: Link station - normal RX and TX traffic.
+ * @IWM_STA_GENERAL_PURPOSE: General purpose. In AP mode used for beacons
+ * and probe responses.
+ * @IWM_STA_MULTICAST: multicast traffic,
+ * @IWM_STA_TDLS_LINK: TDLS link station
+ * @IWM_STA_AUX_ACTIVITY: auxilary station (scan, ROC and so on).
+ */
+#define IWM_STA_LINK 0
+#define IWM_STA_GENERAL_PURPOSE 1
+#define IWM_STA_MULTICAST 2
+#define IWM_STA_TDLS_LINK 3
+#define IWM_STA_AUX_ACTIVITY 4
/**
* struct iwm_add_sta_key_cmd - add/modify sta key
blob - 57e75479f83795472d80bdb2915dc923fa6b13a9
blob + 6bbd65fb8a57e7942687729c44a9fd748c920cdb
--- sys/dev/pci/if_iwmvar.h
+++ sys/dev/pci/if_iwmvar.h
@@ -381,6 +381,7 @@ struct iwm_softc {
int ba_start;
int ba_tid;
uint16_t ba_ssn;
+ uint16_t ba_winsize;
/* Task for HT protection updates. */
struct task htprot_task;