162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (c) 2008-2011 Atheros Communications Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any
562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above
662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1162306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1362306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1462306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1862306a36Sopenharmony_ci#include "ath9k.h"
1962306a36Sopenharmony_ci#include "ar9003_mac.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define SKB_CB_ATHBUF(__skb)	(*((struct ath_rxbuf **)__skb->cb))
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	return sc->ps_enabled &&
2662306a36Sopenharmony_ci	       (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP);
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/*
3062306a36Sopenharmony_ci * Setup and link descriptors.
3162306a36Sopenharmony_ci *
3262306a36Sopenharmony_ci * 11N: we can no longer afford to self link the last descriptor.
3362306a36Sopenharmony_ci * MAC acknowledges BA status as long as it copies frames to host
3462306a36Sopenharmony_ci * buffer (or rx fifo). This can incorrectly acknowledge packets
3562306a36Sopenharmony_ci * to a sender if last desc is self-linked.
3662306a36Sopenharmony_ci */
3762306a36Sopenharmony_cistatic void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
3862306a36Sopenharmony_ci			    bool flush)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
4162306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
4262306a36Sopenharmony_ci	struct ath_desc *ds;
4362306a36Sopenharmony_ci	struct sk_buff *skb;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	ds = bf->bf_desc;
4662306a36Sopenharmony_ci	ds->ds_link = 0; /* link to null */
4762306a36Sopenharmony_ci	ds->ds_data = bf->bf_buf_addr;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	/* virtual addr of the beginning of the buffer. */
5062306a36Sopenharmony_ci	skb = bf->bf_mpdu;
5162306a36Sopenharmony_ci	BUG_ON(skb == NULL);
5262306a36Sopenharmony_ci	ds->ds_vdata = skb->data;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	/*
5562306a36Sopenharmony_ci	 * setup rx descriptors. The rx_bufsize here tells the hardware
5662306a36Sopenharmony_ci	 * how much data it can DMA to us and that we are prepared
5762306a36Sopenharmony_ci	 * to process
5862306a36Sopenharmony_ci	 */
5962306a36Sopenharmony_ci	ath9k_hw_setuprxdesc(ah, ds,
6062306a36Sopenharmony_ci			     common->rx_bufsize,
6162306a36Sopenharmony_ci			     0);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	if (sc->rx.rxlink)
6462306a36Sopenharmony_ci		*sc->rx.rxlink = bf->bf_daddr;
6562306a36Sopenharmony_ci	else if (!flush)
6662306a36Sopenharmony_ci		ath9k_hw_putrxbuf(ah, bf->bf_daddr);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	sc->rx.rxlink = &ds->ds_link;
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
7262306a36Sopenharmony_ci			      bool flush)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	if (sc->rx.buf_hold)
7562306a36Sopenharmony_ci		ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	sc->rx.buf_hold = bf;
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistatic void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	/* XXX block beacon interrupts */
8362306a36Sopenharmony_ci	ath9k_hw_setantenna(sc->sc_ah, antenna);
8462306a36Sopenharmony_ci	sc->rx.defant = antenna;
8562306a36Sopenharmony_ci	sc->rx.rxotherant = 0;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic void ath_opmode_init(struct ath_softc *sc)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
9162306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	u32 rfilt, mfilt[2];
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	/* configure rx filter */
9662306a36Sopenharmony_ci	rfilt = ath_calcrxfilter(sc);
9762306a36Sopenharmony_ci	ath9k_hw_setrxfilter(ah, rfilt);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	/* configure bssid mask */
10062306a36Sopenharmony_ci	ath_hw_setbssidmask(common);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	/* configure operational mode */
10362306a36Sopenharmony_ci	ath9k_hw_setopmode(ah);
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	/* calculate and install multicast filter */
10662306a36Sopenharmony_ci	mfilt[0] = mfilt[1] = ~0;
10762306a36Sopenharmony_ci	ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistatic bool ath_rx_edma_buf_link(struct ath_softc *sc,
11162306a36Sopenharmony_ci				 enum ath9k_rx_qtype qtype)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
11462306a36Sopenharmony_ci	struct ath_rx_edma *rx_edma;
11562306a36Sopenharmony_ci	struct sk_buff *skb;
11662306a36Sopenharmony_ci	struct ath_rxbuf *bf;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	rx_edma = &sc->rx.rx_edma[qtype];
11962306a36Sopenharmony_ci	if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize)
12062306a36Sopenharmony_ci		return false;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list);
12362306a36Sopenharmony_ci	list_del_init(&bf->list);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	skb = bf->bf_mpdu;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	memset(skb->data, 0, ah->caps.rx_status_len);
12862306a36Sopenharmony_ci	dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
12962306a36Sopenharmony_ci				ah->caps.rx_status_len, DMA_TO_DEVICE);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	SKB_CB_ATHBUF(skb) = bf;
13262306a36Sopenharmony_ci	ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype);
13362306a36Sopenharmony_ci	__skb_queue_tail(&rx_edma->rx_fifo, skb);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	return true;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic void ath_rx_addbuffer_edma(struct ath_softc *sc,
13962306a36Sopenharmony_ci				  enum ath9k_rx_qtype qtype)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
14262306a36Sopenharmony_ci	struct ath_rxbuf *bf, *tbf;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	if (list_empty(&sc->rx.rxbuf)) {
14562306a36Sopenharmony_ci		ath_dbg(common, QUEUE, "No free rx buf available\n");
14662306a36Sopenharmony_ci		return;
14762306a36Sopenharmony_ci	}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list)
15062306a36Sopenharmony_ci		if (!ath_rx_edma_buf_link(sc, qtype))
15162306a36Sopenharmony_ci			break;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic void ath_rx_remove_buffer(struct ath_softc *sc,
15662306a36Sopenharmony_ci				 enum ath9k_rx_qtype qtype)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	struct ath_rxbuf *bf;
15962306a36Sopenharmony_ci	struct ath_rx_edma *rx_edma;
16062306a36Sopenharmony_ci	struct sk_buff *skb;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	rx_edma = &sc->rx.rx_edma[qtype];
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	while ((skb = __skb_dequeue(&rx_edma->rx_fifo)) != NULL) {
16562306a36Sopenharmony_ci		bf = SKB_CB_ATHBUF(skb);
16662306a36Sopenharmony_ci		BUG_ON(!bf);
16762306a36Sopenharmony_ci		list_add_tail(&bf->list, &sc->rx.rxbuf);
16862306a36Sopenharmony_ci	}
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_cistatic void ath_rx_edma_cleanup(struct ath_softc *sc)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
17462306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
17562306a36Sopenharmony_ci	struct ath_rxbuf *bf;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
17862306a36Sopenharmony_ci	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	list_for_each_entry(bf, &sc->rx.rxbuf, list) {
18162306a36Sopenharmony_ci		if (bf->bf_mpdu) {
18262306a36Sopenharmony_ci			dma_unmap_single(sc->dev, bf->bf_buf_addr,
18362306a36Sopenharmony_ci					common->rx_bufsize,
18462306a36Sopenharmony_ci					DMA_BIDIRECTIONAL);
18562306a36Sopenharmony_ci			dev_kfree_skb_any(bf->bf_mpdu);
18662306a36Sopenharmony_ci			bf->bf_buf_addr = 0;
18762306a36Sopenharmony_ci			bf->bf_mpdu = NULL;
18862306a36Sopenharmony_ci		}
18962306a36Sopenharmony_ci	}
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cistatic void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size)
19362306a36Sopenharmony_ci{
19462306a36Sopenharmony_ci	__skb_queue_head_init(&rx_edma->rx_fifo);
19562306a36Sopenharmony_ci	rx_edma->rx_fifo_hwsize = size;
19662306a36Sopenharmony_ci}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic int ath_rx_edma_init(struct ath_softc *sc, int nbufs)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
20162306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
20262306a36Sopenharmony_ci	struct sk_buff *skb;
20362306a36Sopenharmony_ci	struct ath_rxbuf *bf;
20462306a36Sopenharmony_ci	int error = 0, i;
20562306a36Sopenharmony_ci	u32 size;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
20862306a36Sopenharmony_ci				    ah->caps.rx_status_len);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_LP],
21162306a36Sopenharmony_ci			       ah->caps.rx_lp_qdepth);
21262306a36Sopenharmony_ci	ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP],
21362306a36Sopenharmony_ci			       ah->caps.rx_hp_qdepth);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	size = sizeof(struct ath_rxbuf) * nbufs;
21662306a36Sopenharmony_ci	bf = devm_kzalloc(sc->dev, size, GFP_KERNEL);
21762306a36Sopenharmony_ci	if (!bf)
21862306a36Sopenharmony_ci		return -ENOMEM;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	INIT_LIST_HEAD(&sc->rx.rxbuf);
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	for (i = 0; i < nbufs; i++, bf++) {
22362306a36Sopenharmony_ci		skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_KERNEL);
22462306a36Sopenharmony_ci		if (!skb) {
22562306a36Sopenharmony_ci			error = -ENOMEM;
22662306a36Sopenharmony_ci			goto rx_init_fail;
22762306a36Sopenharmony_ci		}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci		memset(skb->data, 0, common->rx_bufsize);
23062306a36Sopenharmony_ci		bf->bf_mpdu = skb;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci		bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
23362306a36Sopenharmony_ci						 common->rx_bufsize,
23462306a36Sopenharmony_ci						 DMA_BIDIRECTIONAL);
23562306a36Sopenharmony_ci		if (unlikely(dma_mapping_error(sc->dev,
23662306a36Sopenharmony_ci						bf->bf_buf_addr))) {
23762306a36Sopenharmony_ci				dev_kfree_skb_any(skb);
23862306a36Sopenharmony_ci				bf->bf_mpdu = NULL;
23962306a36Sopenharmony_ci				bf->bf_buf_addr = 0;
24062306a36Sopenharmony_ci				ath_err(common,
24162306a36Sopenharmony_ci					"dma_mapping_error() on RX init\n");
24262306a36Sopenharmony_ci				error = -ENOMEM;
24362306a36Sopenharmony_ci				goto rx_init_fail;
24462306a36Sopenharmony_ci		}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci		list_add_tail(&bf->list, &sc->rx.rxbuf);
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	return 0;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cirx_init_fail:
25262306a36Sopenharmony_ci	ath_rx_edma_cleanup(sc);
25362306a36Sopenharmony_ci	return error;
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistatic void ath_edma_start_recv(struct ath_softc *sc)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	ath9k_hw_rxena(sc->sc_ah);
25962306a36Sopenharmony_ci	ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP);
26062306a36Sopenharmony_ci	ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP);
26162306a36Sopenharmony_ci	ath_opmode_init(sc);
26262306a36Sopenharmony_ci	ath9k_hw_startpcureceive(sc->sc_ah, sc->cur_chan->offchannel);
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic void ath_edma_stop_recv(struct ath_softc *sc)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
26862306a36Sopenharmony_ci	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ciint ath_rx_init(struct ath_softc *sc, int nbufs)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
27462306a36Sopenharmony_ci	struct sk_buff *skb;
27562306a36Sopenharmony_ci	struct ath_rxbuf *bf;
27662306a36Sopenharmony_ci	int error = 0;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	spin_lock_init(&sc->sc_pcu_lock);
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
28162306a36Sopenharmony_ci			     sc->sc_ah->caps.rx_status_len;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
28462306a36Sopenharmony_ci		return ath_rx_edma_init(sc, nbufs);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	ath_dbg(common, CONFIG, "cachelsz %u rxbufsize %u\n",
28762306a36Sopenharmony_ci		common->cachelsz, common->rx_bufsize);
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	/* Initialize rx descriptors */
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
29262306a36Sopenharmony_ci				  "rx", nbufs, 1, 0);
29362306a36Sopenharmony_ci	if (error != 0) {
29462306a36Sopenharmony_ci		ath_err(common,
29562306a36Sopenharmony_ci			"failed to allocate rx descriptors: %d\n",
29662306a36Sopenharmony_ci			error);
29762306a36Sopenharmony_ci		goto err;
29862306a36Sopenharmony_ci	}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	list_for_each_entry(bf, &sc->rx.rxbuf, list) {
30162306a36Sopenharmony_ci		skb = ath_rxbuf_alloc(common, common->rx_bufsize,
30262306a36Sopenharmony_ci				      GFP_KERNEL);
30362306a36Sopenharmony_ci		if (skb == NULL) {
30462306a36Sopenharmony_ci			error = -ENOMEM;
30562306a36Sopenharmony_ci			goto err;
30662306a36Sopenharmony_ci		}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci		bf->bf_mpdu = skb;
30962306a36Sopenharmony_ci		bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
31062306a36Sopenharmony_ci						 common->rx_bufsize,
31162306a36Sopenharmony_ci						 DMA_FROM_DEVICE);
31262306a36Sopenharmony_ci		if (unlikely(dma_mapping_error(sc->dev,
31362306a36Sopenharmony_ci					       bf->bf_buf_addr))) {
31462306a36Sopenharmony_ci			dev_kfree_skb_any(skb);
31562306a36Sopenharmony_ci			bf->bf_mpdu = NULL;
31662306a36Sopenharmony_ci			bf->bf_buf_addr = 0;
31762306a36Sopenharmony_ci			ath_err(common,
31862306a36Sopenharmony_ci				"dma_mapping_error() on RX init\n");
31962306a36Sopenharmony_ci			error = -ENOMEM;
32062306a36Sopenharmony_ci			goto err;
32162306a36Sopenharmony_ci		}
32262306a36Sopenharmony_ci	}
32362306a36Sopenharmony_ci	sc->rx.rxlink = NULL;
32462306a36Sopenharmony_cierr:
32562306a36Sopenharmony_ci	if (error)
32662306a36Sopenharmony_ci		ath_rx_cleanup(sc);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	return error;
32962306a36Sopenharmony_ci}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_civoid ath_rx_cleanup(struct ath_softc *sc)
33262306a36Sopenharmony_ci{
33362306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
33462306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
33562306a36Sopenharmony_ci	struct sk_buff *skb;
33662306a36Sopenharmony_ci	struct ath_rxbuf *bf;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
33962306a36Sopenharmony_ci		ath_rx_edma_cleanup(sc);
34062306a36Sopenharmony_ci		return;
34162306a36Sopenharmony_ci	}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	list_for_each_entry(bf, &sc->rx.rxbuf, list) {
34462306a36Sopenharmony_ci		skb = bf->bf_mpdu;
34562306a36Sopenharmony_ci		if (skb) {
34662306a36Sopenharmony_ci			dma_unmap_single(sc->dev, bf->bf_buf_addr,
34762306a36Sopenharmony_ci					 common->rx_bufsize,
34862306a36Sopenharmony_ci					 DMA_FROM_DEVICE);
34962306a36Sopenharmony_ci			dev_kfree_skb(skb);
35062306a36Sopenharmony_ci			bf->bf_buf_addr = 0;
35162306a36Sopenharmony_ci			bf->bf_mpdu = NULL;
35262306a36Sopenharmony_ci		}
35362306a36Sopenharmony_ci	}
35462306a36Sopenharmony_ci}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci/*
35762306a36Sopenharmony_ci * Calculate the receive filter according to the
35862306a36Sopenharmony_ci * operating mode and state:
35962306a36Sopenharmony_ci *
36062306a36Sopenharmony_ci * o always accept unicast, broadcast, and multicast traffic
36162306a36Sopenharmony_ci * o maintain current state of phy error reception (the hal
36262306a36Sopenharmony_ci *   may enable phy error frames for noise immunity work)
36362306a36Sopenharmony_ci * o probe request frames are accepted only when operating in
36462306a36Sopenharmony_ci *   hostap, adhoc, or monitor modes
36562306a36Sopenharmony_ci * o enable promiscuous mode according to the interface state
36662306a36Sopenharmony_ci * o accept beacons:
36762306a36Sopenharmony_ci *   - when operating in adhoc mode so the 802.11 layer creates
36862306a36Sopenharmony_ci *     node table entries for peers,
36962306a36Sopenharmony_ci *   - when operating in station mode for collecting rssi data when
37062306a36Sopenharmony_ci *     the station is otherwise quiet, or
37162306a36Sopenharmony_ci *   - when operating as a repeater so we see repeater-sta beacons
37262306a36Sopenharmony_ci *   - when scanning
37362306a36Sopenharmony_ci */
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ciu32 ath_calcrxfilter(struct ath_softc *sc)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
37862306a36Sopenharmony_ci	u32 rfilt;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_ATH9K_TX99))
38162306a36Sopenharmony_ci		return 0;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
38462306a36Sopenharmony_ci		| ATH9K_RX_FILTER_MCAST;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	/* if operating on a DFS channel, enable radar pulse detection */
38762306a36Sopenharmony_ci	if (sc->hw->conf.radar_enabled)
38862306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_PHYRADAR | ATH9K_RX_FILTER_PHYERR;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	spin_lock_bh(&sc->chan_lock);
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	if (sc->cur_chan->rxfilter & FIF_PROBE_REQ)
39362306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_PROBEREQ;
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	if (sc->sc_ah->is_monitoring)
39662306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_PROM;
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	if ((sc->cur_chan->rxfilter & FIF_CONTROL) ||
39962306a36Sopenharmony_ci	    sc->sc_ah->dynack.enabled)
40062306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_CONTROL;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
40362306a36Sopenharmony_ci	    (sc->cur_chan->nvifs <= 1) &&
40462306a36Sopenharmony_ci	    !(sc->cur_chan->rxfilter & FIF_BCN_PRBRESP_PROMISC))
40562306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_MYBEACON;
40662306a36Sopenharmony_ci	else if (sc->sc_ah->opmode != NL80211_IFTYPE_OCB)
40762306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_BEACON;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
41062306a36Sopenharmony_ci	    (sc->cur_chan->rxfilter & FIF_PSPOLL))
41162306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_PSPOLL;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	if (sc->cur_chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
41462306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_COMP_BAR;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	if (sc->cur_chan->nvifs > 1 ||
41762306a36Sopenharmony_ci	    (sc->cur_chan->rxfilter & (FIF_OTHER_BSS | FIF_MCAST_ACTION))) {
41862306a36Sopenharmony_ci		/* This is needed for older chips */
41962306a36Sopenharmony_ci		if (sc->sc_ah->hw_version.macVersion <= AR_SREV_VERSION_9160)
42062306a36Sopenharmony_ci			rfilt |= ATH9K_RX_FILTER_PROM;
42162306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
42262306a36Sopenharmony_ci	}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah) ||
42562306a36Sopenharmony_ci	    AR_SREV_9561(sc->sc_ah))
42662306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_4ADDRESS;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah))
42962306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	if (ath9k_is_chanctx_enabled() &&
43262306a36Sopenharmony_ci	    test_bit(ATH_OP_SCANNING, &common->op_flags))
43362306a36Sopenharmony_ci		rfilt |= ATH9K_RX_FILTER_BEACON;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	spin_unlock_bh(&sc->chan_lock);
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	return rfilt;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_civoid ath_startrecv(struct ath_softc *sc)
44262306a36Sopenharmony_ci{
44362306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
44462306a36Sopenharmony_ci	struct ath_rxbuf *bf, *tbf;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
44762306a36Sopenharmony_ci		ath_edma_start_recv(sc);
44862306a36Sopenharmony_ci		return;
44962306a36Sopenharmony_ci	}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	if (list_empty(&sc->rx.rxbuf))
45262306a36Sopenharmony_ci		goto start_recv;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	sc->rx.buf_hold = NULL;
45562306a36Sopenharmony_ci	sc->rx.rxlink = NULL;
45662306a36Sopenharmony_ci	list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
45762306a36Sopenharmony_ci		ath_rx_buf_link(sc, bf, false);
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	/* We could have deleted elements so the list may be empty now */
46162306a36Sopenharmony_ci	if (list_empty(&sc->rx.rxbuf))
46262306a36Sopenharmony_ci		goto start_recv;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list);
46562306a36Sopenharmony_ci	ath9k_hw_putrxbuf(ah, bf->bf_daddr);
46662306a36Sopenharmony_ci	ath9k_hw_rxena(ah);
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_cistart_recv:
46962306a36Sopenharmony_ci	ath_opmode_init(sc);
47062306a36Sopenharmony_ci	ath9k_hw_startpcureceive(ah, sc->cur_chan->offchannel);
47162306a36Sopenharmony_ci}
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_cistatic void ath_flushrecv(struct ath_softc *sc)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
47662306a36Sopenharmony_ci		ath_rx_tasklet(sc, 1, true);
47762306a36Sopenharmony_ci	ath_rx_tasklet(sc, 1, false);
47862306a36Sopenharmony_ci}
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_cibool ath_stoprecv(struct ath_softc *sc)
48162306a36Sopenharmony_ci{
48262306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
48362306a36Sopenharmony_ci	bool stopped, reset = false;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	ath9k_hw_abortpcurecv(ah);
48662306a36Sopenharmony_ci	ath9k_hw_setrxfilter(ah, 0);
48762306a36Sopenharmony_ci	stopped = ath9k_hw_stopdmarecv(ah, &reset);
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	ath_flushrecv(sc);
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
49262306a36Sopenharmony_ci		ath_edma_stop_recv(sc);
49362306a36Sopenharmony_ci	else
49462306a36Sopenharmony_ci		sc->rx.rxlink = NULL;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	if (!(ah->ah_flags & AH_UNPLUGGED) &&
49762306a36Sopenharmony_ci	    unlikely(!stopped)) {
49862306a36Sopenharmony_ci		ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
49962306a36Sopenharmony_ci			"Failed to stop Rx DMA\n");
50062306a36Sopenharmony_ci		RESET_STAT_INC(sc, RESET_RX_DMA_ERROR);
50162306a36Sopenharmony_ci	}
50262306a36Sopenharmony_ci	return stopped && !reset;
50362306a36Sopenharmony_ci}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_cistatic bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci	/* Check whether the Beacon frame has DTIM indicating buffered bc/mc */
50862306a36Sopenharmony_ci	struct ieee80211_mgmt *mgmt;
50962306a36Sopenharmony_ci	u8 *pos, *end, id, elen;
51062306a36Sopenharmony_ci	struct ieee80211_tim_ie *tim;
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	mgmt = (struct ieee80211_mgmt *)skb->data;
51362306a36Sopenharmony_ci	pos = mgmt->u.beacon.variable;
51462306a36Sopenharmony_ci	end = skb->data + skb->len;
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	while (pos + 2 < end) {
51762306a36Sopenharmony_ci		id = *pos++;
51862306a36Sopenharmony_ci		elen = *pos++;
51962306a36Sopenharmony_ci		if (pos + elen > end)
52062306a36Sopenharmony_ci			break;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci		if (id == WLAN_EID_TIM) {
52362306a36Sopenharmony_ci			if (elen < sizeof(*tim))
52462306a36Sopenharmony_ci				break;
52562306a36Sopenharmony_ci			tim = (struct ieee80211_tim_ie *) pos;
52662306a36Sopenharmony_ci			if (tim->dtim_count != 0)
52762306a36Sopenharmony_ci				break;
52862306a36Sopenharmony_ci			return tim->bitmap_ctrl & 0x01;
52962306a36Sopenharmony_ci		}
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci		pos += elen;
53262306a36Sopenharmony_ci	}
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	return false;
53562306a36Sopenharmony_ci}
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_cistatic void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
53862306a36Sopenharmony_ci{
53962306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
54062306a36Sopenharmony_ci	bool skip_beacon = false;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	if (skb->len < 24 + 8 + 2 + 2)
54362306a36Sopenharmony_ci		return;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	sc->ps_flags &= ~PS_WAIT_FOR_BEACON;
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	if (sc->ps_flags & PS_BEACON_SYNC) {
54862306a36Sopenharmony_ci		sc->ps_flags &= ~PS_BEACON_SYNC;
54962306a36Sopenharmony_ci		ath_dbg(common, PS,
55062306a36Sopenharmony_ci			"Reconfigure beacon timers based on synchronized timestamp\n");
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
55362306a36Sopenharmony_ci		if (ath9k_is_chanctx_enabled()) {
55462306a36Sopenharmony_ci			if (sc->cur_chan == &sc->offchannel.chan)
55562306a36Sopenharmony_ci				skip_beacon = true;
55662306a36Sopenharmony_ci		}
55762306a36Sopenharmony_ci#endif
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci		if (!skip_beacon &&
56062306a36Sopenharmony_ci		    !(WARN_ON_ONCE(sc->cur_chan->beacon.beacon_interval == 0)))
56162306a36Sopenharmony_ci			ath9k_set_beacon(sc);
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci		ath9k_p2p_beacon_sync(sc);
56462306a36Sopenharmony_ci	}
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	if (ath_beacon_dtim_pending_cab(skb)) {
56762306a36Sopenharmony_ci		/*
56862306a36Sopenharmony_ci		 * Remain awake waiting for buffered broadcast/multicast
56962306a36Sopenharmony_ci		 * frames. If the last broadcast/multicast frame is not
57062306a36Sopenharmony_ci		 * received properly, the next beacon frame will work as
57162306a36Sopenharmony_ci		 * a backup trigger for returning into NETWORK SLEEP state,
57262306a36Sopenharmony_ci		 * so we are waiting for it as well.
57362306a36Sopenharmony_ci		 */
57462306a36Sopenharmony_ci		ath_dbg(common, PS,
57562306a36Sopenharmony_ci			"Received DTIM beacon indicating buffered broadcast/multicast frame(s)\n");
57662306a36Sopenharmony_ci		sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON;
57762306a36Sopenharmony_ci		return;
57862306a36Sopenharmony_ci	}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	if (sc->ps_flags & PS_WAIT_FOR_CAB) {
58162306a36Sopenharmony_ci		/*
58262306a36Sopenharmony_ci		 * This can happen if a broadcast frame is dropped or the AP
58362306a36Sopenharmony_ci		 * fails to send a frame indicating that all CAB frames have
58462306a36Sopenharmony_ci		 * been delivered.
58562306a36Sopenharmony_ci		 */
58662306a36Sopenharmony_ci		sc->ps_flags &= ~PS_WAIT_FOR_CAB;
58762306a36Sopenharmony_ci		ath_dbg(common, PS, "PS wait for CAB frames timed out\n");
58862306a36Sopenharmony_ci	}
58962306a36Sopenharmony_ci}
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_cistatic void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon)
59262306a36Sopenharmony_ci{
59362306a36Sopenharmony_ci	struct ieee80211_hdr *hdr;
59462306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	hdr = (struct ieee80211_hdr *)skb->data;
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	/* Process Beacon and CAB receive in PS state */
59962306a36Sopenharmony_ci	if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc))
60062306a36Sopenharmony_ci	    && mybeacon) {
60162306a36Sopenharmony_ci		ath_rx_ps_beacon(sc, skb);
60262306a36Sopenharmony_ci	} else if ((sc->ps_flags & PS_WAIT_FOR_CAB) &&
60362306a36Sopenharmony_ci		   (ieee80211_is_data(hdr->frame_control) ||
60462306a36Sopenharmony_ci		    ieee80211_is_action(hdr->frame_control)) &&
60562306a36Sopenharmony_ci		   is_multicast_ether_addr(hdr->addr1) &&
60662306a36Sopenharmony_ci		   !ieee80211_has_moredata(hdr->frame_control)) {
60762306a36Sopenharmony_ci		/*
60862306a36Sopenharmony_ci		 * No more broadcast/multicast frames to be received at this
60962306a36Sopenharmony_ci		 * point.
61062306a36Sopenharmony_ci		 */
61162306a36Sopenharmony_ci		sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON);
61262306a36Sopenharmony_ci		ath_dbg(common, PS,
61362306a36Sopenharmony_ci			"All PS CAB frames received, back to sleep\n");
61462306a36Sopenharmony_ci	} else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) &&
61562306a36Sopenharmony_ci		   !is_multicast_ether_addr(hdr->addr1) &&
61662306a36Sopenharmony_ci		   !ieee80211_has_morefrags(hdr->frame_control)) {
61762306a36Sopenharmony_ci		sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA;
61862306a36Sopenharmony_ci		ath_dbg(common, PS,
61962306a36Sopenharmony_ci			"Going back to sleep after having received PS-Poll data (0x%lx)\n",
62062306a36Sopenharmony_ci			sc->ps_flags & (PS_WAIT_FOR_BEACON |
62162306a36Sopenharmony_ci					PS_WAIT_FOR_CAB |
62262306a36Sopenharmony_ci					PS_WAIT_FOR_PSPOLL_DATA |
62362306a36Sopenharmony_ci					PS_WAIT_FOR_TX_ACK));
62462306a36Sopenharmony_ci	}
62562306a36Sopenharmony_ci}
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_cistatic bool ath_edma_get_buffers(struct ath_softc *sc,
62862306a36Sopenharmony_ci				 enum ath9k_rx_qtype qtype,
62962306a36Sopenharmony_ci				 struct ath_rx_status *rs,
63062306a36Sopenharmony_ci				 struct ath_rxbuf **dest)
63162306a36Sopenharmony_ci{
63262306a36Sopenharmony_ci	struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
63362306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
63462306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
63562306a36Sopenharmony_ci	struct sk_buff *skb;
63662306a36Sopenharmony_ci	struct ath_rxbuf *bf;
63762306a36Sopenharmony_ci	int ret;
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	skb = skb_peek(&rx_edma->rx_fifo);
64062306a36Sopenharmony_ci	if (!skb)
64162306a36Sopenharmony_ci		return false;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	bf = SKB_CB_ATHBUF(skb);
64462306a36Sopenharmony_ci	BUG_ON(!bf);
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
64762306a36Sopenharmony_ci				common->rx_bufsize, DMA_FROM_DEVICE);
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	ret = ath9k_hw_process_rxdesc_edma(ah, rs, skb->data);
65062306a36Sopenharmony_ci	if (ret == -EINPROGRESS) {
65162306a36Sopenharmony_ci		/*let device gain the buffer again*/
65262306a36Sopenharmony_ci		dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
65362306a36Sopenharmony_ci				common->rx_bufsize, DMA_FROM_DEVICE);
65462306a36Sopenharmony_ci		return false;
65562306a36Sopenharmony_ci	}
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	__skb_unlink(skb, &rx_edma->rx_fifo);
65862306a36Sopenharmony_ci	if (ret == -EINVAL) {
65962306a36Sopenharmony_ci		/* corrupt descriptor, skip this one and the following one */
66062306a36Sopenharmony_ci		list_add_tail(&bf->list, &sc->rx.rxbuf);
66162306a36Sopenharmony_ci		ath_rx_edma_buf_link(sc, qtype);
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci		skb = skb_peek(&rx_edma->rx_fifo);
66462306a36Sopenharmony_ci		if (skb) {
66562306a36Sopenharmony_ci			bf = SKB_CB_ATHBUF(skb);
66662306a36Sopenharmony_ci			BUG_ON(!bf);
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci			__skb_unlink(skb, &rx_edma->rx_fifo);
66962306a36Sopenharmony_ci			list_add_tail(&bf->list, &sc->rx.rxbuf);
67062306a36Sopenharmony_ci			ath_rx_edma_buf_link(sc, qtype);
67162306a36Sopenharmony_ci		}
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci		bf = NULL;
67462306a36Sopenharmony_ci	}
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	*dest = bf;
67762306a36Sopenharmony_ci	return true;
67862306a36Sopenharmony_ci}
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_cistatic struct ath_rxbuf *ath_edma_get_next_rx_buf(struct ath_softc *sc,
68162306a36Sopenharmony_ci						struct ath_rx_status *rs,
68262306a36Sopenharmony_ci						enum ath9k_rx_qtype qtype)
68362306a36Sopenharmony_ci{
68462306a36Sopenharmony_ci	struct ath_rxbuf *bf = NULL;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	while (ath_edma_get_buffers(sc, qtype, rs, &bf)) {
68762306a36Sopenharmony_ci		if (!bf)
68862306a36Sopenharmony_ci			continue;
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci		return bf;
69162306a36Sopenharmony_ci	}
69262306a36Sopenharmony_ci	return NULL;
69362306a36Sopenharmony_ci}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_cistatic struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc,
69662306a36Sopenharmony_ci					   struct ath_rx_status *rs)
69762306a36Sopenharmony_ci{
69862306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
69962306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
70062306a36Sopenharmony_ci	struct ath_desc *ds;
70162306a36Sopenharmony_ci	struct ath_rxbuf *bf;
70262306a36Sopenharmony_ci	int ret;
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	if (list_empty(&sc->rx.rxbuf)) {
70562306a36Sopenharmony_ci		sc->rx.rxlink = NULL;
70662306a36Sopenharmony_ci		return NULL;
70762306a36Sopenharmony_ci	}
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list);
71062306a36Sopenharmony_ci	if (bf == sc->rx.buf_hold)
71162306a36Sopenharmony_ci		return NULL;
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	ds = bf->bf_desc;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	/*
71662306a36Sopenharmony_ci	 * Must provide the virtual address of the current
71762306a36Sopenharmony_ci	 * descriptor, the physical address, and the virtual
71862306a36Sopenharmony_ci	 * address of the next descriptor in the h/w chain.
71962306a36Sopenharmony_ci	 * This allows the HAL to look ahead to see if the
72062306a36Sopenharmony_ci	 * hardware is done with a descriptor by checking the
72162306a36Sopenharmony_ci	 * done bit in the following descriptor and the address
72262306a36Sopenharmony_ci	 * of the current descriptor the DMA engine is working
72362306a36Sopenharmony_ci	 * on.  All this is necessary because of our use of
72462306a36Sopenharmony_ci	 * a self-linked list to avoid rx overruns.
72562306a36Sopenharmony_ci	 */
72662306a36Sopenharmony_ci	ret = ath9k_hw_rxprocdesc(ah, ds, rs);
72762306a36Sopenharmony_ci	if (ret == -EINPROGRESS) {
72862306a36Sopenharmony_ci		struct ath_rx_status trs;
72962306a36Sopenharmony_ci		struct ath_rxbuf *tbf;
73062306a36Sopenharmony_ci		struct ath_desc *tds;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci		memset(&trs, 0, sizeof(trs));
73362306a36Sopenharmony_ci		if (list_is_last(&bf->list, &sc->rx.rxbuf)) {
73462306a36Sopenharmony_ci			sc->rx.rxlink = NULL;
73562306a36Sopenharmony_ci			return NULL;
73662306a36Sopenharmony_ci		}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci		tbf = list_entry(bf->list.next, struct ath_rxbuf, list);
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci		/*
74162306a36Sopenharmony_ci		 * On some hardware the descriptor status words could
74262306a36Sopenharmony_ci		 * get corrupted, including the done bit. Because of
74362306a36Sopenharmony_ci		 * this, check if the next descriptor's done bit is
74462306a36Sopenharmony_ci		 * set or not.
74562306a36Sopenharmony_ci		 *
74662306a36Sopenharmony_ci		 * If the next descriptor's done bit is set, the current
74762306a36Sopenharmony_ci		 * descriptor has been corrupted. Force s/w to discard
74862306a36Sopenharmony_ci		 * this descriptor and continue...
74962306a36Sopenharmony_ci		 */
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci		tds = tbf->bf_desc;
75262306a36Sopenharmony_ci		ret = ath9k_hw_rxprocdesc(ah, tds, &trs);
75362306a36Sopenharmony_ci		if (ret == -EINPROGRESS)
75462306a36Sopenharmony_ci			return NULL;
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci		/*
75762306a36Sopenharmony_ci		 * Re-check previous descriptor, in case it has been filled
75862306a36Sopenharmony_ci		 * in the mean time.
75962306a36Sopenharmony_ci		 */
76062306a36Sopenharmony_ci		ret = ath9k_hw_rxprocdesc(ah, ds, rs);
76162306a36Sopenharmony_ci		if (ret == -EINPROGRESS) {
76262306a36Sopenharmony_ci			/*
76362306a36Sopenharmony_ci			 * mark descriptor as zero-length and set the 'more'
76462306a36Sopenharmony_ci			 * flag to ensure that both buffers get discarded
76562306a36Sopenharmony_ci			 */
76662306a36Sopenharmony_ci			rs->rs_datalen = 0;
76762306a36Sopenharmony_ci			rs->rs_more = true;
76862306a36Sopenharmony_ci		}
76962306a36Sopenharmony_ci	}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	list_del(&bf->list);
77262306a36Sopenharmony_ci	if (!bf->bf_mpdu)
77362306a36Sopenharmony_ci		return bf;
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	/*
77662306a36Sopenharmony_ci	 * Synchronize the DMA transfer with CPU before
77762306a36Sopenharmony_ci	 * 1. accessing the frame
77862306a36Sopenharmony_ci	 * 2. requeueing the same buffer to h/w
77962306a36Sopenharmony_ci	 */
78062306a36Sopenharmony_ci	dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
78162306a36Sopenharmony_ci			common->rx_bufsize,
78262306a36Sopenharmony_ci			DMA_FROM_DEVICE);
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci	return bf;
78562306a36Sopenharmony_ci}
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_cistatic void ath9k_process_tsf(struct ath_rx_status *rs,
78862306a36Sopenharmony_ci			      struct ieee80211_rx_status *rxs,
78962306a36Sopenharmony_ci			      u64 tsf)
79062306a36Sopenharmony_ci{
79162306a36Sopenharmony_ci	u32 tsf_lower = tsf & 0xffffffff;
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	rxs->mactime = (tsf & ~0xffffffffULL) | rs->rs_tstamp;
79462306a36Sopenharmony_ci	if (rs->rs_tstamp > tsf_lower &&
79562306a36Sopenharmony_ci	    unlikely(rs->rs_tstamp - tsf_lower > 0x10000000))
79662306a36Sopenharmony_ci		rxs->mactime -= 0x100000000ULL;
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	if (rs->rs_tstamp < tsf_lower &&
79962306a36Sopenharmony_ci	    unlikely(tsf_lower - rs->rs_tstamp > 0x10000000))
80062306a36Sopenharmony_ci		rxs->mactime += 0x100000000ULL;
80162306a36Sopenharmony_ci}
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci/*
80462306a36Sopenharmony_ci * For Decrypt or Demic errors, we only mark packet status here and always push
80562306a36Sopenharmony_ci * up the frame up to let mac80211 handle the actual error case, be it no
80662306a36Sopenharmony_ci * decryption key or real decryption error. This let us keep statistics there.
80762306a36Sopenharmony_ci */
80862306a36Sopenharmony_cistatic int ath9k_rx_skb_preprocess(struct ath_softc *sc,
80962306a36Sopenharmony_ci				   struct sk_buff *skb,
81062306a36Sopenharmony_ci				   struct ath_rx_status *rx_stats,
81162306a36Sopenharmony_ci				   struct ieee80211_rx_status *rx_status,
81262306a36Sopenharmony_ci				   bool *decrypt_error, u64 tsf)
81362306a36Sopenharmony_ci{
81462306a36Sopenharmony_ci	struct ieee80211_hw *hw = sc->hw;
81562306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
81662306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
81762306a36Sopenharmony_ci	struct ieee80211_hdr *hdr;
81862306a36Sopenharmony_ci	bool discard_current = sc->rx.discard_next;
81962306a36Sopenharmony_ci	bool is_phyerr;
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	/*
82262306a36Sopenharmony_ci	 * Discard corrupt descriptors which are marked in
82362306a36Sopenharmony_ci	 * ath_get_next_rx_buf().
82462306a36Sopenharmony_ci	 */
82562306a36Sopenharmony_ci	if (discard_current)
82662306a36Sopenharmony_ci		goto corrupt;
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	sc->rx.discard_next = false;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	/*
83162306a36Sopenharmony_ci	 * Discard zero-length packets and packets smaller than an ACK
83262306a36Sopenharmony_ci	 * which are not PHY_ERROR (short radar pulses have a length of 3)
83362306a36Sopenharmony_ci	 */
83462306a36Sopenharmony_ci	is_phyerr = rx_stats->rs_status & ATH9K_RXERR_PHY;
83562306a36Sopenharmony_ci	if (!rx_stats->rs_datalen ||
83662306a36Sopenharmony_ci	    (rx_stats->rs_datalen < 10 && !is_phyerr)) {
83762306a36Sopenharmony_ci		RX_STAT_INC(sc, rx_len_err);
83862306a36Sopenharmony_ci		goto corrupt;
83962306a36Sopenharmony_ci	}
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	/*
84262306a36Sopenharmony_ci	 * rs_status follows rs_datalen so if rs_datalen is too large
84362306a36Sopenharmony_ci	 * we can take a hint that hardware corrupted it, so ignore
84462306a36Sopenharmony_ci	 * those frames.
84562306a36Sopenharmony_ci	 */
84662306a36Sopenharmony_ci	if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) {
84762306a36Sopenharmony_ci		RX_STAT_INC(sc, rx_len_err);
84862306a36Sopenharmony_ci		goto corrupt;
84962306a36Sopenharmony_ci	}
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	/* Only use status info from the last fragment */
85262306a36Sopenharmony_ci	if (rx_stats->rs_more)
85362306a36Sopenharmony_ci		return 0;
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	/*
85662306a36Sopenharmony_ci	 * Return immediately if the RX descriptor has been marked
85762306a36Sopenharmony_ci	 * as corrupt based on the various error bits.
85862306a36Sopenharmony_ci	 *
85962306a36Sopenharmony_ci	 * This is different from the other corrupt descriptor
86062306a36Sopenharmony_ci	 * condition handled above.
86162306a36Sopenharmony_ci	 */
86262306a36Sopenharmony_ci	if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC)
86362306a36Sopenharmony_ci		goto corrupt;
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	ath9k_process_tsf(rx_stats, rx_status, tsf);
86862306a36Sopenharmony_ci	ath_debug_stat_rx(sc, rx_stats);
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	/*
87162306a36Sopenharmony_ci	 * Process PHY errors and return so that the packet
87262306a36Sopenharmony_ci	 * can be dropped.
87362306a36Sopenharmony_ci	 */
87462306a36Sopenharmony_ci	if (rx_stats->rs_status & ATH9K_RXERR_PHY) {
87562306a36Sopenharmony_ci		/*
87662306a36Sopenharmony_ci		 * DFS and spectral are mutually exclusive
87762306a36Sopenharmony_ci		 *
87862306a36Sopenharmony_ci		 * Since some chips use PHYERR_RADAR as indication for both, we
87962306a36Sopenharmony_ci		 * need to double check which feature is enabled to prevent
88062306a36Sopenharmony_ci		 * feeding spectral or dfs-detector with wrong frames.
88162306a36Sopenharmony_ci		 */
88262306a36Sopenharmony_ci		if (hw->conf.radar_enabled) {
88362306a36Sopenharmony_ci			ath9k_dfs_process_phyerr(sc, hdr, rx_stats,
88462306a36Sopenharmony_ci						 rx_status->mactime);
88562306a36Sopenharmony_ci		} else if (sc->spec_priv.spectral_mode != SPECTRAL_DISABLED &&
88662306a36Sopenharmony_ci			   ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats,
88762306a36Sopenharmony_ci					       rx_status->mactime)) {
88862306a36Sopenharmony_ci			RX_STAT_INC(sc, rx_spectral);
88962306a36Sopenharmony_ci		}
89062306a36Sopenharmony_ci		return -EINVAL;
89162306a36Sopenharmony_ci	}
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	/*
89462306a36Sopenharmony_ci	 * everything but the rate is checked here, the rate check is done
89562306a36Sopenharmony_ci	 * separately to avoid doing two lookups for a rate for each frame.
89662306a36Sopenharmony_ci	 */
89762306a36Sopenharmony_ci	spin_lock_bh(&sc->chan_lock);
89862306a36Sopenharmony_ci	if (!ath9k_cmn_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error,
89962306a36Sopenharmony_ci				 sc->cur_chan->rxfilter)) {
90062306a36Sopenharmony_ci		spin_unlock_bh(&sc->chan_lock);
90162306a36Sopenharmony_ci		return -EINVAL;
90262306a36Sopenharmony_ci	}
90362306a36Sopenharmony_ci	spin_unlock_bh(&sc->chan_lock);
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	if (ath_is_mybeacon(common, hdr)) {
90662306a36Sopenharmony_ci		RX_STAT_INC(sc, rx_beacons);
90762306a36Sopenharmony_ci		rx_stats->is_mybeacon = true;
90862306a36Sopenharmony_ci	}
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	/*
91162306a36Sopenharmony_ci	 * This shouldn't happen, but have a safety check anyway.
91262306a36Sopenharmony_ci	 */
91362306a36Sopenharmony_ci	if (WARN_ON(!ah->curchan))
91462306a36Sopenharmony_ci		return -EINVAL;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	if (ath9k_cmn_process_rate(common, hw, rx_stats, rx_status)) {
91762306a36Sopenharmony_ci		/*
91862306a36Sopenharmony_ci		 * No valid hardware bitrate found -- we should not get here
91962306a36Sopenharmony_ci		 * because hardware has already validated this frame as OK.
92062306a36Sopenharmony_ci		 */
92162306a36Sopenharmony_ci		ath_dbg(common, ANY, "unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
92262306a36Sopenharmony_ci			rx_stats->rs_rate);
92362306a36Sopenharmony_ci		RX_STAT_INC(sc, rx_rate_err);
92462306a36Sopenharmony_ci		return -EINVAL;
92562306a36Sopenharmony_ci	}
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	if (ath9k_is_chanctx_enabled()) {
92862306a36Sopenharmony_ci		if (rx_stats->is_mybeacon)
92962306a36Sopenharmony_ci			ath_chanctx_beacon_recv_ev(sc,
93062306a36Sopenharmony_ci					   ATH_CHANCTX_EVENT_BEACON_RECEIVED);
93162306a36Sopenharmony_ci	}
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status);
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci	rx_status->band = ah->curchan->chan->band;
93662306a36Sopenharmony_ci	rx_status->freq = ah->curchan->chan->center_freq;
93762306a36Sopenharmony_ci	rx_status->antenna = rx_stats->rs_antenna;
93862306a36Sopenharmony_ci	rx_status->flag |= RX_FLAG_MACTIME_END;
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
94162306a36Sopenharmony_ci	if (ieee80211_is_data_present(hdr->frame_control) &&
94262306a36Sopenharmony_ci	    !ieee80211_is_qos_nullfunc(hdr->frame_control))
94362306a36Sopenharmony_ci		sc->rx.num_pkts++;
94462306a36Sopenharmony_ci#endif
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	return 0;
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_cicorrupt:
94962306a36Sopenharmony_ci	sc->rx.discard_next = rx_stats->rs_more;
95062306a36Sopenharmony_ci	return -EINVAL;
95162306a36Sopenharmony_ci}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci/*
95462306a36Sopenharmony_ci * Run the LNA combining algorithm only in these cases:
95562306a36Sopenharmony_ci *
95662306a36Sopenharmony_ci * Standalone WLAN cards with both LNA/Antenna diversity
95762306a36Sopenharmony_ci * enabled in the EEPROM.
95862306a36Sopenharmony_ci *
95962306a36Sopenharmony_ci * WLAN+BT cards which are in the supported card list
96062306a36Sopenharmony_ci * in ath_pci_id_table and the user has loaded the
96162306a36Sopenharmony_ci * driver with "bt_ant_diversity" set to true.
96262306a36Sopenharmony_ci */
96362306a36Sopenharmony_cistatic void ath9k_antenna_check(struct ath_softc *sc,
96462306a36Sopenharmony_ci				struct ath_rx_status *rs)
96562306a36Sopenharmony_ci{
96662306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
96762306a36Sopenharmony_ci	struct ath9k_hw_capabilities *pCap = &ah->caps;
96862306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB))
97162306a36Sopenharmony_ci		return;
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	/*
97462306a36Sopenharmony_ci	 * Change the default rx antenna if rx diversity
97562306a36Sopenharmony_ci	 * chooses the other antenna 3 times in a row.
97662306a36Sopenharmony_ci	 */
97762306a36Sopenharmony_ci	if (sc->rx.defant != rs->rs_antenna) {
97862306a36Sopenharmony_ci		if (++sc->rx.rxotherant >= 3)
97962306a36Sopenharmony_ci			ath_setdefantenna(sc, rs->rs_antenna);
98062306a36Sopenharmony_ci	} else {
98162306a36Sopenharmony_ci		sc->rx.rxotherant = 0;
98262306a36Sopenharmony_ci	}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	if (pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV) {
98562306a36Sopenharmony_ci		if (common->bt_ant_diversity)
98662306a36Sopenharmony_ci			ath_ant_comb_scan(sc, rs);
98762306a36Sopenharmony_ci	} else {
98862306a36Sopenharmony_ci		ath_ant_comb_scan(sc, rs);
98962306a36Sopenharmony_ci	}
99062306a36Sopenharmony_ci}
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_cistatic void ath9k_apply_ampdu_details(struct ath_softc *sc,
99362306a36Sopenharmony_ci	struct ath_rx_status *rs, struct ieee80211_rx_status *rxs)
99462306a36Sopenharmony_ci{
99562306a36Sopenharmony_ci	if (rs->rs_isaggr) {
99662306a36Sopenharmony_ci		rxs->flag |= RX_FLAG_AMPDU_DETAILS | RX_FLAG_AMPDU_LAST_KNOWN;
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci		rxs->ampdu_reference = sc->rx.ampdu_ref;
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci		if (!rs->rs_moreaggr) {
100162306a36Sopenharmony_ci			rxs->flag |= RX_FLAG_AMPDU_IS_LAST;
100262306a36Sopenharmony_ci			sc->rx.ampdu_ref++;
100362306a36Sopenharmony_ci		}
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci		if (rs->rs_flags & ATH9K_RX_DELIM_CRC_PRE)
100662306a36Sopenharmony_ci			rxs->flag |= RX_FLAG_AMPDU_DELIM_CRC_ERROR;
100762306a36Sopenharmony_ci	}
100862306a36Sopenharmony_ci}
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_cistatic void ath_rx_count_airtime(struct ath_softc *sc,
101162306a36Sopenharmony_ci				 struct ath_rx_status *rs,
101262306a36Sopenharmony_ci				 struct sk_buff *skb)
101362306a36Sopenharmony_ci{
101462306a36Sopenharmony_ci	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
101562306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
101662306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
101762306a36Sopenharmony_ci	struct ieee80211_sta *sta;
101862306a36Sopenharmony_ci	struct ieee80211_rx_status *rxs;
101962306a36Sopenharmony_ci	const struct ieee80211_rate *rate;
102062306a36Sopenharmony_ci	bool is_sgi, is_40, is_sp;
102162306a36Sopenharmony_ci	int phy;
102262306a36Sopenharmony_ci	u16 len = rs->rs_datalen;
102362306a36Sopenharmony_ci	u32 airtime = 0;
102462306a36Sopenharmony_ci	u8 tidno;
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	if (!ieee80211_is_data(hdr->frame_control))
102762306a36Sopenharmony_ci		return;
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	rcu_read_lock();
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci	sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL);
103262306a36Sopenharmony_ci	if (!sta)
103362306a36Sopenharmony_ci		goto exit;
103462306a36Sopenharmony_ci	tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	rxs = IEEE80211_SKB_RXCB(skb);
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	is_sgi = !!(rxs->enc_flags & RX_ENC_FLAG_SHORT_GI);
103962306a36Sopenharmony_ci	is_40 = !!(rxs->bw == RATE_INFO_BW_40);
104062306a36Sopenharmony_ci	is_sp = !!(rxs->enc_flags & RX_ENC_FLAG_SHORTPRE);
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	if (!!(rxs->encoding == RX_ENC_HT)) {
104362306a36Sopenharmony_ci		/* MCS rates */
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci		airtime += ath_pkt_duration(sc, rxs->rate_idx, len,
104662306a36Sopenharmony_ci					is_40, is_sgi, is_sp);
104762306a36Sopenharmony_ci	} else {
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci		phy = IS_CCK_RATE(rs->rs_rate) ? WLAN_RC_PHY_CCK : WLAN_RC_PHY_OFDM;
105062306a36Sopenharmony_ci		rate = &common->sbands[rxs->band].bitrates[rxs->rate_idx];
105162306a36Sopenharmony_ci		airtime += ath9k_hw_computetxtime(ah, phy, rate->bitrate * 100,
105262306a36Sopenharmony_ci						len, rxs->rate_idx, is_sp);
105362306a36Sopenharmony_ci	}
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	ieee80211_sta_register_airtime(sta, tidno, 0, airtime);
105662306a36Sopenharmony_ciexit:
105762306a36Sopenharmony_ci	rcu_read_unlock();
105862306a36Sopenharmony_ci}
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ciint ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
106162306a36Sopenharmony_ci{
106262306a36Sopenharmony_ci	struct ath_rxbuf *bf;
106362306a36Sopenharmony_ci	struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb;
106462306a36Sopenharmony_ci	struct ieee80211_rx_status *rxs;
106562306a36Sopenharmony_ci	struct ath_hw *ah = sc->sc_ah;
106662306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
106762306a36Sopenharmony_ci	struct ieee80211_hw *hw = sc->hw;
106862306a36Sopenharmony_ci	int retval;
106962306a36Sopenharmony_ci	struct ath_rx_status rs;
107062306a36Sopenharmony_ci	enum ath9k_rx_qtype qtype;
107162306a36Sopenharmony_ci	bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
107262306a36Sopenharmony_ci	int dma_type;
107362306a36Sopenharmony_ci	u64 tsf = 0;
107462306a36Sopenharmony_ci	unsigned long flags;
107562306a36Sopenharmony_ci	dma_addr_t new_buf_addr;
107662306a36Sopenharmony_ci	unsigned int budget = 512;
107762306a36Sopenharmony_ci	struct ieee80211_hdr *hdr;
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	if (edma)
108062306a36Sopenharmony_ci		dma_type = DMA_BIDIRECTIONAL;
108162306a36Sopenharmony_ci	else
108262306a36Sopenharmony_ci		dma_type = DMA_FROM_DEVICE;
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	tsf = ath9k_hw_gettsf64(ah);
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	do {
108962306a36Sopenharmony_ci		bool decrypt_error = false;
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci		memset(&rs, 0, sizeof(rs));
109262306a36Sopenharmony_ci		if (edma)
109362306a36Sopenharmony_ci			bf = ath_edma_get_next_rx_buf(sc, &rs, qtype);
109462306a36Sopenharmony_ci		else
109562306a36Sopenharmony_ci			bf = ath_get_next_rx_buf(sc, &rs);
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci		if (!bf)
109862306a36Sopenharmony_ci			break;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci		skb = bf->bf_mpdu;
110162306a36Sopenharmony_ci		if (!skb)
110262306a36Sopenharmony_ci			continue;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci		/*
110562306a36Sopenharmony_ci		 * Take frame header from the first fragment and RX status from
110662306a36Sopenharmony_ci		 * the last one.
110762306a36Sopenharmony_ci		 */
110862306a36Sopenharmony_ci		if (sc->rx.frag)
110962306a36Sopenharmony_ci			hdr_skb = sc->rx.frag;
111062306a36Sopenharmony_ci		else
111162306a36Sopenharmony_ci			hdr_skb = skb;
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci		rxs = IEEE80211_SKB_RXCB(hdr_skb);
111462306a36Sopenharmony_ci		memset(rxs, 0, sizeof(struct ieee80211_rx_status));
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ci		retval = ath9k_rx_skb_preprocess(sc, hdr_skb, &rs, rxs,
111762306a36Sopenharmony_ci						 &decrypt_error, tsf);
111862306a36Sopenharmony_ci		if (retval)
111962306a36Sopenharmony_ci			goto requeue_drop_frag;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci		/* Ensure we always have an skb to requeue once we are done
112262306a36Sopenharmony_ci		 * processing the current buffer's skb */
112362306a36Sopenharmony_ci		requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC);
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci		/* If there is no memory we ignore the current RX'd frame,
112662306a36Sopenharmony_ci		 * tell hardware it can give us a new frame using the old
112762306a36Sopenharmony_ci		 * skb and put it at the tail of the sc->rx.rxbuf list for
112862306a36Sopenharmony_ci		 * processing. */
112962306a36Sopenharmony_ci		if (!requeue_skb) {
113062306a36Sopenharmony_ci			RX_STAT_INC(sc, rx_oom_err);
113162306a36Sopenharmony_ci			goto requeue_drop_frag;
113262306a36Sopenharmony_ci		}
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci		/* We will now give hardware our shiny new allocated skb */
113562306a36Sopenharmony_ci		new_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
113662306a36Sopenharmony_ci					      common->rx_bufsize, dma_type);
113762306a36Sopenharmony_ci		if (unlikely(dma_mapping_error(sc->dev, new_buf_addr))) {
113862306a36Sopenharmony_ci			dev_kfree_skb_any(requeue_skb);
113962306a36Sopenharmony_ci			goto requeue_drop_frag;
114062306a36Sopenharmony_ci		}
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci		/* Unmap the frame */
114362306a36Sopenharmony_ci		dma_unmap_single(sc->dev, bf->bf_buf_addr,
114462306a36Sopenharmony_ci				 common->rx_bufsize, dma_type);
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci		bf->bf_mpdu = requeue_skb;
114762306a36Sopenharmony_ci		bf->bf_buf_addr = new_buf_addr;
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci		skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len);
115062306a36Sopenharmony_ci		if (ah->caps.rx_status_len)
115162306a36Sopenharmony_ci			skb_pull(skb, ah->caps.rx_status_len);
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci		if (!rs.rs_more)
115462306a36Sopenharmony_ci			ath9k_cmn_rx_skb_postprocess(common, hdr_skb, &rs,
115562306a36Sopenharmony_ci						     rxs, decrypt_error);
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci		if (rs.rs_more) {
115862306a36Sopenharmony_ci			RX_STAT_INC(sc, rx_frags);
115962306a36Sopenharmony_ci			/*
116062306a36Sopenharmony_ci			 * rs_more indicates chained descriptors which can be
116162306a36Sopenharmony_ci			 * used to link buffers together for a sort of
116262306a36Sopenharmony_ci			 * scatter-gather operation.
116362306a36Sopenharmony_ci			 */
116462306a36Sopenharmony_ci			if (sc->rx.frag) {
116562306a36Sopenharmony_ci				/* too many fragments - cannot handle frame */
116662306a36Sopenharmony_ci				dev_kfree_skb_any(sc->rx.frag);
116762306a36Sopenharmony_ci				dev_kfree_skb_any(skb);
116862306a36Sopenharmony_ci				RX_STAT_INC(sc, rx_too_many_frags_err);
116962306a36Sopenharmony_ci				skb = NULL;
117062306a36Sopenharmony_ci			}
117162306a36Sopenharmony_ci			sc->rx.frag = skb;
117262306a36Sopenharmony_ci			goto requeue;
117362306a36Sopenharmony_ci		}
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci		if (sc->rx.frag) {
117662306a36Sopenharmony_ci			int space = skb->len - skb_tailroom(hdr_skb);
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci			if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) {
117962306a36Sopenharmony_ci				dev_kfree_skb(skb);
118062306a36Sopenharmony_ci				RX_STAT_INC(sc, rx_oom_err);
118162306a36Sopenharmony_ci				goto requeue_drop_frag;
118262306a36Sopenharmony_ci			}
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci			sc->rx.frag = NULL;
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci			skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len),
118762306a36Sopenharmony_ci						  skb->len);
118862306a36Sopenharmony_ci			dev_kfree_skb_any(skb);
118962306a36Sopenharmony_ci			skb = hdr_skb;
119062306a36Sopenharmony_ci		}
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci		if (rxs->flag & RX_FLAG_MMIC_STRIPPED)
119362306a36Sopenharmony_ci			skb_trim(skb, skb->len - 8);
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci		spin_lock_irqsave(&sc->sc_pm_lock, flags);
119662306a36Sopenharmony_ci		if ((sc->ps_flags & (PS_WAIT_FOR_BEACON |
119762306a36Sopenharmony_ci				     PS_WAIT_FOR_CAB |
119862306a36Sopenharmony_ci				     PS_WAIT_FOR_PSPOLL_DATA)) ||
119962306a36Sopenharmony_ci		    ath9k_check_auto_sleep(sc))
120062306a36Sopenharmony_ci			ath_rx_ps(sc, skb, rs.is_mybeacon);
120162306a36Sopenharmony_ci		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci		ath9k_antenna_check(sc, &rs);
120462306a36Sopenharmony_ci		ath9k_apply_ampdu_details(sc, &rs, rxs);
120562306a36Sopenharmony_ci		ath_debug_rate_stats(sc, &rs, skb);
120662306a36Sopenharmony_ci		ath_rx_count_airtime(sc, &rs, skb);
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci		hdr = (struct ieee80211_hdr *)skb->data;
120962306a36Sopenharmony_ci		if (ieee80211_is_ack(hdr->frame_control))
121062306a36Sopenharmony_ci			ath_dynack_sample_ack_ts(sc->sc_ah, skb, rs.rs_tstamp);
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci		ieee80211_rx(hw, skb);
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_cirequeue_drop_frag:
121562306a36Sopenharmony_ci		if (sc->rx.frag) {
121662306a36Sopenharmony_ci			dev_kfree_skb_any(sc->rx.frag);
121762306a36Sopenharmony_ci			sc->rx.frag = NULL;
121862306a36Sopenharmony_ci		}
121962306a36Sopenharmony_cirequeue:
122062306a36Sopenharmony_ci		list_add_tail(&bf->list, &sc->rx.rxbuf);
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_ci		if (!edma) {
122362306a36Sopenharmony_ci			ath_rx_buf_relink(sc, bf, flush);
122462306a36Sopenharmony_ci			if (!flush)
122562306a36Sopenharmony_ci				ath9k_hw_rxena(ah);
122662306a36Sopenharmony_ci		} else if (!flush) {
122762306a36Sopenharmony_ci			ath_rx_edma_buf_link(sc, qtype);
122862306a36Sopenharmony_ci		}
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci		if (!budget--)
123162306a36Sopenharmony_ci			break;
123262306a36Sopenharmony_ci	} while (1);
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	if (!(ah->imask & ATH9K_INT_RXEOL)) {
123562306a36Sopenharmony_ci		ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
123662306a36Sopenharmony_ci		ath9k_hw_set_interrupts(ah);
123762306a36Sopenharmony_ci	}
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci	return 0;
124062306a36Sopenharmony_ci}
1241