-/* $OpenBSD: if_iwx.c,v 1.161 2023/03/06 11:03:29 stsp Exp $ */
+/* $OpenBSD: if_iwx.c,v 1.162 2023/03/06 11:08:56 stsp Exp $ */
/*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
#define IWX_MAX_RX_BA_SESSIONS 16
-void
-iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid,
- uint16_t ssn, uint16_t winsize, int timeout_val, int start)
+struct iwx_rxba_data *
+iwx_find_rxba_data(struct iwx_softc *sc, uint8_t tid)
+{
+ int i;
+
+ for (i = 0; i < nitems(sc->sc_rxba_data); i++) {
+ if (sc->sc_rxba_data[i].baid ==
+ IWX_RX_REORDER_DATA_INVALID_BAID)
+ continue;
+ if (sc->sc_rxba_data[i].tid == tid)
+ return &sc->sc_rxba_data[i];
+ }
+
+ return NULL;
+}
+
+int
+iwx_sta_rx_agg_baid_cfg_cmd(struct iwx_softc *sc, struct ieee80211_node *ni,
+ uint8_t tid, uint16_t ssn, uint16_t winsize, int timeout_val, int start,
+ uint8_t *baid)
+{
+ struct iwx_rx_baid_cfg_cmd cmd;
+ uint32_t new_baid = 0;
+ int err;
+
+ splassert(IPL_NET);
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ if (start) {
+ cmd.action = IWX_RX_BAID_ACTION_ADD;
+ cmd.alloc.sta_id_mask = htole32(1 << IWX_STATION_ID);
+ cmd.alloc.tid = tid;
+ cmd.alloc.ssn = htole16(ssn);
+ cmd.alloc.win_size = htole16(winsize);
+ } else {
+ struct iwx_rxba_data *rxba;
+
+ rxba = iwx_find_rxba_data(sc, tid);
+ if (rxba == NULL)
+ return ENOENT;
+ *baid = rxba->baid;
+
+ cmd.action = IWX_RX_BAID_ACTION_REMOVE;
+ if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
+ IWX_RX_BAID_ALLOCATION_CONFIG_CMD) == 1) {
+ cmd.remove_v1.baid = rxba->baid;
+ } else {
+ cmd.remove.sta_id_mask = htole32(1 << IWX_STATION_ID);
+ cmd.remove.tid = tid;
+ }
+ }
+
+ err = iwx_send_cmd_pdu_status(sc, IWX_WIDE_ID(IWX_DATA_PATH_GROUP,
+ IWX_RX_BAID_ALLOCATION_CONFIG_CMD), sizeof(cmd), &cmd, &new_baid);
+ if (err)
+ return err;
+
+ if (start) {
+ if (new_baid >= nitems(sc->sc_rxba_data))
+ return ERANGE;
+ *baid = new_baid;
+ }
+
+ return 0;
+}
+
+int
+iwx_sta_rx_agg_sta_cmd(struct iwx_softc *sc, struct ieee80211_node *ni,
+ uint8_t tid, uint16_t ssn, uint16_t winsize, int timeout_val, int start,
+ uint8_t *baid)
{
- struct ieee80211com *ic = &sc->sc_ic;
struct iwx_add_sta_cmd cmd;
struct iwx_node *in = (void *)ni;
- int err, s;
+ int err;
uint32_t status;
- struct iwx_rxba_data *rxba = NULL;
- uint8_t baid = 0;
-
- s = splnet();
- if (start && sc->sc_rx_ba_sessions >= IWX_MAX_RX_BA_SESSIONS) {
- ieee80211_addba_req_refuse(ic, ni, tid);
- splx(s);
- return;
- }
+ splassert(IPL_NET);
memset(&cmd, 0, sizeof(cmd));
cmd.add_immediate_ba_ssn = htole16(ssn);
cmd.rx_ba_window = htole16(winsize);
} else {
+ struct iwx_rxba_data *rxba;
+
+ rxba = iwx_find_rxba_data(sc, tid);
+ if (rxba == NULL)
+ return ENOENT;
+ *baid = rxba->baid;
+
cmd.remove_immediate_ba_tid = (uint8_t)tid;
}
cmd.modify_mask = start ? IWX_STA_MODIFY_ADD_BA_TID :
status = IWX_ADD_STA_SUCCESS;
err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA, sizeof(cmd), &cmd,
&status);
+ if (err)
+ return err;
- if (err || (status & IWX_ADD_STA_STATUS_MASK) != IWX_ADD_STA_SUCCESS) {
- if (start)
- ieee80211_addba_req_refuse(ic, ni, tid);
+ if ((status & IWX_ADD_STA_STATUS_MASK) != IWX_ADD_STA_SUCCESS)
+ return EIO;
+
+ if (!(status & IWX_ADD_STA_BAID_VALID_MASK))
+ return EINVAL;
+
+ if (start) {
+ *baid = (status & IWX_ADD_STA_BAID_MASK) >>
+ IWX_ADD_STA_BAID_SHIFT;
+ if (*baid == IWX_RX_REORDER_DATA_INVALID_BAID ||
+ *baid >= nitems(sc->sc_rxba_data))
+ return ERANGE;
+ }
+
+ return 0;
+}
+
+void
+iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid,
+ uint16_t ssn, uint16_t winsize, int timeout_val, int start)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ int err, s;
+ struct iwx_rxba_data *rxba = NULL;
+ uint8_t baid = 0;
+
+ s = splnet();
+
+ if (start && sc->sc_rx_ba_sessions >= IWX_MAX_RX_BA_SESSIONS) {
+ ieee80211_addba_req_refuse(ic, ni, tid);
splx(s);
return;
}
+ if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_BAID_ML_SUPPORT)) {
+ err = iwx_sta_rx_agg_baid_cfg_cmd(sc, ni, tid, ssn, winsize,
+ timeout_val, start, &baid);
+ } else {
+ err = iwx_sta_rx_agg_sta_cmd(sc, ni, tid, ssn, winsize,
+ timeout_val, start, &baid);
+ }
+ if (err) {
+ ieee80211_addba_req_refuse(ic, ni, tid);
+ splx(s);
+ return;
+ }
+
+ rxba = &sc->sc_rxba_data[baid];
+
/* Deaggregation is done in hardware. */
if (start) {
- if (!(status & IWX_ADD_STA_BAID_VALID_MASK)) {
- ieee80211_addba_req_refuse(ic, ni, tid);
- splx(s);
- return;
- }
- baid = (status & IWX_ADD_STA_BAID_MASK) >>
- IWX_ADD_STA_BAID_SHIFT;
- if (baid == IWX_RX_REORDER_DATA_INVALID_BAID ||
- baid >= nitems(sc->sc_rxba_data)) {
- ieee80211_addba_req_refuse(ic, ni, tid);
- splx(s);
- return;
- }
- rxba = &sc->sc_rxba_data[baid];
if (rxba->baid != IWX_RX_REORDER_DATA_INVALID_BAID) {
ieee80211_addba_req_refuse(ic, ni, tid);
splx(s);
ba = &ni->ni_rx_ba[tid];
ba->ba_timeout_val = 0;
}
- } else {
- int i;
- for (i = 0; i < nitems(sc->sc_rxba_data); i++) {
- rxba = &sc->sc_rxba_data[i];
- if (rxba->baid ==
- IWX_RX_REORDER_DATA_INVALID_BAID)
- continue;
- if (rxba->tid != tid)
- continue;
- iwx_clear_reorder_buffer(sc, rxba);
- break;
- }
- }
+ } else
+ iwx_clear_reorder_buffer(sc, rxba);
if (start) {
sc->sc_rx_ba_sessions++;
break;
}
+ case IWX_WIDE_ID(IWX_DATA_PATH_GROUP,
+ IWX_RX_BAID_ALLOCATION_CONFIG_CMD):
case IWX_WIDE_ID(IWX_MAC_CONF_GROUP,
IWX_SESSION_PROTECTION_CMD):
case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,
-/* $OpenBSD: if_iwxreg.h,v 1.49 2023/03/06 11:03:29 stsp Exp $ */
+/* $OpenBSD: if_iwxreg.h,v 1.50 2023/03/06 11:08:56 stsp Exp $ */
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
#define IWX_UCODE_TLV_CAPA_PROTECTED_TWT 56
#define IWX_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE 57
#define IWX_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN 58
+#define IWX_UCODE_TLV_CAPA_BAID_ML_SUPPORT 63
#define IWX_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE 64
#define IWX_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS 65
#define IWX_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT 67
#define IWX_DQA_ENABLE_CMD 0x00
#define IWX_RLC_CONFIG_CMD 0x08
#define IWX_TLC_MNG_CONFIG_CMD 0x0f
+#define IWX_RX_BAID_ALLOCATION_CONFIG_CMD 0x16
#define IWX_RX_NO_DATA_NOTIF 0xf5
#define IWX_TLC_MNG_UPDATE_NOTIF 0xf7
uint8_t reserved[3];
} __packed; /* RLC_CONFIG_CMD_API_S_VER_2 */
+#define IWX_MAX_BAID_OLD 16 /* MAX_IMMEDIATE_BA_API_D_VER_2 */
+#define IWX_MAX_BAID 32 /* MAX_IMMEDIATE_BA_API_D_VER_3 */
+
+/**
+ * BAID allocation/config action
+ * @IWX_RX_BAID_ACTION_ADD: add a new BAID session
+ * @IWX_RX_BAID_ACTION_MODIFY: modify the BAID session
+ * @IWX_RX_BAID_ACTION_REMOVE: remove the BAID session
+ */
+#define IWX_RX_BAID_ACTION_ADD 0
+#define IWX_RX_BAID_ACTION_MODIFY 1
+#define IWX_RX_BAID_ACTION_REMOVE 2
+/* RX_BAID_ALLOCATION_ACTION_E_VER_1 */
+
+/**
+ * struct iwx_rx_baid_cfg_cmd_alloc - BAID allocation data
+ * @sta_id_mask: station ID mask
+ * @tid: the TID for this session
+ * @reserved: reserved
+ * @ssn: the starting sequence number
+ * @win_size: RX BA session window size
+ */
+struct iwx_rx_baid_cfg_cmd_alloc {
+ uint32_t sta_id_mask;
+ uint8_t tid;
+ uint8_t reserved[3];
+ uint16_t ssn;
+ uint16_t win_size;
+} __packed; /* RX_BAID_ALLOCATION_ADD_CMD_API_S_VER_1 */
+
+/**
+ * struct iwx_rx_baid_cfg_cmd_modify - BAID modification data
+ * @old_sta_id_mask: old station ID mask
+ * @new_sta_id_mask: new station ID mask
+ * @tid: TID of the BAID
+ */
+struct iwx_rx_baid_cfg_cmd_modify {
+ uint32_t old_sta_id_mask;
+ uint32_t new_sta_id_mask;
+ uint32_t tid;
+} __packed; /* RX_BAID_ALLOCATION_MODIFY_CMD_API_S_VER_2 */
+
+/**
+ * struct iwx_rx_baid_cfg_cmd_remove_v1 - BAID removal data
+ * @baid: the BAID to remove
+ */
+struct iwx_rx_baid_cfg_cmd_remove_v1 {
+ uint32_t baid;
+} __packed; /* RX_BAID_ALLOCATION_REMOVE_CMD_API_S_VER_1 */
+
+/**
+ * struct iwx_rx_baid_cfg_cmd_remove - BAID removal data
+ * @sta_id_mask: the station mask of the BAID to remove
+ * @tid: the TID of the BAID to remove
+ */
+struct iwx_rx_baid_cfg_cmd_remove {
+ uint32_t sta_id_mask;
+ uint32_t tid;
+} __packed; /* RX_BAID_ALLOCATION_REMOVE_CMD_API_S_VER_2 */
+
+/**
+ * struct iwx_rx_baid_cfg_cmd - BAID allocation/config command
+ * @action: the action, from &enum iwx_rx_baid_action
+ */
+struct iwx_rx_baid_cfg_cmd {
+ uint32_t action;
+ union {
+ struct iwx_rx_baid_cfg_cmd_alloc alloc;
+ struct iwx_rx_baid_cfg_cmd_modify modify;
+ struct iwx_rx_baid_cfg_cmd_remove_v1 remove_v1;
+ struct iwx_rx_baid_cfg_cmd_remove remove;
+ }; /* RX_BAID_ALLOCATION_OPERATION_API_U_VER_2 */
+} __packed; /* RX_BAID_ALLOCATION_CONFIG_CMD_API_S_VER_2 */
+
+/**
+ * struct iwx_rx_baid_cfg_resp - BAID allocation response
+ * @baid: the allocated BAID
+ */
+struct iwx_rx_baid_cfg_resp {
+ uint32_t baid;
+}; /* RX_BAID_ALLOCATION_RESPONSE_API_S_VER_1 */
/**
* Options for TLC config flags