summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath9k/recv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/recv.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c65
1 files changed, 42 insertions, 23 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index c90ca57..ebb8d36 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -381,6 +381,10 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
| ATH9K_RX_FILTER_MCAST;
+ /* if operating on a DFS channel, enable radar pulse detection */
+ if (sc->hw->conf.radar_enabled)
+ rfilt |= ATH9K_RX_FILTER_PHYRADAR | ATH9K_RX_FILTER_PHYERR;
+
if (sc->rx.rxfilter & FIF_PROBE_REQ)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
@@ -723,6 +727,13 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
ret = ath9k_hw_rxprocdesc(ah, tds, &trs);
if (ret == -EINPROGRESS)
return NULL;
+
+ /*
+ * mark descriptor as zero-length and set the 'more'
+ * flag to ensure that both buffers get discarded
+ */
+ rs->rs_datalen = 0;
+ rs->rs_more = true;
}
list_del(&bf->list);
@@ -929,14 +940,20 @@ static void ath9k_process_rssi(struct ath_common *common,
* up the frame up to let mac80211 handle the actual error case, be it no
* decryption key or real decryption error. This let us keep statistics there.
*/
-static int ath9k_rx_skb_preprocess(struct ath_common *common,
- struct ieee80211_hw *hw,
+static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
struct ieee80211_hdr *hdr,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rx_status,
bool *decrypt_error)
{
- struct ath_hw *ah = common->ah;
+ struct ieee80211_hw *hw = sc->hw;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ bool discard_current = sc->rx.discard_next;
+
+ sc->rx.discard_next = rx_stats->rs_more;
+ if (discard_current)
+ return -EINVAL;
/*
* everything but the rate is checked here, the rate check is done
@@ -962,6 +979,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
if (rx_stats->rs_moreaggr)
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+ sc->rx.discard_next = false;
return 0;
}
@@ -981,7 +999,7 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
fc = hdr->frame_control;
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(fc);
/* The MAC header is padded to have 32-bit boundary if the
* packet payload is non-zero. The general calculation for
@@ -1162,6 +1180,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
u64 tsf = 0;
u32 tsf_lower = 0;
unsigned long flags;
+ dma_addr_t new_buf_addr;
if (edma)
dma_type = DMA_BIDIRECTIONAL;
@@ -1228,6 +1247,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
rxs->mactime += 0x100000000ULL;
+ if (rs.rs_phyerr == ATH9K_PHYERR_RADAR)
+ ath9k_dfs_process_phyerr(sc, hdr, &rs, rxs->mactime);
+
if (rs.rs_status & ATH9K_RXERR_PHY) {
if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) {
RX_STAT_INC(rx_spectral);
@@ -1235,8 +1257,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
}
}
- retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
- rxs, &decrypt_error);
+ retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs,
+ &decrypt_error);
if (retval)
goto requeue_drop_frag;
@@ -1257,10 +1279,20 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
goto requeue_drop_frag;
}
+ /* We will now give hardware our shiny new allocated skb */
+ new_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
+ common->rx_bufsize, dma_type);
+ if (unlikely(dma_mapping_error(sc->dev, new_buf_addr))) {
+ dev_kfree_skb_any(requeue_skb);
+ goto requeue_drop_frag;
+ }
+
+ bf->bf_mpdu = requeue_skb;
+ bf->bf_buf_addr = new_buf_addr;
+
/* Unmap the frame */
dma_unmap_single(sc->dev, bf->bf_buf_addr,
- common->rx_bufsize,
- dma_type);
+ common->rx_bufsize, dma_type);
skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len);
if (ah->caps.rx_status_len)
@@ -1270,21 +1302,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
rxs, decrypt_error);
- /* We will now give hardware our shiny new allocated skb */
- bf->bf_mpdu = requeue_skb;
- bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
- common->rx_bufsize,
- dma_type);
- if (unlikely(dma_mapping_error(sc->dev,
- bf->bf_buf_addr))) {
- dev_kfree_skb_any(requeue_skb);
- bf->bf_mpdu = NULL;
- bf->bf_buf_addr = 0;
- ath_err(common, "dma_mapping_error() on RX\n");
- ieee80211_rx(hw, skb);
- break;
- }
-
if (rs.rs_more) {
RX_STAT_INC(rx_frags);
/*
@@ -1302,6 +1319,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
sc->rx.frag = skb;
goto requeue;
}
+ if (rs.rs_status & ATH9K_RXERR_CORRUPT_DESC)
+ goto requeue_drop_frag;
if (sc->rx.frag) {
int space = skb->len - skb_tailroom(hdr_skb);