Implement support for the BAR_FRAME_RELEASE iwx(4) firmware notification.
authorstsp <stsp@openbsd.org>
Thu, 29 Jul 2021 12:01:45 +0000 (12:01 +0000)
committerstsp <stsp@openbsd.org>
Thu, 29 Jul 2021 12:01:45 +0000 (12:01 +0000)
New firmware will generate this notification when a block ack request is
received. Older firmware passed the block ack request frame to the driver.

ok kevlo@

sys/dev/pci/if_iwx.c
sys/dev/pci/if_iwxreg.h

index 892577d..af46177 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwx.c,v 1.84 2021/07/29 12:01:04 stsp Exp $        */
+/*     $OpenBSD: if_iwx.c,v 1.85 2021/07/29 12:01:45 stsp Exp $        */
 
 /*
  * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -318,6 +318,8 @@ int iwx_ampdu_rx_start(struct ieee80211com *, struct ieee80211_node *,
 void   iwx_ampdu_rx_stop(struct ieee80211com *, struct ieee80211_node *,
            uint8_t);
 void   iwx_rx_ba_session_expired(void *);
+void   iwx_rx_bar_frame_release(struct iwx_softc *, struct iwx_rx_packet *,
+           struct iwx_rx_data *, struct mbuf_list *);
 void   iwx_reorder_timer_expired(void *);
 void   iwx_sta_rx_agg(struct iwx_softc *, struct ieee80211_node *, uint8_t,
            uint16_t, uint16_t, int, int);
@@ -2866,6 +2868,41 @@ iwx_rx_ba_session_expired(void *arg)
        splx(s);
 }
 
+void
+iwx_rx_bar_frame_release(struct iwx_softc *sc, struct iwx_rx_packet *pkt,
+    struct iwx_rx_data *data, struct mbuf_list *ml)
+{
+       struct ieee80211com *ic = &sc->sc_ic;
+       struct ieee80211_node *ni = ic->ic_bss;
+       struct iwx_bar_frame_release *release = (void *)data;
+       struct iwx_reorder_buffer *buf;
+       struct iwx_rxba_data *rxba;
+       unsigned int baid, nssn, sta_id, tid;
+
+       if (iwx_rx_packet_payload_len(pkt) < sizeof(*release))
+               return;
+
+       baid = (le32toh(release->ba_info) & IWX_BAR_FRAME_RELEASE_BAID_MASK) >>
+           IWX_BAR_FRAME_RELEASE_BAID_SHIFT;
+       if (baid == IWX_RX_REORDER_DATA_INVALID_BAID ||
+           baid >= nitems(sc->sc_rxba_data))
+               return;
+
+       rxba = &sc->sc_rxba_data[baid];
+       if (rxba == NULL || rxba->baid == IWX_RX_REORDER_DATA_INVALID_BAID)
+               return;
+
+       tid = le32toh(release->sta_tid) & IWX_BAR_FRAME_RELEASE_TID_MASK;
+       sta_id = (le32toh(release->sta_tid) &
+           IWX_BAR_FRAME_RELEASE_STA_MASK) >> IWX_BAR_FRAME_RELEASE_STA_SHIFT;
+       if (tid != rxba->tid || rxba->sta_id != IWX_STATION_ID)
+               return;
+
+       nssn = le32toh(release->ba_info) & IWX_BAR_FRAME_RELEASE_NSSN_MASK;
+       buf = &rxba->reorder_buf;
+       iwx_release_frames(sc, ni, rxba, buf, nssn, ml);
+}
+
 void
 iwx_reorder_timer_expired(void *arg)
 {
@@ -8524,6 +8561,10 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml)
                        break;
                }
 
+               case IWX_BAR_FRAME_RELEASE:
+                       iwx_rx_bar_frame_release(sc, pkt, data, ml);
+                       break;
+
                case IWX_TX_CMD:
                        iwx_rx_tx_cmd(sc, pkt, data);
                        break;
index ba0f5a4..bd6a662 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwxreg.h,v 1.28 2021/07/29 12:00:30 stsp Exp $     */
+/*     $OpenBSD: if_iwxreg.h,v 1.29 2021/07/29 12:01:45 stsp Exp $     */
 
 /*-
  * Based on BSD-licensed source modules in the Linux iwlwifi driver,
@@ -1580,6 +1580,8 @@ struct iwx_tx_queue_cfg_rsp {
 
 #define IWX_REPLY_RX_PHY_CMD   0xc0
 #define IWX_REPLY_RX_MPDU_CMD  0xc1
+#define IWX_BAR_FRAME_RELEASE  0xc2
+#define IWX_FRAME_RELEASE      0xc3
 #define IWX_BA_NOTIF           0xc5
 
 /* Location Aware Regulatory */
@@ -3317,6 +3319,43 @@ struct iwx_rx_mpdu_desc {
        struct iwx_rx_mpdu_desc_v1 v1;
 } __packed;
 
+struct iwx_frame_release {
+       uint8_t baid;
+       uint8_t reserved;
+       uint16_t nssn;
+};
+
+/**
+ * enum iwx_bar_frame_release_sta_tid - STA/TID information for BAR release
+ * @IWX_BAR_FRAME_RELEASE_TID_MASK: TID mask
+ * @IWX_BAR_FRAME_RELEASE_STA_MASK: STA mask
+ */
+#define IWX_BAR_FRAME_RELEASE_TID_MASK 0x0000000f
+#define IWX_BAR_FRAME_RELEASE_STA_MASK 0x000001f0
+#define IWX_BAR_FRAME_RELEASE_STA_SHIFT        4
+
+/**
+ * enum iwx_bar_frame_release_ba_info - BA information for BAR release
+ * @IWL_BAR_FRAME_RELEASE_NSSN_MASK: NSSN mask
+ * @IWL_BAR_FRAME_RELEASE_SN_MASK: SN mask (ignored by driver)
+ * @IWL_BAR_FRAME_RELEASE_BAID_MASK: BAID mask
+ */
+#define IWX_BAR_FRAME_RELEASE_NSSN_MASK                0x00000fff
+#define IWX_BAR_FRAME_RELEASE_SN_MASK          0x00fff000
+#define IWX_BAR_FRAME_RELEASE_SN_SHIFT         12
+#define IWX_BAR_FRAME_RELEASE_BAID_MASK                0x3f000000
+#define IWX_BAR_FRAME_RELEASE_BAID_SHIFT       24
+
+/**
+ * struct iwx_bar_frame_release - frame release from BAR info
+ * @sta_tid: STA & TID information, see &enum iwx_bar_frame_release_sta_tid.
+ * @ba_info: BA information, see &enum iwx_bar_frame_release_ba_info.
+ */
+struct iwx_bar_frame_release {
+       uint32_t sta_tid;
+       uint32_t ba_info;
+} __packed; /* RX_BAR_TO_FRAME_RELEASE_API_S_VER_1 */
+
 /**
  * struct iwx_radio_version_notif - information on the radio version
  * ( IWX_RADIO_VERSION_NOTIFICATION = 0x68 )