summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_iwx.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/if_iwx.c')
-rw-r--r--sys/dev/pci/if_iwx.c177
1 files changed, 132 insertions, 45 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,