diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athioctl.h b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athioctl.h index b9d57ba140..da887d9333 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athioctl.h +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_athioctl.h @@ -373,7 +373,7 @@ struct ath_rx_radiotap_header { */ struct ath_radiotap_vendor_hdr wr_v; #endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */ -} __packed; +} __packed __aligned(8); #define ATH_TX_RADIOTAP_PRESENT ( \ (1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwimac.c b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwimac.c index 4e983dff1a..90f1c4c5fb 100644 --- a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwimac.c +++ b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwimac.c @@ -57,7 +57,7 @@ __FBSDID("$FreeBSD: releng/12.0/sys/dev/bwi/bwimac.c 326022 2017-11-20 19:36:21Z #include #include - + #include #include #include diff --git a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwiphy.c b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwiphy.c index 5b40d0ccb8..76d129f66f 100644 --- a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwiphy.c +++ b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwiphy.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD: releng/12.0/sys/dev/bwi/bwiphy.c 326022 2017-11-20 19:36:21Z #include #include #include - + #include #include #include @@ -88,7 +88,6 @@ static void bwi_phy_config_agc(struct bwi_mac *); static void bwi_tbl_write_2(struct bwi_mac *mac, uint16_t, uint16_t); static void bwi_tbl_write_4(struct bwi_mac *mac, uint16_t, uint32_t); - #define SUP_BPHY(num) { .rev = num, .init = bwi_phy_init_11b_rev##num } static const struct { diff --git a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwirf.c b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwirf.c index bffdc5a58e..c088f03361 100644 --- a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwirf.c +++ b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/bwirf.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD: releng/12.0/sys/dev/bwi/bwirf.c 326022 2017-11-20 19:36:21Z #include #include #include - + #include #include #include diff --git a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c index 8e37aa45a3..f0bb3a6316 100644 --- a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c +++ b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD: releng/12.0/sys/dev/bwi/if_bwi.c 337570 2018-08-10 13:06:14Z #include #include #include - + #include #include #include @@ -1734,15 +1734,6 @@ bwi_set_channel(struct ieee80211com *ic) bwi_rf_set_chan(mac, ieee80211_chan2ieee(ic, c), 0); sc->sc_rates = ieee80211_get_ratetable(c); - - /* - * Setup radio tap channel freq and flags - */ - sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq = - htole16(c->ic_freq); - sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags = - htole16(c->ic_flags & 0xffff); - BWI_UNLOCK(sc); } diff --git a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi_pci.c b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi_pci.c index fe81650493..c4cd03dc44 100644 --- a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi_pci.c +++ b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi_pci.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD: releng/12.0/sys/dev/bwi/if_bwi_pci.c 338948 2018-09-26 17:12 #include #include - + #include #include #include @@ -246,7 +246,6 @@ static device_method_t bwi_pci_methods[] = { DEVMETHOD(device_shutdown, bwi_pci_shutdown), DEVMETHOD(device_suspend, bwi_pci_suspend), DEVMETHOD(device_resume, bwi_pci_resume), - { 0,0 } }; static driver_t bwi_driver = { diff --git a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwireg.h b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwireg.h index 203d8e49f8..94621aab5c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwireg.h +++ b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwireg.h @@ -77,7 +77,6 @@ #define BWI_CONF_LO_REQTO_MASK __BITS(6, 4) /* request timeout */ #define BWI_CONF_LO_REQTO 3 - #define BWI_ID_LO 0xff8 #define BWI_ID_LO_BUSREV_MASK __BITS(31, 28) /* Bus revision */ diff --git a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwivar.h b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwivar.h index ce092f51cb..86aec657ac 100644 --- a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwivar.h +++ b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwivar.h @@ -513,7 +513,7 @@ struct bwi_tx_radiotap_hdr { uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -}; +} __packed; #define BWI_RX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_TSFT) | \ @@ -533,7 +533,7 @@ struct bwi_rx_radiotap_hdr { int8_t wr_antsignal; int8_t wr_antnoise; /* TODO: sq */ -}; +} __packed __aligned(8); struct bwi_vap { struct ieee80211vap bv_vap; diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi2100/dev/ipw/if_ipwvar.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi2100/dev/ipw/if_ipwvar.h index 7ac58151c7..e7e6a7d571 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2100/dev/ipw/if_ipwvar.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2100/dev/ipw/if_ipwvar.h @@ -57,11 +57,12 @@ struct ipw_soft_buf { struct ipw_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; uint8_t wr_flags; + uint8_t wr_pad; uint16_t wr_chan_freq; uint16_t wr_chan_flags; int8_t wr_antsignal; int8_t wr_antnoise; -}; +} __packed __aligned(8); #define IPW_RX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ @@ -72,9 +73,10 @@ struct ipw_rx_radiotap_header { struct ipw_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; + uint8_t wt_pad; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -}; +} __packed; #define IPW_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h index beb70a65b8..f6c5873e08 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h @@ -38,7 +38,7 @@ struct iwi_rx_radiotap_header { int8_t wr_antsignal; int8_t wr_antnoise; uint8_t wr_antenna; -}; +} __packed __aligned(8); #define IWI_RX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ @@ -51,9 +51,10 @@ struct iwi_rx_radiotap_header { struct iwi_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; + uint8_t wt_pad; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -}; +} __packed; #define IWI_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpivar.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpivar.h index 1e0bc520c4..d3d2039ec7 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpivar.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpivar.h @@ -26,7 +26,7 @@ struct wpi_rx_radiotap_header { int8_t wr_dbm_antsignal; int8_t wr_dbm_antnoise; uint8_t wr_antenna; -} __packed; +} __packed __aligned(8); #define WPI_RX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_TSFT) | \ diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c index bc30963eff..d4580338bc 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c @@ -128,8 +128,8 @@ static const struct iwn_ident iwn_ident_table[] = { static int iwn_probe(device_t); static int iwn_attach(device_t); -static int iwn4965_attach(struct iwn_softc *, uint16_t); -static int iwn5000_attach(struct iwn_softc *, uint16_t); +static void iwn4965_attach(struct iwn_softc *, uint16_t); +static void iwn5000_attach(struct iwn_softc *, uint16_t); static int iwn_config_specific(struct iwn_softc *, uint16_t); static void iwn_radiotap_attach(struct iwn_softc *); static void iwn_sysctlattach(struct iwn_softc *); @@ -165,6 +165,7 @@ static int iwn_alloc_tx_ring(struct iwn_softc *, struct iwn_tx_ring *, int); static void iwn_reset_tx_ring(struct iwn_softc *, struct iwn_tx_ring *); static void iwn_free_tx_ring(struct iwn_softc *, struct iwn_tx_ring *); +static void iwn_check_tx_ring(struct iwn_softc *, int); static void iwn5000_ict_reset(struct iwn_softc *); static int iwn_read_eeprom(struct iwn_softc *, uint8_t macaddr[IEEE80211_ADDR_LEN]); @@ -195,6 +196,8 @@ static void iwn_calib_timeout(void *); static void iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *); static void iwn_rx_done(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); +static void iwn_agg_tx_complete(struct iwn_softc *, struct iwn_tx_ring *, + int, int, int); static void iwn_rx_compressed_ba(struct iwn_softc *, struct iwn_rx_desc *); static void iwn5000_rx_calib_results(struct iwn_softc *, struct iwn_rx_desc *); @@ -203,10 +206,13 @@ static void iwn4965_tx_done(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); static void iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); +static void iwn_adj_ampdu_ptr(struct iwn_softc *, struct iwn_tx_ring *); static void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *, int, int, uint8_t); -static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, int, int, - void *); +static int iwn_ampdu_check_bitmap(uint64_t, int, int); +static int iwn_ampdu_index_check(struct iwn_softc *, struct iwn_tx_ring *, + uint64_t, int, int); +static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, void *); static void iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *); static void iwn_notif_intr(struct iwn_softc *); static void iwn_wakeup_intr(struct iwn_softc *); @@ -487,14 +493,9 @@ iwn_attach(device_t dev) * Let's set those up first. */ if (sc->hw_type == IWN_HW_REV_TYPE_4965) - error = iwn4965_attach(sc, pci_get_device(dev)); + iwn4965_attach(sc, pci_get_device(dev)); else - error = iwn5000_attach(sc, pci_get_device(dev)); - if (error != 0) { - device_printf(dev, "could not attach device, error %d\n", - error); - goto fail; - } + iwn5000_attach(sc, pci_get_device(dev)); /* * Next, let's setup the various parameters of each NIC. @@ -1220,12 +1221,13 @@ iwn_config_specific(struct iwn_softc *sc, uint16_t pid) return 0; } -static int +static void iwn4965_attach(struct iwn_softc *sc, uint16_t pid) { struct iwn_ops *ops = &sc->ops; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); + ops->load_firmware = iwn4965_load_firmware; ops->read_eeprom = iwn4965_read_eeprom; ops->post_alive = iwn4965_post_alive; @@ -1260,11 +1262,9 @@ iwn4965_attach(struct iwn_softc *sc, uint16_t pid) sc->sc_flags |= IWN_FLAG_BTCOEX; DPRINTF(sc, IWN_DEBUG_TRACE, "%s: end\n",__func__); - - return 0; } -static int +static void iwn5000_attach(struct iwn_softc *sc, uint16_t pid) { struct iwn_ops *ops = &sc->ops; @@ -1299,7 +1299,7 @@ iwn5000_attach(struct iwn_softc *sc, uint16_t pid) sc->reset_noise_gain = IWN5000_PHY_CALIB_RESET_NOISE_GAIN; sc->noise_gain = IWN5000_PHY_CALIB_NOISE_GAIN; - return 0; + DPRINTF(sc, IWN_DEBUG_TRACE, "%s: end\n",__func__); } /* @@ -1353,6 +1353,8 @@ iwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, ivp->iv_newstate = vap->iv_newstate; vap->iv_newstate = iwn_newstate; sc->ivap[IWN_RXON_BSS_CTX] = vap; + vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K; + vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_4; /* 4uS */ ieee80211_ratectl_init(vap); /* Complete setup. */ @@ -2079,6 +2081,8 @@ iwn_reset_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring) ieee80211_free_node(data->ni); data->ni = NULL; } + data->remapped = 0; + data->long_retries = 0; } /* Clear TX descriptors. */ memset(ring->desc, 0, ring->desc_dma.size); @@ -2117,6 +2121,42 @@ iwn_free_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring) } } +static void +iwn_check_tx_ring(struct iwn_softc *sc, int qid) +{ + struct iwn_tx_ring *ring = &sc->txq[qid]; + + KASSERT(ring->queued >= 0, ("%s: ring->queued (%d) for queue %d < 0!", + __func__, ring->queued, qid)); + + if (qid >= sc->firstaggqueue) { + struct iwn_ops *ops = &sc->ops; + struct ieee80211_tx_ampdu *tap = sc->qid2tap[qid]; + + if (ring->queued == 0 && !IEEE80211_AMPDU_RUNNING(tap)) { + uint16_t ssn = tap->txa_start & 0xfff; + uint8_t tid = tap->txa_tid; + int *res = tap->txa_private; + + iwn_nic_lock(sc); + ops->ampdu_tx_stop(sc, qid, tid, ssn); + iwn_nic_unlock(sc); + + sc->qid2tap[qid] = NULL; + free(res, M_DEVBUF); + } + } + + if (ring->queued < IWN_TX_RING_LOMARK) { + sc->qfullmsk &= ~(1 << qid); + + if (ring->queued == 0) + sc->sc_tx_timer = 0; + else + sc->sc_tx_timer = 5; + } +} + static void iwn5000_ict_reset(struct iwn_softc *sc) { @@ -3163,104 +3203,129 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, } +static void +iwn_agg_tx_complete(struct iwn_softc *sc, struct iwn_tx_ring *ring, int tid, + int idx, int success) +{ + struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; + struct iwn_tx_data *data = &ring->data[idx]; + struct iwn_node *wn; + struct mbuf *m; + struct ieee80211_node *ni; + + KASSERT(data->ni != NULL, ("idx %d: no node", idx)); + KASSERT(data->m != NULL, ("idx %d: no mbuf", idx)); + + /* Unmap and free mbuf. */ + bus_dmamap_sync(ring->data_dmat, data->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(ring->data_dmat, data->map); + m = data->m, data->m = NULL; + ni = data->ni, data->ni = NULL; + wn = (void *)ni; + +#if 0 + /* XXX causes significant performance degradation. */ + txs->flags = IEEE80211_RATECTL_STATUS_SHORT_RETRY | + IEEE80211_RATECTL_STATUS_LONG_RETRY; + txs->long_retries = data->long_retries - 1; +#else + txs->flags = IEEE80211_RATECTL_STATUS_SHORT_RETRY; +#endif + txs->short_retries = wn->agg[tid].short_retries; + if (success) + txs->status = IEEE80211_RATECTL_TX_SUCCESS; + else + txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; + + wn->agg[tid].short_retries = 0; + data->long_retries = 0; + + DPRINTF(sc, IWN_DEBUG_AMPDU, "%s: freeing m %p ni %p idx %d qid %d\n", + __func__, m, ni, idx, ring->qid); + ieee80211_ratectl_tx_complete(ni, txs); + ieee80211_tx_complete(ni, m, !success); +} + /* Process an incoming Compressed BlockAck. */ static void iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc) { - struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; - struct iwn_ops *ops = &sc->ops; + struct iwn_tx_ring *ring; + struct iwn_tx_data *data; struct iwn_node *wn; - struct ieee80211_node *ni; struct iwn_compressed_ba *ba = (struct iwn_compressed_ba *)(desc + 1); - struct iwn_tx_ring *txq; - struct iwn_tx_data *txdata; struct ieee80211_tx_ampdu *tap; - struct mbuf *m; uint64_t bitmap; - uint16_t ssn; uint8_t tid; - int i, lastidx, qid, *res, shift; - int tx_ok = 0, tx_err = 0; + int i, qid, shift; + int tx_ok = 0; - DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__); + DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); qid = le16toh(ba->qid); - txq = &sc->txq[ba->qid]; - tap = sc->qid2tap[ba->qid]; + tap = sc->qid2tap[qid]; + ring = &sc->txq[qid]; tid = tap->txa_tid; wn = (void *)tap->txa_ni; - res = NULL; - ssn = 0; - if (!IEEE80211_AMPDU_RUNNING(tap)) { - res = tap->txa_private; - ssn = tap->txa_start & 0xfff; - } - - for (lastidx = le16toh(ba->ssn) & 0xff; txq->read != lastidx;) { - txdata = &txq->data[txq->read]; - - /* Unmap and free mbuf. */ - bus_dmamap_sync(txq->data_dmat, txdata->map, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(txq->data_dmat, txdata->map); - m = txdata->m, txdata->m = NULL; - ni = txdata->ni, txdata->ni = NULL; - - KASSERT(ni != NULL, ("no node")); - KASSERT(m != NULL, ("no mbuf")); - - DPRINTF(sc, IWN_DEBUG_XMIT, "%s: freeing m=%p\n", __func__, m); - ieee80211_tx_complete(ni, m, 1); - - txq->queued--; - txq->read = (txq->read + 1) % IWN_TX_RING_COUNT; - } - - if (txq->queued == 0 && res != NULL) { - iwn_nic_lock(sc); - ops->ampdu_tx_stop(sc, qid, tid, ssn); - iwn_nic_unlock(sc); - sc->qid2tap[qid] = NULL; - free(res, M_DEVBUF); - return; - } + DPRINTF(sc, IWN_DEBUG_AMPDU, "%s: qid %d tid %d seq %04X ssn %04X\n" + "bitmap: ba %016jX wn %016jX, start %d\n", + __func__, qid, tid, le16toh(ba->seq), le16toh(ba->ssn), + (uintmax_t)le64toh(ba->bitmap), (uintmax_t)wn->agg[tid].bitmap, + wn->agg[tid].startidx); if (wn->agg[tid].bitmap == 0) return; shift = wn->agg[tid].startidx - ((le16toh(ba->seq) >> 4) & 0xff); - if (shift < 0) + if (shift <= -64) shift += 0x100; - if (wn->agg[tid].nframes > (64 - shift)) - return; - /* - * Walk the bitmap and calculate how many successful and failed - * attempts are made. + * Walk the bitmap and calculate how many successful attempts + * are made. * * Yes, the rate control code doesn't know these are A-MPDU - * subframes and that it's okay to fail some of these. + * subframes; due to that long_retries stats are not used here. */ - ni = tap->txa_ni; - bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap; - for (i = 0; bitmap; i++) { - txs->flags = 0; /* XXX TODO */ - if ((bitmap & 1) == 0) { - tx_err ++; - txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; - } else { - tx_ok ++; - txs->status = IEEE80211_RATECTL_TX_SUCCESS; + bitmap = le64toh(ba->bitmap); + if (shift >= 0) + bitmap >>= shift; + else + bitmap <<= -shift; + bitmap &= wn->agg[tid].bitmap; + wn->agg[tid].bitmap = 0; + + for (i = wn->agg[tid].startidx; + bitmap; + bitmap >>= 1, i = (i + 1) % IWN_TX_RING_COUNT) { + if ((bitmap & 1) == 0) + continue; + + data = &ring->data[i]; + if (__predict_false(data->m == NULL)) { + /* + * There is no frame; skip this entry. + * + * NB: it is "ok" to have both + * 'tx done' + 'compressed BA' replies for frame + * with STATE_SCD_QUERY status. + */ + DPRINTF(sc, IWN_DEBUG_AMPDU, + "%s: ring %d: no entry %d\n", __func__, qid, i); + continue; } - ieee80211_ratectl_tx_complete(ni, txs); - bitmap >>= 1; + + tx_ok++; + iwn_agg_tx_complete(sc, ring, tid, i, 1); } - DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, - "->%s: end; %d ok; %d err\n",__func__, tx_ok, tx_err); + ring->queued -= tx_ok; + iwn_check_tx_ring(sc, qid); + DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_AMPDU, + "->%s: end; %d ok\n",__func__, tx_ok); } /* @@ -3508,9 +3573,9 @@ iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, stat->rate, le16toh(stat->duration), le32toh(stat->status)); - if (qid >= sc->firstaggqueue) { - iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, - stat->rtsfailcnt, stat->ackfailcnt, &stat->status); + if (qid >= sc->firstaggqueue && stat->nframes != 1) { + iwn_ampdu_tx_done(sc, qid, stat->nframes, stat->rtsfailcnt, + &stat->status); } else { iwn_tx_done(sc, desc, stat->rtsfailcnt, stat->ackfailcnt, le32toh(stat->status) & 0xff); @@ -3538,15 +3603,32 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, iwn5000_reset_sched(sc, qid, desc->idx); #endif - if (qid >= sc->firstaggqueue) { - iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, - stat->rtsfailcnt, stat->ackfailcnt, &stat->status); + if (qid >= sc->firstaggqueue && stat->nframes != 1) { + iwn_ampdu_tx_done(sc, qid, stat->nframes, stat->rtsfailcnt, + &stat->status); } else { iwn_tx_done(sc, desc, stat->rtsfailcnt, stat->ackfailcnt, le16toh(stat->status) & 0xff); } } +static void +iwn_adj_ampdu_ptr(struct iwn_softc *sc, struct iwn_tx_ring *ring) +{ + int i; + + for (i = ring->read; i != ring->cur; i = (i + 1) % IWN_TX_RING_COUNT) { + struct iwn_tx_data *data = &ring->data[i]; + + if (data->m != NULL) + break; + + data->remapped = 0; + } + + ring->read = i; +} + /* * Adapter-independent backend for TX_DONE firmware notifications. */ @@ -3560,7 +3642,18 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int rtsfailcnt, struct mbuf *m; struct ieee80211_node *ni; + if (__predict_false(data->m == NULL && + ring->qid >= sc->firstaggqueue)) { + /* + * There is no frame; skip this entry. + */ + DPRINTF(sc, IWN_DEBUG_AMPDU, "%s: ring %d: no entry %d\n", + __func__, ring->qid, desc->idx); + return; + } + KASSERT(data->ni != NULL, ("no node")); + KASSERT(data->m != NULL, ("no mbuf")); DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); @@ -3570,6 +3663,19 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int rtsfailcnt, m = data->m, data->m = NULL; ni = data->ni, data->ni = NULL; + data->long_retries = 0; + + if (ring->qid >= sc->firstaggqueue) + iwn_adj_ampdu_ptr(sc, ring); + + /* + * XXX f/w may hang (device timeout) when desc->idx - ring->read == 64 + * (aggregation queues only). + */ + + ring->queued--; + iwn_check_tx_ring(sc, ring->qid); + /* * Update rate control statistics for the node. */ @@ -3618,10 +3724,6 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int rtsfailcnt, ieee80211_tx_complete(ni, m, (status & IWN_TX_FAIL) != 0); - sc->sc_tx_timer = 0; - if (--ring->queued < IWN_TX_RING_LOMARK) - sc->qfullmsk &= ~(1 << ring->qid); - DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); } @@ -3658,148 +3760,218 @@ iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc) wakeup(&ring->desc[desc->idx]); } -static void -iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes, - int rtsfailcnt, int ackfailcnt, void *stat) +static int +iwn_ampdu_check_bitmap(uint64_t bitmap, int start, int idx) { - struct iwn_ops *ops = &sc->ops; - struct iwn_tx_ring *ring = &sc->txq[qid]; - struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; - struct iwn_tx_data *data; - struct mbuf *m; - struct iwn_node *wn; - struct ieee80211_node *ni; - struct ieee80211_tx_ampdu *tap; - uint64_t bitmap; - uint32_t *status = stat; - uint16_t *aggstatus = stat; - uint16_t ssn; - uint8_t tid; - int bit, i, lastidx, *res, seqno, shift, start; + int bit, shift; - /* XXX TODO: status is le16 field! Grr */ - - DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); - DPRINTF(sc, IWN_DEBUG_XMIT, "%s: nframes=%d, status=0x%08x\n", - __func__, - nframes, - *status); - - tap = sc->qid2tap[qid]; - tid = tap->txa_tid; - wn = (void *)tap->txa_ni; - ni = tap->txa_ni; - - /* - * XXX TODO: ACK and RTS failures would be nice here! - */ - - /* - * A-MPDU single frame status - if we failed to transmit it - * in A-MPDU, then it may be a permanent failure. - * - * XXX TODO: check what the Linux iwlwifi driver does here; - * there's some permanent and temporary failures that may be - * handled differently. - */ - if (nframes == 1) { - txs->flags = IEEE80211_RATECTL_STATUS_SHORT_RETRY | - IEEE80211_RATECTL_STATUS_LONG_RETRY; - txs->short_retries = rtsfailcnt; - txs->long_retries = ackfailcnt; - if ((*status & 0xff) != 1 && (*status & 0xff) != 2) { -#ifdef NOT_YET - printf("ieee80211_send_bar()\n"); -#endif - /* - * If we completely fail a transmit, make sure a - * notification is pushed up to the rate control - * layer. - */ - /* XXX */ - txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; - } else { - /* - * If nframes=1, then we won't be getting a BA for - * this frame. Ensure that we correctly update the - * rate control code with how many retries were - * needed to send it. - */ - txs->status = IEEE80211_RATECTL_TX_SUCCESS; - } - ieee80211_ratectl_tx_complete(ni, txs); + bit = idx - start; + shift = 0; + if (bit >= 64) { + shift = 0x100 - bit; + bit = 0; + } else if (bit <= -64) + bit = 0x100 + bit; + else if (bit < 0) { + shift = -bit; + bit = 0; } - bitmap = 0; - start = idx; + if (bit - shift >= 64) + return (0); + + return ((bitmap & (1ULL << (bit - shift))) != 0); +} + +/* + * Firmware bug workaround: in case if 'retries' counter + * overflows 'seqno' field will be incremented: + * status|sequence|status|sequence|status|sequence + * 0000 0A48 0001 0A49 0000 0A6A + * 1000 0A48 1000 0A49 1000 0A6A + * 2000 0A48 2000 0A49 2000 0A6A + * ... + * E000 0A48 E000 0A49 E000 0A6A + * F000 0A48 F000 0A49 F000 0A6A + * 0000 0A49 0000 0A49 0000 0A6B + * 1000 0A49 1000 0A49 1000 0A6B + * ... + * D000 0A49 D000 0A49 D000 0A6B + * E000 0A49 E001 0A49 E000 0A6B + * F000 0A49 F001 0A49 F000 0A6B + * 0000 0A4A 0000 0A4B 0000 0A6A + * 1000 0A4A 1000 0A4B 1000 0A6A + * ... + * + * Odd 'seqno' numbers are incremened by 2 every 2 overflows. + * For even 'seqno' % 4 != 0 overflow is cyclic (0 -> +1 -> 0). + * Not checked with nretries >= 64. + * + */ +static int +iwn_ampdu_index_check(struct iwn_softc *sc, struct iwn_tx_ring *ring, + uint64_t bitmap, int start, int idx) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct iwn_tx_data *data; + int diff, min_retries, max_retries, new_idx, loop_end; + + new_idx = idx - IWN_LONG_RETRY_LIMIT_LOG; + if (new_idx < 0) + new_idx += IWN_TX_RING_COUNT; + + /* + * Corner case: check if retry count is not too big; + * reset device otherwise. + */ + if (!iwn_ampdu_check_bitmap(bitmap, start, new_idx)) { + data = &ring->data[new_idx]; + if (data->long_retries > IWN_LONG_RETRY_LIMIT) { + device_printf(sc->sc_dev, + "%s: retry count (%d) for idx %d/%d overflow, " + "resetting...\n", __func__, data->long_retries, + ring->qid, new_idx); + ieee80211_restart_all(ic); + return (-1); + } + } + + /* Correct index if needed. */ + loop_end = idx; + do { + data = &ring->data[new_idx]; + diff = idx - new_idx; + if (diff < 0) + diff += IWN_TX_RING_COUNT; + + min_retries = IWN_LONG_RETRY_FW_OVERFLOW * diff; + if ((new_idx % 2) == 0) + max_retries = IWN_LONG_RETRY_FW_OVERFLOW * (diff + 1); + else + max_retries = IWN_LONG_RETRY_FW_OVERFLOW * (diff + 2); + + if (!iwn_ampdu_check_bitmap(bitmap, start, new_idx) && + ((data->long_retries >= min_retries && + data->long_retries < max_retries) || + (diff == 1 && + (new_idx & 0x03) == 0x02 && + data->long_retries >= IWN_LONG_RETRY_FW_OVERFLOW))) { + DPRINTF(sc, IWN_DEBUG_AMPDU, + "%s: correcting index %d -> %d in queue %d" + " (retries %d)\n", __func__, idx, new_idx, + ring->qid, data->long_retries); + return (new_idx); + } + + new_idx = (new_idx + 1) % IWN_TX_RING_COUNT; + } while (new_idx != loop_end); + + return (idx); +} + +static void +iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int nframes, int rtsfailcnt, + void *stat) +{ + struct iwn_tx_ring *ring = &sc->txq[qid]; + struct ieee80211_tx_ampdu *tap = sc->qid2tap[qid]; + struct iwn_node *wn = (void *)tap->txa_ni; + struct iwn_tx_data *data; + uint64_t bitmap = 0; + uint16_t *aggstatus = stat; + uint8_t tid = tap->txa_tid; + int bit, i, idx, shift, start, tx_err; + + DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); + + start = le16toh(*(aggstatus + nframes * 2)) & 0xff; + for (i = 0; i < nframes; i++) { - if (le16toh(aggstatus[i * 2]) & 0xc) + uint16_t status = le16toh(aggstatus[i * 2]); + + if (status & IWN_AGG_TX_STATE_IGNORE_MASK) continue; - idx = le16toh(aggstatus[2*i + 1]) & 0xff; + idx = le16toh(aggstatus[i * 2 + 1]) & 0xff; + data = &ring->data[idx]; + if (data->remapped) { + idx = iwn_ampdu_index_check(sc, ring, bitmap, start, idx); + if (idx == -1) { + /* skip error (device will be restarted anyway). */ + continue; + } + + /* Index may have changed. */ + data = &ring->data[idx]; + } + + /* + * XXX Sometimes (rarely) some frames are excluded from events. + * XXX Due to that long_retries counter may be wrong. + */ + data->long_retries &= ~0x0f; + data->long_retries += IWN_AGG_TX_TRY_COUNT(status) + 1; + + if (data->long_retries >= IWN_LONG_RETRY_FW_OVERFLOW) { + int diff, wrong_idx; + + diff = data->long_retries / IWN_LONG_RETRY_FW_OVERFLOW; + wrong_idx = (idx + diff) % IWN_TX_RING_COUNT; + + /* + * Mark the entry so the above code will check it + * next time. + */ + ring->data[wrong_idx].remapped = 1; + } + + if (status & IWN_AGG_TX_STATE_UNDERRUN_MSK) { + /* + * NB: count retries but postpone - it was not + * transmitted. + */ + continue; + } + bit = idx - start; shift = 0; if (bit >= 64) { - shift = 0x100 - idx + start; + shift = 0x100 - bit; bit = 0; - start = idx; } else if (bit <= -64) - bit = 0x100 - start + idx; + bit = 0x100 + bit; else if (bit < 0) { - shift = start - idx; - start = idx; + shift = -bit; bit = 0; } bitmap = bitmap << shift; bitmap |= 1ULL << bit; } - tap = sc->qid2tap[qid]; - tid = tap->txa_tid; - wn = (void *)tap->txa_ni; - wn->agg[tid].bitmap = bitmap; wn->agg[tid].startidx = start; - wn->agg[tid].nframes = nframes; + wn->agg[tid].bitmap = bitmap; + wn->agg[tid].short_retries = rtsfailcnt; - res = NULL; - ssn = 0; - if (!IEEE80211_AMPDU_RUNNING(tap)) { - res = tap->txa_private; - ssn = tap->txa_start & 0xfff; + DPRINTF(sc, IWN_DEBUG_AMPDU, "%s: nframes %d start %d bitmap %016jX\n", + __func__, nframes, start, (uintmax_t)bitmap); + + i = ring->read; + + for (tx_err = 0; + i != wn->agg[tid].startidx; + i = (i + 1) % IWN_TX_RING_COUNT) { + data = &ring->data[i]; + data->remapped = 0; + if (data->m == NULL) + continue; + + tx_err++; + iwn_agg_tx_complete(sc, ring, tid, i, 0); } - /* This is going nframes DWORDS into the descriptor? */ - seqno = le32toh(*(status + nframes)) & 0xfff; - for (lastidx = (seqno & 0xff); ring->read != lastidx;) { - data = &ring->data[ring->read]; + ring->read = wn->agg[tid].startidx; + ring->queued -= tx_err; - /* Unmap and free mbuf. */ - bus_dmamap_sync(ring->data_dmat, data->map, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(ring->data_dmat, data->map); - m = data->m, data->m = NULL; - ni = data->ni, data->ni = NULL; - - KASSERT(ni != NULL, ("no node")); - KASSERT(m != NULL, ("no mbuf")); - DPRINTF(sc, IWN_DEBUG_XMIT, "%s: freeing m=%p\n", __func__, m); - ieee80211_tx_complete(ni, m, 1); - - ring->queued--; - ring->read = (ring->read + 1) % IWN_TX_RING_COUNT; - } - - if (ring->queued == 0 && res != NULL) { - iwn_nic_lock(sc); - ops->ampdu_tx_stop(sc, qid, tid, ssn); - iwn_nic_unlock(sc); - sc->qid2tap[qid] = NULL; - free(res, M_DEVBUF); - return; - } - - sc->sc_tx_timer = 0; - if (ring->queued < IWN_TX_RING_LOMARK) - sc->qfullmsk &= ~(1 << ring->qid); + iwn_check_tx_ring(sc, qid); DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); } @@ -3814,6 +3986,7 @@ iwn_notif_intr(struct iwn_softc *sc) struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint16_t hw; + int is_stopped; bus_dmamap_sync(sc->rxq.stat_dma.tag, sc->rxq.stat_dma.map, BUS_DMASYNC_POSTREAD); @@ -3845,6 +4018,11 @@ iwn_notif_intr(struct iwn_softc *sc) case IWN_MPDU_RX_DONE: /* An 802.11 frame has been received. */ iwn_rx_done(sc, desc, data); + + is_stopped = (sc->sc_flags & IWN_FLAG_RUNNING) == 0; + if (__predict_false(is_stopped)) + return; + break; case IWN_RX_COMPRESSED_BA: @@ -3885,6 +4063,11 @@ iwn_notif_intr(struct iwn_softc *sc) IWN_UNLOCK(sc); ieee80211_beacon_miss(ic); IWN_LOCK(sc); + + is_stopped = (sc->sc_flags & + IWN_FLAG_RUNNING) == 0; + if (__predict_false(is_stopped)) + return; } } break; @@ -3951,6 +4134,11 @@ iwn_notif_intr(struct iwn_softc *sc) IWN_UNLOCK(sc); ieee80211_scan_next(vap); IWN_LOCK(sc); + + is_stopped = (sc->sc_flags & IWN_FLAG_RUNNING) == 0; + if (__predict_false(is_stopped)) + return; + break; } case IWN5000_CALIBRATION_RESULT: @@ -4368,7 +4556,7 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) struct ieee80211_frame *wh; struct ieee80211_key *k = NULL; uint32_t flags; - uint16_t seqno, qos; + uint16_t qos; uint8_t tid, type; int ac, totlen, rate; @@ -4410,25 +4598,13 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) */ ac = M_WME_GETAC(m); - seqno = ni->ni_txseqs[tid]; if (m->m_flags & M_AMPDU_MPDU) { struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac]; - if (!IEEE80211_AMPDU_RUNNING(tap)) { + if (!IEEE80211_AMPDU_RUNNING(tap)) return (EINVAL); - } - /* - * Queue this frame to the hardware ring that we've - * negotiated AMPDU TX on. - * - * Note that the sequence number must match the TX slot - * being used! - */ ac = *(int *)tap->txa_private; - *(uint16_t *)wh->i_seq = - htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT); - ni->ni_txseqs[tid]++; } /* Encrypt the frame if need be. */ @@ -4497,15 +4673,42 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) } ring = &sc->txq[ac]; - if ((m->m_flags & M_AMPDU_MPDU) != 0 && - (seqno % 256) != ring->cur) { - device_printf(sc->sc_dev, - "%s: m=%p: seqno (%d) (%d) != ring index (%d) !\n", - __func__, - m, - seqno, - seqno % 256, - ring->cur); + if (m->m_flags & M_AMPDU_MPDU) { + uint16_t seqno = ni->ni_txseqs[tid]; + + if (ring->queued > IWN_TX_RING_COUNT / 2 && + (ring->cur + 1) % IWN_TX_RING_COUNT == ring->read) { + DPRINTF(sc, IWN_DEBUG_AMPDU, "%s: no more space " + "(queued %d) left in %d queue!\n", + __func__, ring->queued, ac); + return (ENOBUFS); + } + + /* + * Queue this frame to the hardware ring that we've + * negotiated AMPDU TX on. + * + * Note that the sequence number must match the TX slot + * being used! + */ + if ((seqno % 256) != ring->cur) { + device_printf(sc->sc_dev, + "%s: m=%p: seqno (%d) (%d) != ring index (%d) !\n", + __func__, + m, + seqno, + seqno % 256, + ring->cur); + + /* XXX until D9195 will not be committed */ + ni->ni_txseqs[tid] &= ~0xff; + ni->ni_txseqs[tid] += ring->cur; + seqno = ni->ni_txseqs[tid]; + } + + *(uint16_t *)wh->i_seq = + htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT); + ni->ni_txseqs[tid]++; } /* Prepare TX firmware command. */ @@ -4667,6 +4870,13 @@ iwn_tx_cmd(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, desc = &ring->desc[ring->cur]; data = &ring->data[ring->cur]; + if (__predict_false(data->m != NULL || data->ni != NULL)) { + device_printf(sc->sc_dev, "%s: ni (%p) or m (%p) for idx %d " + "in queue %d is not NULL!\n", __func__, data->ni, data->m, + ring->cur, ring->qid); + return EIO; + } + /* Prepare TX firmware command. */ cmd = &ring->cmd[ring->cur]; cmd->code = IWN_CMD_TX_DATA; @@ -8895,18 +9105,12 @@ iwn_scan_end(struct ieee80211com *ic) static void iwn_set_channel(struct ieee80211com *ic) { - const struct ieee80211_channel *c = ic->ic_curchan; struct iwn_softc *sc = ic->ic_softc; int error; DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); IWN_LOCK(sc); - sc->sc_rxtap.wr_chan_freq = htole16(c->ic_freq); - sc->sc_rxtap.wr_chan_flags = htole16(c->ic_flags); - sc->sc_txtap.wt_chan_freq = htole16(c->ic_freq); - sc->sc_txtap.wt_chan_flags = htole16(c->ic_flags); - /* * Only need to set the channel in Monitor mode. AP scanning and auth * are already taken care of by their respective firmware commands. diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_debug.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_debug.h index 06ded6afd5..3f269296eb 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_debug.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_debug.h @@ -44,6 +44,7 @@ enum { IWN_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */ IWN_DEBUG_SCAN = 0x00008000, /* Scan related operations */ IWN_DEBUG_STATS = 0x00010000, /* Statistics updates */ + IWN_DEBUG_AMPDU = 0x00020000, /* A-MPDU specific Tx */ IWN_DEBUG_REGISTER = 0x20000000, /* print chipset register */ IWN_DEBUG_TRACE = 0x40000000, /* Print begin and start driver function */ IWN_DEBUG_FATAL = 0x80000000, /* fatal errors */ diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnreg.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnreg.h index 1a97f6e34f..2c6d865f4a 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnreg.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnreg.h @@ -1378,11 +1378,18 @@ struct iwn_ucode_info { #define IWN_AGG_TX_STATUS_MSK 0x00000fff #define IWN_AGG_TX_TRY_MSK 0x0000f000 +#define IWN_AGG_TX_TRY_POS 12 +#define IWN_AGG_TX_TRY_COUNT(status) \ + (((status) & IWN_AGG_TX_TRY_MSK) >> IWN_AGG_TX_TRY_POS) #define IWN_AGG_TX_STATE_LAST_SENT_MSK \ (IWN_AGG_TX_STATE_LAST_SENT_TTL_MSK | \ IWN_AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK) +#define IWN_AGG_TX_STATE_IGNORE_MASK \ + (IWN_AGG_TX_STATE_FEW_BYTES_MSK | \ + IWN_AGG_TX_STATE_ABORT_MSK) + /* # tx attempts for first frame in aggregation */ #define IWN_AGG_TX_STATE_TRY_CNT_POS 12 #define IWN_AGG_TX_STATE_TRY_CNT_MSK 0xf000 diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnvar.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnvar.h index e88d523c22..fc0f0c8b6f 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnvar.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnvar.h @@ -62,7 +62,7 @@ struct iwn_rx_radiotap_header { uint16_t wr_chan_flags; int8_t wr_dbm_antsignal; int8_t wr_dbm_antnoise; -} __packed; +} __packed __aligned(8); #define IWN_RX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_TSFT) | \ @@ -100,6 +100,11 @@ struct iwn_tx_data { bus_addr_t scratch_paddr; struct mbuf *m; struct ieee80211_node *ni; + unsigned int remapped:1; + unsigned int long_retries:7; +#define IWN_LONG_RETRY_FW_OVERFLOW 0x10 +#define IWN_LONG_RETRY_LIMIT_LOG 7 +#define IWN_LONG_RETRY_LIMIT ((1 << IWN_LONG_RETRY_LIMIT_LOG) - 3) }; struct iwn_tx_ring { @@ -138,8 +143,8 @@ struct iwn_node { uint8_t id; struct { uint64_t bitmap; + int short_retries; int startidx; - int nframes; } agg[IEEE80211_TID_SIZE]; }; diff --git a/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_maloioctl.h b/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_maloioctl.h index ffb01f9857..d4701f7bc4 100644 --- a/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_maloioctl.h +++ b/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_maloioctl.h @@ -93,7 +93,7 @@ struct malo_rx_radiotap_header { int8_t wr_antsignal; int8_t wr_antnoise; u_int8_t wr_antenna; -}; +} __packed __aligned(8); #define MALO_TX_RADIOTAP_PRESENT ( \ (1 << IEEE80211_RADIOTAP_FLAGS) | \ @@ -111,6 +111,6 @@ struct malo_tx_radiotap_header { u_int16_t wt_chan_flags; u_int8_t wt_txpower; u_int8_t wt_antenna; -}; +} __packed; #endif /* _DEV_MALO_MVIOCTL_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl_pci.c b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl_pci.c index 8572d5786c..a8899a00db 100644 --- a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl_pci.c +++ b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl_pci.c @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD: releng/12.0/sys/dev/mwl/if_mwl_pci.c 326255 2017-11-27 14:52 #include #include - + #include #include #include @@ -98,7 +98,6 @@ static const struct mwl_pci_ident mwl_pci_ids[] = { { 0x11ab, 0x2a0c, "Marvell 88W8363" }, { 0x11ab, 0x2a21, "Marvell 88W8363" }, { 0x11ab, 0x2a24, "Marvell 88W8363" }, - { 0, 0, NULL } }; @@ -280,7 +279,6 @@ static device_method_t mwl_pci_methods[] = { DEVMETHOD(device_shutdown, mwl_pci_shutdown), DEVMETHOD(device_suspend, mwl_pci_suspend), DEVMETHOD(device_resume, mwl_pci_resume), - { 0,0 } }; static driver_t mwl_pci_driver = { diff --git a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwlioctl.h b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwlioctl.h index a1fe7903b6..60ddcf9b53 100644 --- a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwlioctl.h +++ b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwlioctl.h @@ -115,7 +115,7 @@ struct mwl_rx_radiotap_header { int8_t wr_antsignal; int8_t wr_antnoise; u_int8_t wr_antenna; -}; +} __packed __aligned(8); #define MWL_TX_RADIOTAP_PRESENT ( \ (1 << IEEE80211_RADIOTAP_FLAGS) | \ @@ -133,6 +133,6 @@ struct mwl_tx_radiotap_header { u_int16_t wt_chan_flags; u_int8_t wt_txpower; u_int8_t wt_antenna; -}; +} __packed; #endif /* _DEV_MWL_MVIOCTL_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/mwlreg.h b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/mwlreg.h index 969cd05ea1..3086510edb 100644 --- a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/mwlreg.h +++ b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/mwlreg.h @@ -57,7 +57,6 @@ #define MACREG_REG_A2H_INTERRUPT_CLEAR_SEL 0x00000C38 // (From ARM to host) #define MACREG_REG_A2H_INTERRUPT_STATUS_MASK 0x00000C3C // (From ARM to host) - // Map to 0x80000000 on BAR1 #define MACREG_REG_GEN_PTR 0x00000C10 #define MACREG_REG_INT_CODE 0x00000C14 @@ -101,7 +100,6 @@ #define MACREG_A2HRIC_BIT_MASK ISR_SRC_BITS - // Bit definitio for MACREG_REG_H2A_INTERRUPT_CAUSE (H2ARIC) #define MACREG_H2ARIC_BIT_PPA_READY 0x00000001 // bit 0 #define MACREG_H2ARIC_BIT_DOOR_BELL 0x00000002 // bit 1 @@ -341,7 +339,6 @@ struct mwl_rxdesc { #define HostCmd_RESULT_BUSY 0x0004 // System is busy (command ignored) #define HostCmd_RESULT_PARTIAL_DATA 0x0005 // Data buffer is not big enough - /* // Definition of action or option for each command // @@ -377,7 +374,6 @@ struct mwl_rxdesc { #define HostCmd_WEP_KEY_INDEX_MASK 0x3fffffff - // Define action or option for HostCmd_CMD_802_11_RESET #define HostCmd_ACT_HALT 0x0001 #define HostCmd_ACT_RESTART 0x0002 @@ -485,7 +481,6 @@ typedef struct { u_int32_t Enable; /* FALSE: Disable or TRUE: Enable */ } __packed HostCmd_DS_BSS_START; - typedef struct { u_int8_t ElemId; u_int8_t Len; @@ -704,7 +699,7 @@ typedef struct { uint32_t FixedRate; // legacy rate(not index) or an MCS code. uint32_t RetryCount; } __packed FIXED_RATE_ENTRY; - + typedef struct { FWCmdHdr CmdHdr; uint32_t Action; //HostCmd_ACT_GEN_GET 0x0000 @@ -723,7 +718,7 @@ typedef struct { uint32_t EntryCount; FIXED_RATE_ENTRY FixedRateTable[4]; } __packed USE_FIXED_RATE_INFO; - + typedef struct { FWCmdHdr CmdHdr; uint32_t Action; @@ -745,7 +740,6 @@ typedef struct { uint8_t Slot; // Slot=0 if regular, Slot=1 if short. } __packed HostCmd_FW_SET_SLOT; - // Define data structure for HostCmd_CMD_802_11_GET_STAT typedef struct { FWCmdHdr CmdHdr; @@ -778,7 +772,6 @@ typedef struct { uint32_t RxExcludedFrames; } __packed HostCmd_DS_802_11_GET_STAT; - // Define data structure for HostCmd_CMD_MAC_REG_ACCESS typedef struct { FWCmdHdr CmdHdr; @@ -806,7 +799,6 @@ typedef struct { uint8_t Reserverd[3]; } __packed HostCmd_DS_RF_REG_ACCESS; - // Define data structure for HostCmd_CMD_802_11_RADIO_CONTROL typedef struct { FWCmdHdr CmdHdr; @@ -815,7 +807,6 @@ typedef struct { uint16_t RadioOn; } __packed HostCmd_DS_802_11_RADIO_CONTROL; - #define TX_POWER_LEVEL_TOTAL 8 // Define data structure for HostCmd_CMD_802_11_RF_TX_POWER typedef struct { @@ -1141,7 +1132,6 @@ typedef struct { uint8_t ActionData[1]; } __packed HostCmd_FW_UPDATE_ENCRYPTION; - typedef struct { FWCmdHdr CmdHdr; uint32_t ActionType; // ENCR_ACTION_TYPE @@ -1272,8 +1262,6 @@ typedef struct { uint8_t Watchdogbitmap; // for SW/BA } __packed HostCmd_FW_GET_WATCHDOG_BITMAP; - - // Define data structure for HostCmd_CMD_SET_REGION_POWER typedef struct { FWCmdHdr CmdHdr; diff --git a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560var.h b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560var.h index 70dcca31f3..73043524ec 100644 --- a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560var.h +++ b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560var.h @@ -27,7 +27,7 @@ struct rt2560_rx_radiotap_header { int8_t wr_antsignal; int8_t wr_antnoise; uint8_t wr_antenna; -}; +} __packed __aligned(8); #define RT2560_RX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_TSFT) | \ @@ -45,7 +45,7 @@ struct rt2560_tx_radiotap_header { uint16_t wt_chan_freq; uint16_t wt_chan_flags; uint8_t wt_antenna; -}; +} __packed; #define RT2560_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661var.h b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661var.h index fb609768ab..33d55cb9a8 100644 --- a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661var.h +++ b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661var.h @@ -42,7 +42,7 @@ struct rt2661_tx_radiotap_header { uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define RT2661_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2860var.h b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2860var.h index 41eaa7f301..7c8dd84c0d 100644 --- a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2860var.h +++ b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2860var.h @@ -55,7 +55,7 @@ struct rt2860_tx_radiotap_header { uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define RT2860_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn.c index fba8c74870..499ae4ebcd 100644 --- a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn.c +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn.c @@ -1564,10 +1564,6 @@ rtwn_set_channel(struct ieee80211com *ic) RTWN_LOCK(sc); rtwn_set_chan(sc, c); - sc->sc_rxtap.wr_chan_freq = htole16(c->ic_freq); - sc->sc_rxtap.wr_chan_flags = htole16(c->ic_flags); - sc->sc_txtap.wt_chan_freq = htole16(c->ic_freq); - sc->sc_txtap.wt_chan_flags = htole16(c->ic_flags); RTWN_UNLOCK(sc); } diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnvar.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnvar.h index 40050c3b90..fe31aa5447 100644 --- a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnvar.h +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnvar.h @@ -62,9 +62,10 @@ struct rtwn_rx_radiotap_header { struct rtwn_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; + uint8_t wt_pad; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define RTWN_TX_RADIOTAP_PRESENT \ (1 << IEEE80211_RADIOTAP_FLAGS | \