/*
* Copyright (c) 2008-2009 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.
*/
#include "ath9k.h"
#include "ar9003_mac.h"
#define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb))
static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
{
return sc->ps_enabled &&
(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP);
}
static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,
struct ieee80211_hdr *hdr)
{
struct ieee80211_hw *hw = sc->pri_wiphy->hw;
int i;
spin_lock_bh(&sc->wiphy_lock);
for (i = 0; i < sc->num_sec_wiphy; i++) {
struct ath_wiphy *aphy = sc->sec_wiphy[i];
if (aphy == NULL)
continue;
if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr)
== 0) {
hw = aphy->hw;
break;
}
}
spin_unlock_bh(&sc->wiphy_lock);
return hw;
}
/*
* 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.
*/
static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(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;
/* virtual addr of the beginning of the buffer. */
skb = bf->bf_mpdu;
BUG_ON(skb == NULL);
ds->ds_vdata = skb->data;
/*
* setup rx descriptors. The rx_bufsize here tells the hardware
* how much data it can DMA to us and that we are prepared
* to process
*/
ath9k_hw_setuprxdesc(ah, ds,
common->rx_bufsize,
0);
if (sc->rx.rxlink == NULL)
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
else
*sc->rx.rxlink = bf->bf_daddr;
sc->rx.rxlink = &ds->ds_link;
ath9k_hw_rxena(ah);
}
static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
{
/* XXX block beacon interrupts */
ath9k_hw_setantenna(sc->sc_ah, antenna);
sc->rx.