/*
* Copyright (c) 2008 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Implementation of receive path.
*/
#include "core.h"
/*
* Setup and link descriptors.
*
* 11N: we can no longer afford to self link the last descriptor.
* MAC acknowledges BA status as long as it copies frames to host
* buffer (or rx fifo). This can incorrectly acknowledge packets
* to a sender if last desc is self-linked.
*
* NOTE: Caller should hold the rxbuf lock.
*/
static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
{
struct ath_hal *ah = sc->sc_ah;
struct ath_desc *ds;
struct sk_buff *skb;
ATH_RXBUF_RESET(bf);
ds = bf->bf_desc;
ds->ds_link = 0; /* link to null */
ds->ds_data = bf->bf_buf_addr;
/* XXX For RADAR?
* virtual addr of the beginning of the buffer. */
skb = bf->bf_mpdu;
ASSERT(skb != NULL);
ds->ds_vdata = skb->data;
/* setup rx descriptors. The sc_rxbufsize here tells the harware
* how much data it can DMA to us and that we are prepared
* to process */
ath9k_hw_setuprxdesc(ah,
ds,
sc->sc_rxbufsize,
0);
if (sc->sc_rxlink == NULL)
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
else
*sc->sc_rxlink = bf->bf_daddr;
sc->sc_rxlink = &ds->ds_link;
ath9k_hw_rxena(ah);
}
/* Process received BAR frame */
static int ath_bar_rx(struct ath_softc *sc,
struct ath_node *an,
struct sk_buff *skb)
{
struct ieee80211_bar *bar;
struct ath_arx_tid *rxtid;
struct sk_buff *tskb;
struct ath_recv_status *rx_status;
int tidno, index, cindex;
u16 seqno;
/* look at BAR contents */
bar = (struct ieee80211_bar *)skb->data;
tidno = (le16_to_cpu(bar->control) & IEEE80211_BAR_CTL_TID_M)
>> IEEE80211_BAR_CTL_TID_S;
seqno = le16_to_cpu(bar->start_seq_num) >> IEEE80211_SEQ_SEQ_SHIFT;
/* process BAR - indicate all pending RX frames till the BAR seqno */
rxtid = &an->an_aggr.rx.tid[tidno];
spin_lock_bh(&rxtid->tidlock);
/* get relative index */
inde