diff options
-rw-r--r-- | sys/dev/pci/if_iwx.c | 177 | ||||
-rw-r--r-- | sys/dev/pci/if_iwxreg.h | 85 | ||||
-rw-r--r-- | sys/dev/pci/if_iwxvar.h | 3 |
3 files changed, 217 insertions, 48 deletions
diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index f81cbee04f6..43e0c8c8a5b 100644 --- a/sys/dev/pci/if_iwx.c +++ b/sys/dev/pci/if_iwx.c @@ -1,4 +1,4 @@ -/* $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> @@ -3317,25 +3317,84 @@ iwx_reorder_timer_expired(void *arg) #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)); @@ -3349,6 +3408,13 @@ iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid, 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 : @@ -3357,30 +3423,60 @@ iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t 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); @@ -3401,19 +3497,8 @@ iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid, 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++; @@ -9795,6 +9880,8 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml) 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, diff --git a/sys/dev/pci/if_iwxreg.h b/sys/dev/pci/if_iwxreg.h index a81b2868767..6cb4bb54602 100644 --- a/sys/dev/pci/if_iwxreg.h +++ b/sys/dev/pci/if_iwxreg.h @@ -1,4 +1,4 @@ -/* $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, @@ -1387,6 +1387,7 @@ enum msix_ivar_for_cause { #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 @@ -2006,6 +2007,7 @@ struct iwx_tx_queue_cfg_rsp { #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 @@ -5344,6 +5346,87 @@ struct iwx_rlc_config_cmd { 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 diff --git a/sys/dev/pci/if_iwxvar.h b/sys/dev/pci/if_iwxvar.h index 76489aa52eb..fbb252d9f4a 100644 --- a/sys/dev/pci/if_iwxvar.h +++ b/sys/dev/pci/if_iwxvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwxvar.h,v 1.39 2023/03/06 10:48:05 stsp Exp $ */ +/* $OpenBSD: if_iwxvar.h,v 1.40 2023/03/06 11:08:56 stsp Exp $ */ /* * Copyright (c) 2014 genua mbh <info@genua.de> @@ -758,7 +758,6 @@ struct iwx_softc { struct iwx_rx_phy_info sc_last_phy_info; int sc_ampdu_ref; -#define IWX_MAX_BAID 32 struct iwx_rxba_data sc_rxba_data[IWX_MAX_BAID]; uint32_t sc_time_event_uid; |