Commit dfef948e authored by David S. Miller's avatar David S. Miller
Browse files
parents ea31ba35 c85e9d77
......@@ -121,6 +121,14 @@ static struct fwentry firmwares[] = {
[BOARD_505A] = { "atmel_at76c505a-rfmd2958.bin" },
[BOARD_505AMX] = { "atmel_at76c505amx-rfmd.bin" },
};
MODULE_FIRMWARE("atmel_at76c503-i3861.bin");
MODULE_FIRMWARE("atmel_at76c503-i3863.bin");
MODULE_FIRMWARE("atmel_at76c503-rfmd.bin");
MODULE_FIRMWARE("atmel_at76c503-rfmd-acc.bin");
MODULE_FIRMWARE("atmel_at76c505-rfmd.bin");
MODULE_FIRMWARE("atmel_at76c505-rfmd2958.bin");
MODULE_FIRMWARE("atmel_at76c505a-rfmd2958.bin");
MODULE_FIRMWARE("atmel_at76c505amx-rfmd.bin");
#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops)
......@@ -524,20 +532,6 @@ static char *hex2str(void *buf, int len)
return ret;
}
#define MAC2STR_BUFFERS 4
static inline char *mac2str(u8 *mac)
{
static atomic_t a = ATOMIC_INIT(0);
static char bufs[MAC2STR_BUFFERS][6 * 3];
char *str;
str = bufs[atomic_inc_return(&a) & (MAC2STR_BUFFERS - 1)];
sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return str;
}
/* LED trigger */
static int tx_activity;
static void at76_ledtrig_tx_timerfunc(unsigned long data);
......@@ -973,13 +967,13 @@ static void at76_dump_mib_mac_addr(struct at76_priv *priv)
goto exit;
}
at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: mac_addr %s res 0x%x 0x%x",
at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: mac_addr %pM res 0x%x 0x%x",
wiphy_name(priv->hw->wiphy),
mac2str(m->mac_addr), m->res[0], m->res[1]);
m->mac_addr, m->res[0], m->res[1]);
for (i = 0; i < ARRAY_SIZE(m->group_addr); i++)
at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: group addr %d: %s, "
at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: group addr %d: %pM, "
"status %d", wiphy_name(priv->hw->wiphy), i,
mac2str(m->group_addr[i]), m->group_addr_status[i]);
m->group_addr[i], m->group_addr_status[i]);
exit:
kfree(m);
}
......@@ -1042,7 +1036,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
at76_dbg(DBG_MIB, "%s: MIB MAC_MGMT: beacon_period %d CFP_max_duration "
"%d medium_occupancy_limit %d station_id 0x%x ATIM_window %d "
"CFP_mode %d privacy_opt_impl %d DTIM_period %d CFP_period %d "
"current_bssid %s current_essid %s current_bss_type %d "
"current_bssid %pM current_essid %s current_bss_type %d "
"pm_mode %d ibss_change %d res %d "
"multi_domain_capability_implemented %d "
"international_roaming %d country_string %.3s",
......@@ -1051,7 +1045,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
le16_to_cpu(m->medium_occupancy_limit),
le16_to_cpu(m->station_id), le16_to_cpu(m->ATIM_window),
m->CFP_mode, m->privacy_option_implemented, m->DTIM_period,
m->CFP_period, mac2str(m->current_bssid),
m->CFP_period, m->current_bssid,
hex2str(m->current_essid, IW_ESSID_MAX_SIZE),
m->current_bss_type, m->power_mgmt_mode, m->ibss_change,
m->res, m->multi_domain_capability_implemented,
......@@ -1080,7 +1074,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
"cwmin %d cwmax %d short_retry_time %d long_retry_time %d "
"scan_type %d scan_channel %d probe_delay %u "
"min_channel_time %d max_channel_time %d listen_int %d "
"desired_ssid %s desired_bssid %s desired_bsstype %d",
"desired_ssid %s desired_bssid %pM desired_bsstype %d",
wiphy_name(priv->hw->wiphy),
le32_to_cpu(m->max_tx_msdu_lifetime),
le32_to_cpu(m->max_rx_lifetime),
......@@ -1092,7 +1086,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
le16_to_cpu(m->max_channel_time),
le16_to_cpu(m->listen_interval),
hex2str(m->desired_ssid, IW_ESSID_MAX_SIZE),
mac2str(m->desired_bssid), m->desired_bsstype);
m->desired_bssid, m->desired_bsstype);
exit:
kfree(m);
}
......@@ -1194,6 +1188,9 @@ static int at76_start_monitor(struct at76_priv *priv)
scan.channel = priv->channel;
scan.scan_type = SCAN_TYPE_PASSIVE;
scan.international_scan = 0;
scan.min_channel_time = cpu_to_le16(priv->scan_min_time);
scan.max_channel_time = cpu_to_le16(priv->scan_max_time);
scan.probe_delay = cpu_to_le16(0);
ret = at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
if (ret >= 0)
......@@ -2284,9 +2281,9 @@ static int at76_init_new_device(struct at76_priv *priv,
priv->mac80211_registered = 1;
printk(KERN_INFO "%s: USB %s, MAC %s, firmware %d.%d.%d-%d\n",
printk(KERN_INFO "%s: USB %s, MAC %pM, firmware %d.%d.%d-%d\n",
wiphy_name(priv->hw->wiphy),
dev_name(&interface->dev), mac2str(priv->mac_addr),
dev_name(&interface->dev), priv->mac_addr,
priv->fw_version.major, priv->fw_version.minor,
priv->fw_version.patch, priv->fw_version.build);
printk(KERN_INFO "%s: regulatory domain 0x%02x: %s\n",
......
......@@ -21,8 +21,28 @@
#include <linux/if_ether.h>
#include <net/mac80211.h>
/*
* The key cache is used for h/w cipher state and also for
* tracking station state such as the current tx antenna.
* We also setup a mapping table between key cache slot indices
* and station state to short-circuit node lookups on rx.
* Different parts have different size key caches. We handle
* up to ATH_KEYMAX entries (could dynamically allocate state).
*/
#define ATH_KEYMAX 128 /* max key cache size we handle */
static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct ath_ani {
bool caldone;
int16_t noise_floor;
unsigned int longcal_timer;
unsigned int shortcal_timer;
unsigned int resetcal_timer;
unsigned int checkani_timer;
struct timer_list timer;
};
enum ath_device_state {
ATH_HW_UNAVAILABLE,
ATH_HW_INITIALIZED,
......@@ -66,6 +86,8 @@ struct ath_common {
int debug_mask;
enum ath_device_state state;
struct ath_ani ani;
u16 cachelsz;
u16 curaid;
u8 macaddr[ETH_ALEN];
......@@ -75,6 +97,12 @@ struct ath_common {
u8 tx_chainmask;
u8 rx_chainmask;
u32 rx_bufsize;
u32 keymax;
DECLARE_BITMAP(keymap, ATH_KEYMAX);
u8 splitmic;
struct ath_regulatory regulatory;
const struct ath_ops *ops;
const struct ath_bus_ops *bus_ops;
......
......@@ -323,10 +323,13 @@ static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
static inline void ath5k_rxbuf_free(struct ath5k_softc *sc,
struct ath5k_buf *bf)
{
struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
BUG_ON(!bf);
if (!bf->skb)
return;
pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize,
PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(bf->skb);
bf->skb = NULL;
......@@ -1181,17 +1184,18 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
* fake physical layer header at the start.
*/
skb = ath_rxbuf_alloc(common,
sc->rxbufsize + common->cachelsz - 1,
common->rx_bufsize,
GFP_ATOMIC);
if (!skb) {
ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
sc->rxbufsize + common->cachelsz - 1);
common->rx_bufsize);
return NULL;
}
*skb_addr = pci_map_single(sc->pdev,
skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
skb->data, common->rx_bufsize,
PCI_DMA_FROMDEVICE);
if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
dev_kfree_skb(skb);
......@@ -1631,10 +1635,10 @@ ath5k_rx_start(struct ath5k_softc *sc)
struct ath5k_buf *bf;
int ret;
sc->rxbufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz);
common->rx_bufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz);
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
common->cachelsz, sc->rxbufsize);
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n",
common->cachelsz, common->rx_bufsize);
spin_lock_bh(&sc->rxbuflock);
sc->rxlink = NULL;
......@@ -1679,6 +1683,8 @@ static unsigned int
ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
struct sk_buff *skb, struct ath5k_rx_status *rs)
{
struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
struct ieee80211_hdr *hdr = (void *)skb->data;
unsigned int keyix, hlen;
......@@ -1695,7 +1701,7 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
skb->len >= hlen + 4) {
keyix = skb->data[hlen + 3] >> 6;
if (test_bit(keyix, sc->keymap))
if (test_bit(keyix, common->keymap))
return RX_FLAG_DECRYPTED;
}
......@@ -1769,6 +1775,8 @@ ath5k_tasklet_rx(unsigned long data)
struct sk_buff *skb, *next_skb;
dma_addr_t next_skb_addr;
struct ath5k_softc *sc = (void *)data;
struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
struct ath5k_buf *bf;
struct ath5k_desc *ds;
int ret;
......@@ -1846,7 +1854,7 @@ accept:
if (!next_skb)
goto next;
pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize,
PCI_DMA_FROMDEVICE);
skb_put(skb, rs.rs_datalen);
......@@ -3032,6 +3040,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_key_conf *key)
{
struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
int ret = 0;
if (modparam_nohwcrypt)
......@@ -3064,14 +3074,14 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
ATH5K_ERR(sc, "can't set the key\n");
goto unlock;
}
__set_bit(key->keyidx, sc->keymap);
__set_bit(key->keyidx, common->keymap);
key->hw_key_idx = key->keyidx;
key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV |
IEEE80211_KEY_FLAG_GENERATE_MMIC);
break;
case DISABLE_KEY:
ath5k_hw_reset_key(sc->ah, key->keyidx);
__clear_bit(key->keyidx, sc->keymap);
__clear_bit(key->keyidx, common->keymap);
break;
default:
ret = -EINVAL;
......
......@@ -153,8 +153,6 @@ struct ath5k_softc {
enum ath5k_int imask; /* interrupt mask copy */
DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */
u8 bssidmask[ETH_ALEN];
unsigned int led_pin, /* GPIO pin for driving LED */
......
......@@ -3025,8 +3025,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
return -EINVAL;
}
if (txpower == 0)
txpower = AR5K_TUNE_DEFAULT_TXPOWER;
/* Reset TX power values */
memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
......
config ATH9K_HW
tristate
config ATH9K_COMMON
tristate
config ATH9K
tristate "Atheros 802.11n wireless cards support"
......@@ -8,6 +10,7 @@ config ATH9K
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
select ATH9K_COMMON
---help---
This module adds support for wireless adapters based on
Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family
......
......@@ -23,3 +23,6 @@ ath9k_hw-y:= hw.o \
mac.o \
obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o
obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o
ath9k_common-y:= common.o
......@@ -19,14 +19,16 @@
#include <linux/etherdevice.h>
#include <linux/device.h>
#include <net/mac80211.h>
#include <linux/leds.h>
#include "hw.h"
#include "rc.h"
#include "debug.h"
#include "../ath.h"
#include "../debug.h"
#include "common.h"
/*
* Header for the ath9k.ko driver core *only* -- hw code nor any other driver
* should rely on this file or its contents.
*/
struct ath_node;
......@@ -99,18 +101,6 @@ enum buffer_type {
BUF_XRETRY = BIT(5),
};
struct ath_buf_state {
int bfs_nframes;
u16 bfs_al;
u16 bfs_frmlen;
int bfs_seqno;
int bfs_tidno;
int bfs_retries;
u8 bf_type;
u32 bfs_keyix;
enum ath9k_key_type bfs_keytype;
};
#define bf_nframes bf_state.bfs_nframes
#define bf_al bf_state.bfs_al
#define bf_frmlen bf_state.bfs_frmlen
......@@ -125,21 +115,6 @@ struct ath_buf_state {
#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY)
#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
struct ath_buf {
struct list_head list;
struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or
an aggregate) */
struct ath_buf *bf_next; /* next subframe in the aggregate */
struct sk_buff *bf_mpdu; /* enclosing frame structure */
struct ath_desc *bf_desc; /* virtual addr of desc */
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer */
bool bf_stale;
u16 bf_flags;
struct ath_buf_state bf_state;
dma_addr_t bf_dmacontext;
};
struct ath_descdma {
struct ath_desc *dd_desc;
dma_addr_t dd_desc_paddr;
......@@ -159,13 +134,9 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
#define ATH_MAX_ANTENNA 3
#define ATH_RXBUF 512
#define WME_NUM_TID 16
#define ATH_TXBUF 512
#define ATH_TXMAXTRY 13
#define ATH_MGT_TXMAXTRY 4
#define WME_BA_BMP_SIZE 64
#define WME_MAX_BA WME_BA_BMP_SIZE
#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
#define TID_TO_WME_AC(_tid) \
((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
......@@ -173,12 +144,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
(((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
WME_AC_VO)
#define WME_AC_BE 0
#define WME_AC_BK 1
#define WME_AC_VI 2
#define WME_AC_VO 3
#define WME_NUM_AC 4
#define ADDBA_EXCHANGE_ATTEMPTS 10
#define ATH_AGGR_DELIM_SZ 4
#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
......@@ -252,30 +217,6 @@ struct ath_txq {
#define AGGR_ADDBA_COMPLETE BIT(2)
#define AGGR_ADDBA_PROGRESS BIT(3)
struct ath_atx_tid {
struct list_head list;
struct list_head buf_q;
struct ath_node *an;
struct ath_atx_ac *ac;
struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];
u16 seq_start;
u16 seq_next;
u16 baw_size;
int tidno;
int baw_head; /* first un-acked tx buffer */
int baw_tail; /* next unused tx buffer slot */
int sched;
int paused;
u8 state;
};
struct ath_atx_ac {
int sched;
int qnum;
struct list_head list;
struct list_head tid_q;
};
struct ath_tx_control {
struct ath_txq *txq;
int if_id;
......@@ -286,29 +227,6 @@ struct ath_tx_control {
#define ATH_TX_XRETRY 0x02
#define ATH_TX_BAR 0x04
#define ATH_RSSI_LPF_LEN 10
#define RSSI_LPF_THRESHOLD -20
#define ATH_RSSI_EP_MULTIPLIER (1<<7)
#define ATH_EP_MUL(x, mul) ((x) * (mul))
#define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER))
#define ATH_LPF_RSSI(x, y, len) \
((x != ATH_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y))
#define ATH_RSSI_LPF(x, y) do { \
if ((y) >= RSSI_LPF_THRESHOLD) \
x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \
} while (0)
#define ATH_EP_RND(x, mul) \
((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
struct ath_node {
struct ath_softc *an_sc;
struct ath_atx_tid tid[WME_NUM_TID];
struct ath_atx_ac ac[WME_NUM_AC];
u16 maxampdu;
u8 mpdudensity;
int last_rssi;
};
struct ath_tx {
u16 seq_no;
u32 txqsetup;
......@@ -323,7 +241,6 @@ struct ath_rx {
u8 defant;
u8 rxotherant;
u32 *rxlink;
int bufsize;
unsigned int rxfilter;
spinlock_t rxflushlock;
spinlock_t rxbuflock;
......@@ -434,16 +351,6 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
struct ath_ani {
bool caldone;
int16_t noise_floor;
unsigned int longcal_timer;
unsigned int shortcal_timer;
unsigned int resetcal_timer;
unsigned int checkani_timer;
struct timer_list timer;
};
/* Defines the BT AR_BT_COEX_WGHT used */
enum ath_stomp_type {
ATH_BTCOEX_NO_STOMP,
......@@ -503,18 +410,7 @@ struct ath_led {
#define ATH_CHAN_MAX 255
#define IEEE80211_WEP_NKID 4 /* number of key ids */
/*
* The key cache is used for h/w cipher state and also for
* tracking station state such as the current tx antenna.
* We also setup a mapping table between key cache slot indices
* and station state to short-circuit node lookups on rx.
* Different parts have different size key caches. We handle
* up to ATH_KEYMAX entries (could dynamically allocate state).
*/
#define ATH_KEYMAX 128 /* max key cache size we handle */
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
#define ATH_RSSI_DUMMY_MARKER 0x127
#define ATH_RATE_DUMMY_MARKER 0
#define SC_OP_INVALID BIT(0)
......@@ -573,9 +469,6 @@ struct ath_softc {
u16 curtxpow;
u8 nbcnvifs;
u16 nvifs;
u32 keymax;
DECLARE_BITMAP(keymap, ATH_KEYMAX);
u8 splitmic;
bool ps_enabled;
unsigned long ps_usecount;
enum ath9k_int imask;
......@@ -601,7 +494,6 @@ struct ath_softc {
int beacon_interval;
struct ath_ani ani;
#ifdef CONFIG_ATH9K_DEBUG
struct ath9k_debug debug;
#endif
......@@ -620,6 +512,7 @@ struct ath_wiphy {
ATH_WIPHY_PAUSED,
ATH_WIPHY_SCAN,
} state;
bool idle;
int chan_idx;
int chan_is_ht;
};
......@@ -654,8 +547,9 @@ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
void ath_update_chainmask(struct ath_softc *sc, int is_ht);
int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
struct ath9k_channel *hchan);
void ath_radio_enable(struct ath_softc *sc);
void ath_radio_disable(struct ath_softc *sc);
void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
#ifdef CONFIG_PCI
int ath_pci_init(void);
......@@ -691,6 +585,10 @@ void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
bool ath9k_wiphy_scanning(struct ath_softc *sc);
void ath9k_wiphy_work(struct work_struct *work);
bool ath9k_all_wiphys_idle(struct ath_softc *sc);
void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle);
void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue);
void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue);
int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype);
#endif /* ATH9K_H */
/*
* Copyright (c) 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.
*/
/*
* Module for common driver code between ath9k and ath9k_htc
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include "common.h"
MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
MODULE_LICENSE("Dual BSD/GPL");
/* Common RX processing */
/* Assumes you've already done the endian to CPU conversion */
static bool ath9k_rx_accept(struct ath_common *common,
struct sk_buff *skb,
struct ieee80211_rx_status *rxs,
struct ath_rx_status *rx_stats,
bool *decrypt_error)
{
struct ath_hw *ah = common->ah;
struct ieee80211_hdr *hdr;
__le16 fc;
hdr = (struct ieee80211_hdr *) skb->data;
fc = hdr->frame_control;
if (!rx_stats->rs_datalen)
return false;
/*
* rs_status follows rs_datalen so if rs_datalen is too large
* we can take a hint that hardware corrupted it, so ignore
* those frames.
*/
if (rx_stats->rs_datalen > common->rx_bufsize)
return false;
/*
* rs_more indicates chained descriptors which can be used
* to link buffers together for a sort of scatter-gather