mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 17:51:43 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
dfef948ed2
@ -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));
|
||||
|
@ -1,5 +1,7 @@
|
||||
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 */
|
||||
|
286
drivers/net/wireless/ath/ath9k/common.c
Normal file
286
drivers/net/wireless/ath/ath9k/common.c
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* 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
|
||||
* operation.
|
||||
*
|
||||
* The rx_stats->rs_status will not be set until the end of the
|
||||
* chained descriptors so it can be ignored if rs_more is set. The
|
||||
* rs_more will be false at the last element of the chained
|
||||
* descriptors.
|
||||
*/
|
||||
if (!rx_stats->rs_more && rx_stats->rs_status != 0) {
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_CRC)
|
||||
rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_PHY)
|
||||
return false;
|
||||
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
|
||||
*decrypt_error = true;
|
||||
} else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
|
||||
if (ieee80211_is_ctl(fc))
|
||||
/*
|
||||
* Sometimes, we get invalid
|
||||
* MIC failures on valid control frames.
|
||||
* Remove these mic errors.
|
||||
*/
|
||||
rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
|
||||
else
|
||||
rxs->flag |= RX_FLAG_MMIC_ERROR;
|
||||
}
|
||||
/*
|
||||
* Reject error frames with the exception of
|
||||
* decryption and MIC failures. For monitor mode,
|
||||
* we also ignore the CRC error.
|
||||
*/
|
||||
if (ah->opmode == NL80211_IFTYPE_MONITOR) {
|
||||
if (rx_stats->rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
||||
ATH9K_RXERR_CRC))
|
||||
return false;
|
||||
} else {
|
||||
if (rx_stats->rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static u8 ath9k_process_rate(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
enum ieee80211_band band;
|
||||
unsigned int i = 0;
|
||||
|
||||
band = hw->conf.channel->band;
|
||||
sband = hw->wiphy->bands[band];
|
||||
|
||||
if (rx_stats->rs_rate & 0x80) {
|
||||
/* HT rate */
|
||||
rxs->flag |= RX_FLAG_HT;
|
||||
if (rx_stats->rs_flags & ATH9K_RX_2040)
|
||||
rxs->flag |= RX_FLAG_40MHZ;
|
||||
if (rx_stats->rs_flags & ATH9K_RX_GI)
|
||||
rxs->flag |= RX_FLAG_SHORT_GI;
|
||||
return rx_stats->rs_rate & 0x7f;
|
||||
}
|
||||
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if (sband->bitrates[i].hw_value == rx_stats->rs_rate)
|
||||
return i;
|
||||
if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
|
||||
rxs->flag |= RX_FLAG_SHORTPRE;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/* No valid hardware bitrate found -- we should not get here */
|
||||
ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected "
|
||||
"0x%02x using 1 Mbit\n", rx_stats->rs_rate);
|
||||
if ((common->debug_mask & ATH_DBG_XMIT))
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_NONE, skb->data, skb->len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath9k_process_rssi(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ath_node *an;
|
||||
int last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
__le16 fc;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
|
||||
rcu_read_lock();
|
||||
/*
|
||||
* XXX: use ieee80211_find_sta! This requires quite a bit of work
|
||||
* under the current ath9k virtual wiphy implementation as we have
|
||||
* no way of tying a vif to wiphy. Typically vifs are attached to
|
||||
* at least one sdata of a wiphy on mac80211 but with ath9k virtual
|
||||
* wiphy you'd have to iterate over every wiphy and each sdata.
|
||||
*/
|
||||
sta = ieee80211_find_sta_by_hw(hw, hdr->addr2);
|
||||
if (sta) {
|
||||
an = (struct ath_node *) sta->drv_priv;
|
||||
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
|
||||
!rx_stats->rs_moreaggr)
|
||||
ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
|
||||
last_rssi = an->last_rssi;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
|
||||
rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
|
||||
ATH_RSSI_EP_MULTIPLIER);
|
||||
if (rx_stats->rs_rssi < 0)
|
||||
rx_stats->rs_rssi = 0;
|
||||
else if (rx_stats->rs_rssi > 127)
|
||||
rx_stats->rs_rssi = 127;
|
||||
|
||||
/* Update Beacon RSSI, this is used by ANI. */
|
||||
if (ieee80211_is_beacon(fc))
|
||||
ah->stats.avgbrssi = rx_stats->rs_rssi;
|
||||
}
|
||||
|
||||
/*
|
||||
* For Decrypt or Demic errors, we only mark packet status here and always push
|
||||
* 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.
|
||||
*/
|
||||
int ath9k_cmn_rx_skb_preprocess(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
bool *decrypt_error)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
|
||||
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
|
||||
if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error))
|
||||
return -EINVAL;
|
||||
|
||||
ath9k_process_rssi(common, hw, skb, rx_stats);
|
||||
|
||||
rx_status->rate_idx = ath9k_process_rate(common, hw,
|
||||
rx_stats, rx_status, skb);
|
||||
rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp);
|
||||
rx_status->band = hw->conf.channel->band;
|
||||
rx_status->freq = hw->conf.channel->center_freq;
|
||||
rx_status->noise = common->ani.noise_floor;
|
||||
rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
|
||||
rx_status->antenna = rx_stats->rs_antenna;
|
||||
rx_status->flag |= RX_FLAG_TSFT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_rx_skb_preprocess);
|
||||
|
||||
void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
bool decrypt_error)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ieee80211_hdr *hdr;
|
||||
int hdrlen, padsize;
|
||||
u8 keyix;
|
||||
__le16 fc;
|
||||
|
||||
/* see if any padding is done by the hw and remove it */
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
fc = hdr->frame_control;
|
||||
|
||||
/* The MAC header is padded to have 32-bit boundary if the
|
||||
* packet payload is non-zero. The general calculation for
|
||||
* padsize would take into account odd header lengths:
|
||||
* padsize = (4 - hdrlen % 4) % 4; However, since only
|
||||
* even-length headers are used, padding can only be 0 or 2
|
||||
* bytes and we can optimize this a bit. In addition, we must
|
||||
* not try to remove padding from short control frames that do
|
||||
* not have payload. */
|
||||
padsize = hdrlen & 3;
|
||||
if (padsize && hdrlen >= 24) {
|
||||
memmove(skb->data + padsize, skb->data, hdrlen);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
|
||||
keyix = rx_stats->rs_keyix;
|
||||
|
||||
if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
|
||||
rxs->flag |= RX_FLAG_DECRYPTED;
|
||||
} else if (ieee80211_has_protected(fc)
|
||||
&& !decrypt_error && skb->len >= hdrlen + 4) {
|
||||
keyix = skb->data[hdrlen + 3] >> 6;
|
||||
|
||||
if (test_bit(keyix, common->keymap))
|
||||
rxs->flag |= RX_FLAG_DECRYPTED;
|
||||
}
|
||||
if (ah->sw_mgmt_crypto &&
|
||||
(rxs->flag & RX_FLAG_DECRYPTED) &&
|
||||
ieee80211_is_mgmt(fc))
|
||||
/* Use software decrypt for management frames. */
|
||||
rxs->flag &= ~RX_FLAG_DECRYPTED;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
|
||||
|
||||
static int __init ath9k_cmn_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
module_init(ath9k_cmn_init);
|
||||
|
||||
static void __exit ath9k_cmn_exit(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
module_exit(ath9k_cmn_exit);
|
123
drivers/net/wireless/ath/ath9k/common.h
Normal file
123
drivers/net/wireless/ath/ath9k/common.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "../ath.h"
|
||||
#include "../debug.h"
|
||||
|
||||
#include "hw.h"
|
||||
|
||||
/* Common header for Atheros 802.11n base driver cores */
|
||||
|
||||
#define WME_NUM_TID 16
|
||||
#define WME_BA_BMP_SIZE 64
|
||||
#define WME_MAX_BA WME_BA_BMP_SIZE
|
||||
#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
|
||||
|
||||
#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 ATH_RSSI_DUMMY_MARKER 0x127
|
||||
#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_atx_ac {
|
||||
int sched;
|
||||
int qnum;
|
||||
struct list_head list;
|
||||
struct list_head tid_q;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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_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_node {
|
||||
struct ath_common *common;
|
||||
struct ath_atx_tid tid[WME_NUM_TID];
|
||||
struct ath_atx_ac ac[WME_NUM_AC];
|
||||
u16 maxampdu;
|
||||
u8 mpdudensity;
|
||||
int last_rssi;
|
||||
};
|
||||
|
||||
int ath9k_cmn_rx_skb_preprocess(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
bool *decrypt_error);
|
||||
|
||||
void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
bool decrypt_error);
|
@ -3710,6 +3710,21 @@ void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting)
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_set_tsfadjust);
|
||||
|
||||
/*
|
||||
* Extend 15-bit time stamp from rx descriptor to
|
||||
* a full 64-bit TSF using the current h/w TSF.
|
||||
*/
|
||||
u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp)
|
||||
{
|
||||
u64 tsf;
|
||||
|
||||
tsf = ath9k_hw_gettsf64(ah);
|
||||
if ((tsf & 0x7fff) < rstamp)
|
||||
tsf -= 0x8000;
|
||||
return (tsf & ~0x7fff) | rstamp;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_extend_tsf);
|
||||
|
||||
bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
|
||||
{
|
||||
if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
|
||||
|
@ -432,7 +432,7 @@ struct ath9k_hw_version {
|
||||
* Using de Bruijin sequence to to look up 1's index in a 32 bit number
|
||||
* debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
|
||||
*/
|
||||
#define debruijn32 0x077CB531UL
|
||||
#define debruijn32 0x077CB531U
|
||||
|
||||
struct ath_gen_timer_configuration {
|
||||
u32 next_addr;
|
||||
@ -689,6 +689,7 @@ u64 ath9k_hw_gettsf64(struct ath_hw *ah);
|
||||
void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
|
||||
void ath9k_hw_reset_tsf(struct ath_hw *ah);
|
||||
void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
|
||||
u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp);
|
||||
bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
|
||||
void ath9k_hw_set11nmac2040(struct ath_hw *ah);
|
||||
void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
|
||||
|
@ -405,34 +405,34 @@ static void ath_ani_calibrate(unsigned long data)
|
||||
ath9k_ps_wakeup(sc);
|
||||
|
||||
/* Long calibration runs independently of short calibration. */
|
||||
if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
|
||||
if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
|
||||
longcal = true;
|
||||
ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
|
||||
sc->ani.longcal_timer = timestamp;
|
||||
common->ani.longcal_timer = timestamp;
|
||||
}
|
||||
|
||||
/* Short calibration applies only while caldone is false */
|
||||
if (!sc->ani.caldone) {
|
||||
if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) {
|
||||
if (!common->ani.caldone) {
|
||||
if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
|
||||
shortcal = true;
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"shortcal @%lu\n", jiffies);
|
||||
sc->ani.shortcal_timer = timestamp;
|
||||
sc->ani.resetcal_timer = timestamp;
|
||||
common->ani.shortcal_timer = timestamp;
|
||||
common->ani.resetcal_timer = timestamp;
|
||||
}
|
||||
} else {
|
||||
if ((timestamp - sc->ani.resetcal_timer) >=
|
||||
if ((timestamp - common->ani.resetcal_timer) >=
|
||||
ATH_RESTART_CALINTERVAL) {
|
||||
sc->ani.caldone = ath9k_hw_reset_calvalid(ah);
|
||||
if (sc->ani.caldone)
|
||||
sc->ani.resetcal_timer = timestamp;
|
||||
common->ani.caldone = ath9k_hw_reset_calvalid(ah);
|
||||
if (common->ani.caldone)
|
||||
common->ani.resetcal_timer = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify whether we must check ANI */
|
||||
if ((timestamp - sc->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
|
||||
if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
|
||||
aniflag = true;
|
||||
sc->ani.checkani_timer = timestamp;
|
||||
common->ani.checkani_timer = timestamp;
|
||||
}
|
||||
|
||||
/* Skip all processing if there's nothing to do. */
|
||||
@ -443,21 +443,21 @@ static void ath_ani_calibrate(unsigned long data)
|
||||
|
||||
/* Perform calibration if necessary */
|
||||
if (longcal || shortcal) {
|
||||
sc->ani.caldone =
|
||||
common->ani.caldone =
|
||||
ath9k_hw_calibrate(ah,
|
||||
ah->curchan,
|
||||
common->rx_chainmask,
|
||||
longcal);
|
||||
|
||||
if (longcal)
|
||||
sc->ani.noise_floor = ath9k_hw_getchan_noise(ah,
|
||||
common->ani.noise_floor = ath9k_hw_getchan_noise(ah,
|
||||
ah->curchan);
|
||||
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
" calibrate chan %u/%x nf: %d\n",
|
||||
ah->curchan->channel,
|
||||
ah->curchan->channelFlags,
|
||||
sc->ani.noise_floor);
|
||||
common->ani.noise_floor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -473,21 +473,21 @@ set_timer:
|
||||
cal_interval = ATH_LONG_CALINTERVAL;
|
||||
if (sc->sc_ah->config.enable_ani)
|
||||
cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
|
||||
if (!sc->ani.caldone)
|
||||
if (!common->ani.caldone)
|
||||
cal_interval = min(cal_interval, (u32)short_cal_interval);
|
||||
|
||||
mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
|
||||
mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
|
||||
}
|
||||
|
||||
static void ath_start_ani(struct ath_softc *sc)
|
||||
static void ath_start_ani(struct ath_common *common)
|
||||
{
|
||||
unsigned long timestamp = jiffies_to_msecs(jiffies);
|
||||
|
||||
sc->ani.longcal_timer = timestamp;
|
||||
sc->ani.shortcal_timer = timestamp;
|
||||
sc->ani.checkani_timer = timestamp;
|
||||
common->ani.longcal_timer = timestamp;
|
||||
common->ani.shortcal_timer = timestamp;
|
||||
common->ani.checkani_timer = timestamp;
|
||||
|
||||
mod_timer(&sc->ani.timer,
|
||||
mod_timer(&common->ani.timer,
|
||||
jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
|
||||
}
|
||||
|
||||
@ -733,10 +733,11 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
|
||||
return chanmode;
|
||||
}
|
||||
|
||||
static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key,
|
||||
static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
|
||||
struct ath9k_keyval *hk, const u8 *addr,
|
||||
bool authenticator)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
const u8 *key_rxmic;
|
||||
const u8 *key_txmic;
|
||||
|
||||
@ -756,42 +757,42 @@ static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key,
|
||||
memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
|
||||
memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
|
||||
}
|
||||
return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
|
||||
return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
|
||||
}
|
||||
if (!sc->splitmic) {
|
||||
if (!common->splitmic) {
|
||||
/* TX and RX keys share the same key cache entry. */
|
||||
memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
|
||||
memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
|
||||
return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
|
||||
return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
|
||||
}
|
||||
|
||||
/* Separate key cache entries for TX and RX */
|
||||
|
||||
/* TX key goes at first index, RX key at +32. */
|
||||
memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
|
||||
if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) {
|
||||
if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) {
|
||||
/* TX MIC entry failed. No need to proceed further */
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Setting TX MIC Key Failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
|
||||
/* XXX delete tx key on failure? */
|
||||
return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix + 32, hk, addr);
|
||||
return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr);
|
||||
}
|
||||
|
||||
static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc)
|
||||
static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
|
||||
if (test_bit(i, sc->keymap) ||
|
||||
test_bit(i + 64, sc->keymap))
|
||||
for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
|
||||
if (test_bit(i, common->keymap) ||
|
||||
test_bit(i + 64, common->keymap))
|
||||
continue; /* At least one part of TKIP key allocated */
|
||||
if (sc->splitmic &&
|
||||
(test_bit(i + 32, sc->keymap) ||
|
||||
test_bit(i + 64 + 32, sc->keymap)))
|
||||
if (common->splitmic &&
|
||||
(test_bit(i + 32, common->keymap) ||
|
||||
test_bit(i + 64 + 32, common->keymap)))
|
||||
continue; /* At least one part of TKIP key allocated */
|
||||
|
||||
/* Found a free slot for a TKIP key */
|
||||
@ -800,60 +801,60 @@ static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ath_reserve_key_cache_slot(struct ath_softc *sc)
|
||||
static int ath_reserve_key_cache_slot(struct ath_common *common)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* First, try to find slots that would not be available for TKIP. */
|
||||
if (sc->splitmic) {
|
||||
for (i = IEEE80211_WEP_NKID; i < sc->keymax / 4; i++) {
|
||||
if (!test_bit(i, sc->keymap) &&
|
||||
(test_bit(i + 32, sc->keymap) ||
|
||||
test_bit(i + 64, sc->keymap) ||
|
||||
test_bit(i + 64 + 32, sc->keymap)))
|
||||
if (common->splitmic) {
|
||||
for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
|
||||
if (!test_bit(i, common->keymap) &&
|
||||
(test_bit(i + 32, common->keymap) ||
|
||||
test_bit(i + 64, common->keymap) ||
|
||||
test_bit(i + 64 + 32, common->keymap)))
|
||||
return i;
|
||||
if (!test_bit(i + 32, sc->keymap) &&
|
||||
(test_bit(i, sc->keymap) ||
|
||||
test_bit(i + 64, sc->keymap) ||
|
||||
test_bit(i + 64 + 32, sc->keymap)))
|
||||
if (!test_bit(i + 32, common->keymap) &&
|
||||
(test_bit(i, common->keymap) ||
|
||||
test_bit(i + 64, common->keymap) ||
|
||||
test_bit(i + 64 + 32, common->keymap)))
|
||||
return i + 32;
|
||||
if (!test_bit(i + 64, sc->keymap) &&
|
||||
(test_bit(i , sc->keymap) ||
|
||||
test_bit(i + 32, sc->keymap) ||
|
||||
test_bit(i + 64 + 32, sc->keymap)))
|
||||
if (!test_bit(i + 64, common->keymap) &&
|
||||
(test_bit(i , common->keymap) ||
|
||||
test_bit(i + 32, common->keymap) ||
|
||||
test_bit(i + 64 + 32, common->keymap)))
|
||||
return i + 64;
|
||||
if (!test_bit(i + 64 + 32, sc->keymap) &&
|
||||
(test_bit(i, sc->keymap) ||
|
||||
test_bit(i + 32, sc->keymap) ||
|
||||
test_bit(i + 64, sc->keymap)))
|
||||
if (!test_bit(i + 64 + 32, common->keymap) &&
|
||||
(test_bit(i, common->keymap) ||
|
||||
test_bit(i + 32, common->keymap) ||
|
||||
test_bit(i + 64, common->keymap)))
|
||||
return i + 64 + 32;
|
||||
}
|
||||
} else {
|
||||
for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
|
||||
if (!test_bit(i, sc->keymap) &&
|
||||
test_bit(i + 64, sc->keymap))
|
||||
for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
|
||||
if (!test_bit(i, common->keymap) &&
|
||||
test_bit(i + 64, common->keymap))
|
||||
return i;
|
||||
if (test_bit(i, sc->keymap) &&
|
||||
!test_bit(i + 64, sc->keymap))
|
||||
if (test_bit(i, common->keymap) &&
|
||||
!test_bit(i + 64, common->keymap))
|
||||
return i + 64;
|
||||
}
|
||||
}
|
||||
|
||||
/* No partially used TKIP slots, pick any available slot */
|
||||
for (i = IEEE80211_WEP_NKID; i < sc->keymax; i++) {
|
||||
for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
|
||||
/* Do not allow slots that could be needed for TKIP group keys
|
||||
* to be used. This limitation could be removed if we know that
|
||||
* TKIP will not be used. */
|
||||
if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
|
||||
continue;
|
||||
if (sc->splitmic) {
|
||||
if (common->splitmic) {
|
||||
if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
|
||||
continue;
|
||||
if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!test_bit(i, sc->keymap))
|
||||
if (!test_bit(i, common->keymap))
|
||||
return i; /* Found a free slot for a key */
|
||||
}
|
||||
|
||||
@ -861,11 +862,12 @@ static int ath_reserve_key_cache_slot(struct ath_softc *sc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ath_key_config(struct ath_softc *sc,
|
||||
static int ath_key_config(struct ath_common *common,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ath9k_keyval hk;
|
||||
const u8 *mac = NULL;
|
||||
int ret = 0;
|
||||
@ -911,48 +913,50 @@ static int ath_key_config(struct ath_softc *sc,
|
||||
mac = sta->addr;
|
||||
|
||||
if (key->alg == ALG_TKIP)
|
||||
idx = ath_reserve_key_cache_slot_tkip(sc);
|
||||
idx = ath_reserve_key_cache_slot_tkip(common);
|
||||
else
|
||||
idx = ath_reserve_key_cache_slot(sc);
|
||||
idx = ath_reserve_key_cache_slot(common);
|
||||
if (idx < 0)
|
||||
return -ENOSPC; /* no free key cache entries */
|
||||
}
|
||||
|
||||
if (key->alg == ALG_TKIP)
|
||||
ret = ath_setkey_tkip(sc, idx, key->key, &hk, mac,
|
||||
ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
|
||||
vif->type == NL80211_IFTYPE_AP);
|
||||
else
|
||||
ret = ath9k_hw_set_keycache_entry(sc->sc_ah, idx, &hk, mac);
|
||||
ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac);
|
||||
|
||||
if (!ret)
|
||||
return -EIO;
|
||||
|
||||
set_bit(idx, sc->keymap);
|
||||
set_bit(idx, common->keymap);
|
||||
if (key->alg == ALG_TKIP) {
|
||||
set_bit(idx + 64, sc->keymap);
|
||||
if (sc->splitmic) {
|
||||
set_bit(idx + 32, sc->keymap);
|
||||
set_bit(idx + 64 + 32, sc->keymap);
|
||||
set_bit(idx + 64, common->keymap);
|
||||
if (common->splitmic) {
|
||||
set_bit(idx + 32, common->keymap);
|
||||
set_bit(idx + 64 + 32, common->keymap);
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
|
||||
static void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
|
||||
{
|
||||
ath9k_hw_keyreset(sc->sc_ah, key->hw_key_idx);
|
||||
struct ath_hw *ah = common->ah;
|
||||
|
||||
ath9k_hw_keyreset(ah, key->hw_key_idx);
|
||||
if (key->hw_key_idx < IEEE80211_WEP_NKID)
|
||||
return;
|
||||
|
||||
clear_bit(key->hw_key_idx, sc->keymap);
|
||||
clear_bit(key->hw_key_idx, common->keymap);
|
||||
if (key->alg != ALG_TKIP)
|
||||
return;
|
||||
|
||||
clear_bit(key->hw_key_idx + 64, sc->keymap);
|
||||
if (sc->splitmic) {
|
||||
clear_bit(key->hw_key_idx + 32, sc->keymap);
|
||||
clear_bit(key->hw_key_idx + 64 + 32, sc->keymap);
|
||||
clear_bit(key->hw_key_idx + 64, common->keymap);
|
||||
if (common->splitmic) {
|
||||
clear_bit(key->hw_key_idx + 32, common->keymap);
|
||||
clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1023,12 +1027,12 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
|
||||
/* Reset rssi stats */
|
||||
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
|
||||
|
||||
ath_start_ani(sc);
|
||||
ath_start_ani(common);
|
||||
} else {
|
||||
ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
|
||||
common->curaid = 0;
|
||||
/* Stop ANI */
|
||||
del_timer_sync(&sc->ani.timer);
|
||||
del_timer_sync(&common->ani.timer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1200,11 +1204,11 @@ fail:
|
||||
ath_deinit_leds(sc);
|
||||
}
|
||||
|
||||
void ath_radio_enable(struct ath_softc *sc)
|
||||
void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ieee80211_channel *channel = sc->hw->conf.channel;
|
||||
struct ieee80211_channel *channel = hw->conf.channel;
|
||||
int r;
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
@ -1241,18 +1245,18 @@ void ath_radio_enable(struct ath_softc *sc)
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
|
||||
|
||||
ieee80211_wake_queues(sc->hw);
|
||||
ieee80211_wake_queues(hw);
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
void ath_radio_disable(struct ath_softc *sc)
|
||||
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ieee80211_channel *channel = sc->hw->conf.channel;
|
||||
struct ieee80211_channel *channel = hw->conf.channel;
|
||||
int r;
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
ieee80211_stop_queues(sc->hw);
|
||||
ieee80211_stop_queues(hw);
|
||||
|
||||
/* Disable LED */
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
||||
@ -1266,7 +1270,7 @@ void ath_radio_disable(struct ath_softc *sc)
|
||||
ath_flushrecv(sc); /* flush recv queue */
|
||||
|
||||
if (!ah->curchan)
|
||||
ah->curchan = ath_get_curchannel(sc, sc->hw);
|
||||
ah->curchan = ath_get_curchannel(sc, hw);
|
||||
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
r = ath9k_hw_reset(ah, ah->curchan, false);
|
||||
@ -1679,19 +1683,19 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
}
|
||||
|
||||
/* Get the hardware key cache size. */
|
||||
sc->keymax = ah->caps.keycache_size;
|
||||
if (sc->keymax > ATH_KEYMAX) {
|
||||
common->keymax = ah->caps.keycache_size;
|
||||
if (common->keymax > ATH_KEYMAX) {
|
||||
ath_print(common, ATH_DBG_ANY,
|
||||
"Warning, using only %u entries in %u key cache\n",
|
||||
ATH_KEYMAX, sc->keymax);
|
||||
sc->keymax = ATH_KEYMAX;
|
||||
ATH_KEYMAX, common->keymax);
|
||||
common->keymax = ATH_KEYMAX;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the key cache since some parts do not
|
||||
* reset the contents on initial power up.
|
||||
*/
|
||||
for (i = 0; i < sc->keymax; i++)
|
||||
for (i = 0; i < common->keymax; i++)
|
||||
ath9k_hw_keyreset(ah, (u16) i);
|
||||
|
||||
/* default to MONITOR mode */
|
||||
@ -1761,8 +1765,8 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
/* Initializes the noise floor to a reasonable default value.
|
||||
* Later on this will be updated during ANI processing. */
|
||||
|
||||
sc->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
|
||||
setup_timer(&sc->ani.timer, ath_ani_calibrate, (unsigned long)sc);
|
||||
common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
|
||||
setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
|
||||
|
||||
if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
|
||||
ATH9K_CIPHER_TKIP, NULL)) {
|
||||
@ -1788,7 +1792,7 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
ATH9K_CIPHER_MIC, NULL)
|
||||
&& ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
|
||||
0, NULL))
|
||||
sc->splitmic = 1;
|
||||
common->splitmic = 1;
|
||||
|
||||
/* turn on mcast key search if possible */
|
||||
if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
|
||||
@ -2634,7 +2638,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
|
||||
if (conf->type == NL80211_IFTYPE_AP ||
|
||||
conf->type == NL80211_IFTYPE_ADHOC ||
|
||||
conf->type == NL80211_IFTYPE_MONITOR)
|
||||
ath_start_ani(sc);
|
||||
ath_start_ani(common);
|
||||
|
||||
out:
|
||||
mutex_unlock(&sc->mutex);
|
||||
@ -2655,7 +2659,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
/* Stop ANI */
|
||||
del_timer_sync(&sc->ani.timer);
|
||||
del_timer_sync(&common->ani.timer);
|
||||
|
||||
/* Reclaim beacon resources */
|
||||
if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
|
||||
@ -2688,23 +2692,38 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
bool all_wiphys_idle = false, disable_radio = false;
|
||||
bool disable_radio;
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
/* Leave this as the first check */
|
||||
/*
|
||||
* Leave this as the first check because we need to turn on the
|
||||
* radio if it was disabled before prior to processing the rest
|
||||
* of the changes. Likewise we must only disable the radio towards
|
||||
* the end.
|
||||
*/
|
||||
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
|
||||
bool enable_radio;
|
||||
bool all_wiphys_idle;
|
||||
bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
|
||||
|
||||
spin_lock_bh(&sc->wiphy_lock);
|
||||
all_wiphys_idle = ath9k_all_wiphys_idle(sc);
|
||||
ath9k_set_wiphy_idle(aphy, idle);
|
||||
|
||||
if (!idle && all_wiphys_idle)
|
||||
enable_radio = true;
|
||||
|
||||
/*
|
||||
* After we unlock here its possible another wiphy
|
||||
* can be re-renabled so to account for that we will
|
||||
* only disable the radio toward the end of this routine
|
||||
* if by then all wiphys are still idle.
|
||||
*/
|
||||
spin_unlock_bh(&sc->wiphy_lock);
|
||||
|
||||
if (conf->flags & IEEE80211_CONF_IDLE){
|
||||
if (all_wiphys_idle)
|
||||
disable_radio = true;
|
||||
}
|
||||
else if (all_wiphys_idle) {
|
||||
ath_radio_enable(sc);
|
||||
if (enable_radio) {
|
||||
ath_radio_enable(sc, hw);
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"not-idle: enabling radio\n");
|
||||
}
|
||||
@ -2779,9 +2798,13 @@ skip_chan_change:
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER)
|
||||
sc->config.txpowlimit = 2 * conf->power_level;
|
||||
|
||||
spin_lock_bh(&sc->wiphy_lock);
|
||||
disable_radio = ath9k_all_wiphys_idle(sc);
|
||||
spin_unlock_bh(&sc->wiphy_lock);
|
||||
|
||||
if (disable_radio) {
|
||||
ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
|
||||
ath_radio_disable(sc);
|
||||
ath_radio_disable(sc, hw);
|
||||
}
|
||||
|
||||
mutex_unlock(&sc->mutex);
|
||||
@ -2898,7 +2921,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
|
||||
|
||||
switch (cmd) {
|
||||
case SET_KEY:
|
||||
ret = ath_key_config(sc, vif, sta, key);
|
||||
ret = ath_key_config(common, vif, sta, key);
|
||||
if (ret >= 0) {
|
||||
key->hw_key_idx = ret;
|
||||
/* push IV and Michael MIC generation to stack */
|
||||
@ -2911,7 +2934,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
|
||||
}
|
||||
break;
|
||||
case DISABLE_KEY:
|
||||
ath_key_delete(sc, key);
|
||||
ath_key_delete(common, key);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
@ -19,6 +19,8 @@
|
||||
#ifndef RC_H
|
||||
#define RC_H
|
||||
|
||||
#include "hw.h"
|
||||
|
||||
struct ath_softc;
|
||||
|
||||
#define ATH_RATE_MAX 30
|
||||
|
@ -48,6 +48,7 @@ static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,
|
||||
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;
|
||||
|
||||
@ -62,11 +63,13 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
|
||||
BUG_ON(skb == NULL);
|
||||
ds->ds_vdata = skb->data;
|
||||
|
||||
/* setup rx descriptors. The rx.bufsize here tells the harware
|
||||
/*
|
||||
* 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 */
|
||||
* to process
|
||||
*/
|
||||
ath9k_hw_setuprxdesc(ah, ds,
|
||||
sc->rx.bufsize,
|
||||
common->rx_bufsize,
|
||||
0);
|
||||
|
||||
if (sc->rx.rxlink == NULL)
|
||||
@ -86,190 +89,6 @@ static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
|
||||
sc->rx.rxotherant = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extend 15-bit time stamp from rx descriptor to
|
||||
* a full 64-bit TSF using the current h/w TSF.
|
||||
*/
|
||||
static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
|
||||
{
|
||||
u64 tsf;
|
||||
|
||||
tsf = ath9k_hw_gettsf64(sc->sc_ah);
|
||||
if ((tsf & 0x7fff) < rstamp)
|
||||
tsf -= 0x8000;
|
||||
return (tsf & ~0x7fff) | rstamp;
|
||||
}
|
||||
|
||||
/*
|
||||
* For Decrypt or Demic errors, we only mark packet status here and always push
|
||||
* 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 ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
|
||||
struct ieee80211_rx_status *rx_status, bool *decrypt_error,
|
||||
struct ath_softc *sc)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
u8 ratecode;
|
||||
__le16 fc;
|
||||
struct ieee80211_hw *hw;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ath_node *an;
|
||||
int last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
|
||||
hw = ath_get_virt_hw(sc, hdr);
|
||||
|
||||
if (ds->ds_rxstat.rs_more) {
|
||||
/*
|
||||
* Frame spans multiple descriptors; this cannot happen yet
|
||||
* as we don't support jumbograms. If not in monitor mode,
|
||||
* discard the frame. Enable this if you want to see
|
||||
* error frames in Monitor mode.
|
||||
*/
|
||||
if (sc->sc_ah->opmode != NL80211_IFTYPE_MONITOR)
|
||||
goto rx_next;
|
||||
} else if (ds->ds_rxstat.rs_status != 0) {
|
||||
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
|
||||
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY)
|
||||
goto rx_next;
|
||||
|
||||
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
|
||||
*decrypt_error = true;
|
||||
} else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) {
|
||||
if (ieee80211_is_ctl(fc))
|
||||
/*
|
||||
* Sometimes, we get invalid
|
||||
* MIC failures on valid control frames.
|
||||
* Remove these mic errors.
|
||||
*/
|
||||
ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC;
|
||||
else
|
||||
rx_status->flag |= RX_FLAG_MMIC_ERROR;
|
||||
}
|
||||
/*
|
||||
* Reject error frames with the exception of
|
||||
* decryption and MIC failures. For monitor mode,
|
||||
* we also ignore the CRC error.
|
||||
*/
|
||||
if (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR) {
|
||||
if (ds->ds_rxstat.rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
||||
ATH9K_RXERR_CRC))
|
||||
goto rx_next;
|
||||
} else {
|
||||
if (ds->ds_rxstat.rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
|
||||
goto rx_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ratecode = ds->ds_rxstat.rs_rate;
|
||||
|
||||
if (ratecode & 0x80) {
|
||||
/* HT rate */
|
||||
rx_status->flag |= RX_FLAG_HT;
|
||||
if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040)
|
||||
rx_status->flag |= RX_FLAG_40MHZ;
|
||||
if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI)
|
||||
rx_status->flag |= RX_FLAG_SHORT_GI;
|
||||
rx_status->rate_idx = ratecode & 0x7f;
|
||||
} else {
|
||||
int i = 0, cur_band, n_rates;
|
||||
|
||||
cur_band = hw->conf.channel->band;
|
||||
n_rates = sc->sbands[cur_band].n_bitrates;
|
||||
|
||||
for (i = 0; i < n_rates; i++) {
|
||||
if (sc->sbands[cur_band].bitrates[i].hw_value ==
|
||||
ratecode) {
|
||||
rx_status->rate_idx = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sc->sbands[cur_band].bitrates[i].hw_value_short ==
|
||||
ratecode) {
|
||||
rx_status->rate_idx = i;
|
||||
rx_status->flag |= RX_FLAG_SHORTPRE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
/* XXX: use ieee80211_find_sta! */
|
||||
sta = ieee80211_find_sta_by_hw(sc->hw, hdr->addr2);
|
||||
if (sta) {
|
||||
an = (struct ath_node *) sta->drv_priv;
|
||||
if (ds->ds_rxstat.rs_rssi != ATH9K_RSSI_BAD &&
|
||||
!ds->ds_rxstat.rs_moreaggr)
|
||||
ATH_RSSI_LPF(an->last_rssi, ds->ds_rxstat.rs_rssi);
|
||||
last_rssi = an->last_rssi;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
|
||||
ds->ds_rxstat.rs_rssi = ATH_EP_RND(last_rssi,
|
||||
ATH_RSSI_EP_MULTIPLIER);
|
||||
if (ds->ds_rxstat.rs_rssi < 0)
|
||||
ds->ds_rxstat.rs_rssi = 0;
|
||||
else if (ds->ds_rxstat.rs_rssi > 127)
|
||||
ds->ds_rxstat.rs_rssi = 127;
|
||||
|
||||
/* Update Beacon RSSI, this is used by ANI. */
|
||||
if (ieee80211_is_beacon(fc))
|
||||
sc->sc_ah->stats.avgbrssi = ds->ds_rxstat.rs_rssi;
|
||||
|
||||
rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
|
||||
rx_status->band = hw->conf.channel->band;
|
||||
rx_status->freq = hw->conf.channel->center_freq;
|
||||
rx_status->noise = sc->ani.noise_floor;
|
||||
rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + ds->ds_rxstat.rs_rssi;
|
||||
rx_status->antenna = ds->ds_rxstat.rs_antenna;
|
||||
|
||||
/*
|
||||
* Theory for reporting quality:
|
||||
*
|
||||
* At a hardware RSSI of 45 you will be able to use MCS 7 reliably.
|
||||
* At a hardware RSSI of 45 you will be able to use MCS 15 reliably.
|
||||
* At a hardware RSSI of 35 you should be able use 54 Mbps reliably.
|
||||
*
|
||||
* MCS 7 is the highets MCS index usable by a 1-stream device.
|
||||
* MCS 15 is the highest MCS index usable by a 2-stream device.
|
||||
*
|
||||
* All ath9k devices are either 1-stream or 2-stream.
|
||||
*
|
||||
* How many bars you see is derived from the qual reporting.
|
||||
*
|
||||
* A more elaborate scheme can be used here but it requires tables
|
||||
* of SNR/throughput for each possible mode used. For the MCS table
|
||||
* you can refer to the wireless wiki:
|
||||
*
|
||||
* http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n
|
||||
*
|
||||
*/
|
||||
if (conf_is_ht(&hw->conf))
|
||||
rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45;
|
||||
else
|
||||
rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 35;
|
||||
|
||||
/* rssi can be more than 45 though, anything above that
|
||||
* should be considered at 100% */
|
||||
if (rx_status->qual > 100)
|
||||
rx_status->qual = 100;
|
||||
|
||||
rx_status->flag |= RX_FLAG_TSFT;
|
||||
|
||||
return 1;
|
||||
rx_next:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath_opmode_init(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
@ -307,11 +126,11 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
sc->sc_flags &= ~SC_OP_RXFLUSH;
|
||||
spin_lock_init(&sc->rx.rxbuflock);
|
||||
|
||||
sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
|
||||
min(common->cachelsz, (u16)64));
|
||||
common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
|
||||
min(common->cachelsz, (u16)64));
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
|
||||
common->cachelsz, sc->rx.bufsize);
|
||||
common->cachelsz, common->rx_bufsize);
|
||||
|
||||
/* Initialize rx descriptors */
|
||||
|
||||
@ -324,7 +143,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
}
|
||||
|
||||
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
|
||||
skb = ath_rxbuf_alloc(common, sc->rx.bufsize, GFP_KERNEL);
|
||||
skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_KERNEL);
|
||||
if (skb == NULL) {
|
||||
error = -ENOMEM;
|
||||
goto err;
|
||||
@ -332,7 +151,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
|
||||
bf->bf_mpdu = skb;
|
||||
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
|
||||
sc->rx.bufsize,
|
||||
common->rx_bufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(sc->dev,
|
||||
bf->bf_buf_addr))) {
|
||||
@ -356,6 +175,8 @@ err:
|
||||
|
||||
void ath_rx_cleanup(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct sk_buff *skb;
|
||||
struct ath_buf *bf;
|
||||
|
||||
@ -363,7 +184,7 @@ void ath_rx_cleanup(struct ath_softc *sc)
|
||||
skb = bf->bf_mpdu;
|
||||
if (skb) {
|
||||
dma_unmap_single(sc->dev, bf->bf_buf_addr,
|
||||
sc->rx.bufsize, DMA_FROM_DEVICE);
|
||||
common->rx_bufsize, DMA_FROM_DEVICE);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
@ -616,8 +437,9 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath_rx_send_to_mac80211(struct ath_softc *sc, struct sk_buff *skb,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw,
|
||||
struct ath_softc *sc, struct sk_buff *skb,
|
||||
struct ieee80211_rx_status *rxs)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
@ -637,19 +459,14 @@ static void ath_rx_send_to_mac80211(struct ath_softc *sc, struct sk_buff *skb,
|
||||
if (aphy == NULL)
|
||||
continue;
|
||||
nskb = skb_copy(skb, GFP_ATOMIC);
|
||||
if (nskb) {
|
||||
memcpy(IEEE80211_SKB_RXCB(nskb), rx_status,
|
||||
sizeof(*rx_status));
|
||||
ieee80211_rx(aphy->hw, nskb);
|
||||
}
|
||||
if (!nskb)
|
||||
continue;
|
||||
ieee80211_rx(aphy->hw, nskb);
|
||||
}
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
|
||||
ieee80211_rx(sc->hw, skb);
|
||||
} else {
|
||||
} else
|
||||
/* Deliver unicast frames based on receiver address */
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
|
||||
ieee80211_rx(ath_get_virt_hw(sc, hdr), skb);
|
||||
}
|
||||
ieee80211_rx(hw, skb);
|
||||
}
|
||||
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
@ -660,15 +477,20 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
|
||||
struct ath_buf *bf;
|
||||
struct ath_desc *ds;
|
||||
struct ath_rx_status *rx_stats;
|
||||
struct sk_buff *skb = NULL, *requeue_skb;
|
||||
struct ieee80211_rx_status rx_status;
|
||||
struct ieee80211_rx_status *rxs;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
/*
|
||||
* The hw can techncically differ from common->hw when using ath9k
|
||||
* virtual wiphy so to account for that we iterate over the active
|
||||
* wiphys and find the appropriate wiphy and therefore hw.
|
||||
*/
|
||||
struct ieee80211_hw *hw = NULL;
|
||||
struct ieee80211_hdr *hdr;
|
||||
int hdrlen, padsize, retval;
|
||||
int retval;
|
||||
bool decrypt_error = false;
|
||||
u8 keyix;
|
||||
__le16 fc;
|
||||
|
||||
spin_lock_bh(&sc->rx.rxbuflock);
|
||||
|
||||
@ -740,9 +562,15 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
* 2. requeueing the same buffer to h/w
|
||||
*/
|
||||
dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
|
||||
sc->rx.bufsize,
|
||||
common->rx_bufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
rxs = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
hw = ath_get_virt_hw(sc, hdr);
|
||||
rx_stats = &ds->ds_rxstat;
|
||||
|
||||
/*
|
||||
* If we're asked to flush receive queue, directly
|
||||
* chain it back at the queue without processing it.
|
||||
@ -750,19 +578,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
if (flush)
|
||||
goto requeue;
|
||||
|
||||
if (!ds->ds_rxstat.rs_datalen)
|
||||
goto requeue;
|
||||
|
||||
/* The status portion of the descriptor could get corrupted. */
|
||||
if (sc->rx.bufsize < ds->ds_rxstat.rs_datalen)
|
||||
goto requeue;
|
||||
|
||||
if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc))
|
||||
retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, rx_stats,
|
||||
rxs, &decrypt_error);
|
||||
if (retval)
|
||||
goto requeue;
|
||||
|
||||
/* Ensure we always have an skb to requeue once we are done
|
||||
* processing the current buffer's skb */
|
||||
requeue_skb = ath_rxbuf_alloc(common, sc->rx.bufsize, GFP_ATOMIC);
|
||||
requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC);
|
||||
|
||||
/* If there is no memory we ignore the current RX'd frame,
|
||||
* tell hardware it can give us a new frame using the old
|
||||
@ -773,60 +596,26 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
|
||||
/* Unmap the frame */
|
||||
dma_unmap_single(sc->dev, bf->bf_buf_addr,
|
||||
sc->rx.bufsize,
|
||||
common->rx_bufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
skb_put(skb, ds->ds_rxstat.rs_datalen);
|
||||
skb_put(skb, rx_stats->rs_datalen);
|
||||
|
||||
/* see if any padding is done by the hw and remove it */
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
fc = hdr->frame_control;
|
||||
|
||||
/* The MAC header is padded to have 32-bit boundary if the
|
||||
* packet payload is non-zero. The general calculation for
|
||||
* padsize would take into account odd header lengths:
|
||||
* padsize = (4 - hdrlen % 4) % 4; However, since only
|
||||
* even-length headers are used, padding can only be 0 or 2
|
||||
* bytes and we can optimize this a bit. In addition, we must
|
||||
* not try to remove padding from short control frames that do
|
||||
* not have payload. */
|
||||
padsize = hdrlen & 3;
|
||||
if (padsize && hdrlen >= 24) {
|
||||
memmove(skb->data + padsize, skb->data, hdrlen);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
|
||||
keyix = ds->ds_rxstat.rs_keyix;
|
||||
|
||||
if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
|
||||
rx_status.flag |= RX_FLAG_DECRYPTED;
|
||||
} else if (ieee80211_has_protected(fc)
|
||||
&& !decrypt_error && skb->len >= hdrlen + 4) {
|
||||
keyix = skb->data[hdrlen + 3] >> 6;
|
||||
|
||||
if (test_bit(keyix, sc->keymap))
|
||||
rx_status.flag |= RX_FLAG_DECRYPTED;
|
||||
}
|
||||
if (ah->sw_mgmt_crypto &&
|
||||
(rx_status.flag & RX_FLAG_DECRYPTED) &&
|
||||
ieee80211_is_mgmt(fc)) {
|
||||
/* Use software decrypt for management frames. */
|
||||
rx_status.flag &= ~RX_FLAG_DECRYPTED;
|
||||
}
|
||||
ath9k_cmn_rx_skb_postprocess(common, skb, rx_stats,
|
||||
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,
|
||||
sc->rx.bufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
common->rx_bufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(sc->dev,
|
||||
bf->bf_buf_addr))) {
|
||||
dev_kfree_skb_any(requeue_skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"dma_mapping_error() on RX\n");
|
||||
ath_rx_send_to_mac80211(sc, skb, &rx_status);
|
||||
ath_rx_send_to_mac80211(hw, sc, skb, rxs);
|
||||
break;
|
||||
}
|
||||
bf->bf_dmacontext = bf->bf_buf_addr;
|
||||
@ -837,7 +626,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
*/
|
||||
if (sc->rx.defant != ds->ds_rxstat.rs_antenna) {
|
||||
if (++sc->rx.rxotherant >= 3)
|
||||
ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna);
|
||||
ath_setdefantenna(sc, rx_stats->rs_antenna);
|
||||
} else {
|
||||
sc->rx.rxotherant = 0;
|
||||
}
|
||||
@ -847,7 +636,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
SC_OP_WAIT_FOR_PSPOLL_DATA)))
|
||||
ath_rx_ps(sc, skb);
|
||||
|
||||
ath_rx_send_to_mac80211(sc, skb, &rx_status);
|
||||
ath_rx_send_to_mac80211(hw, sc, skb, rxs);
|
||||
|
||||
requeue:
|
||||
list_move_tail(&bf->list, &sc->rx.rxbuf);
|
||||
|
@ -971,10 +971,10 @@ enum {
|
||||
#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S 4
|
||||
#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080
|
||||
#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7
|
||||
#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00000400
|
||||
#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 10
|
||||
#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000
|
||||
#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12
|
||||
#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00001000
|
||||
#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 1
|
||||
#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000
|
||||
#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15
|
||||
#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000
|
||||
|
@ -298,6 +298,7 @@ static void ath9k_wiphy_unpause_channel(struct ath_softc *sc)
|
||||
void ath9k_wiphy_chan_work(struct work_struct *work)
|
||||
{
|
||||
struct ath_softc *sc = container_of(work, struct ath_softc, chan_work);
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_wiphy *aphy = sc->next_wiphy;
|
||||
|
||||
if (aphy == NULL)
|
||||
@ -313,6 +314,10 @@ void ath9k_wiphy_chan_work(struct work_struct *work)
|
||||
/* XXX: remove me eventually */
|
||||
ath9k_update_ichannel(sc, aphy->hw,
|
||||
&sc->sc_ah->channels[sc->chan_idx]);
|
||||
|
||||
/* sync hw configuration for hw code */
|
||||
common->hw = aphy->hw;
|
||||
|
||||
ath_update_chainmask(sc, sc->chan_is_ht);
|
||||
if (ath_set_channel(sc, aphy->hw,
|
||||
&sc->sc_ah->channels[sc->chan_idx]) < 0) {
|
||||
@ -521,8 +526,9 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy)
|
||||
* frame being completed)
|
||||
*/
|
||||
spin_unlock_bh(&sc->wiphy_lock);
|
||||
ath_radio_disable(sc);
|
||||
ath_radio_enable(sc);
|
||||
ath_radio_disable(sc, aphy->hw);
|
||||
ath_radio_enable(sc, aphy->hw);
|
||||
/* Only the primary wiphy hw is used for queuing work */
|
||||
ieee80211_queue_work(aphy->sc->hw,
|
||||
&aphy->sc->chan_work);
|
||||
return -EBUSY; /* previous select still in progress */
|
||||
@ -668,15 +674,78 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
|
||||
bool ath9k_all_wiphys_idle(struct ath_softc *sc)
|
||||
{
|
||||
unsigned int i;
|
||||
if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) {
|
||||
if (!sc->pri_wiphy->idle)
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < sc->num_sec_wiphy; i++) {
|
||||
struct ath_wiphy *aphy = sc->sec_wiphy[i];
|
||||
if (!aphy)
|
||||
continue;
|
||||
if (aphy->state != ATH_WIPHY_INACTIVE)
|
||||
if (!aphy->idle)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* caller must hold wiphy_lock */
|
||||
void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle)
|
||||
{
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
|
||||
aphy->idle = idle;
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
|
||||
"Marking %s as %s\n",
|
||||
wiphy_name(aphy->hw->wiphy),
|
||||
idle ? "idle" : "not-idle");
|
||||
}
|
||||
/* Only bother starting a queue on an active virtual wiphy */
|
||||
void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue)
|
||||
{
|
||||
struct ieee80211_hw *hw = sc->pri_wiphy->hw;
|
||||
unsigned int i;
|
||||
|
||||
spin_lock_bh(&sc->wiphy_lock);
|
||||
|
||||
/* Start the primary wiphy */
|
||||
if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) {
|
||||
ieee80211_wake_queue(hw, skb_queue);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* Now start the secondary wiphy queues */
|
||||
for (i = 0; i < sc->num_sec_wiphy; i++) {
|
||||
struct ath_wiphy *aphy = sc->sec_wiphy[i];
|
||||
if (!aphy)
|
||||
continue;
|
||||
if (aphy->state != ATH_WIPHY_ACTIVE)
|
||||
continue;
|
||||
|
||||
hw = aphy->hw;
|
||||
ieee80211_wake_queue(hw, skb_queue);
|
||||
break;
|
||||
}
|
||||
|
||||
unlock:
|
||||
spin_unlock_bh(&sc->wiphy_lock);
|
||||
}
|
||||
|
||||
/* Go ahead and propagate information to all virtual wiphys, it won't hurt */
|
||||
void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue)
|
||||
{
|
||||
struct ieee80211_hw *hw = sc->pri_wiphy->hw;
|
||||
unsigned int i;
|
||||
|
||||
spin_lock_bh(&sc->wiphy_lock);
|
||||
|
||||
/* Stop the primary wiphy */
|
||||
ieee80211_stop_queue(hw, skb_queue);
|
||||
|
||||
/* Now stop the secondary wiphy queues */
|
||||
for (i = 0; i < sc->num_sec_wiphy; i++) {
|
||||
struct ath_wiphy *aphy = sc->sec_wiphy[i];
|
||||
if (!aphy)
|
||||
continue;
|
||||
hw = aphy->hw;
|
||||
ieee80211_stop_queue(hw, skb_queue);
|
||||
}
|
||||
spin_unlock_bh(&sc->wiphy_lock);
|
||||
}
|
||||
|
@ -267,7 +267,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_node *an = NULL;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_hw *hw;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct ath_tx_info_priv *tx_info_priv;
|
||||
struct ath_atx_tid *tid = NULL;
|
||||
struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
|
||||
struct ath_desc *ds = bf_last->bf_desc;
|
||||
@ -280,10 +283,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
skb = bf->bf_mpdu;
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
tx_info_priv = (struct ath_tx_info_priv *) tx_info->rate_driver_data[0];
|
||||
hw = tx_info_priv->aphy->hw;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
/* XXX: use ieee80211_find_sta! */
|
||||
sta = ieee80211_find_sta_by_hw(sc->hw, hdr->addr1);
|
||||
sta = ieee80211_find_sta_by_hw(hw, hdr->addr1);
|
||||
if (!sta) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
@ -908,9 +915,10 @@ int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
|
||||
struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
|
||||
{
|
||||
struct ath_txq *txq = NULL;
|
||||
u16 skb_queue = skb_get_queue_mapping(skb);
|
||||
int qnum;
|
||||
|
||||
qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
|
||||
qnum = ath_get_hal_qnum(skb_queue, sc);
|
||||
txq = &sc->tx.txq[qnum];
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
@ -919,7 +927,7 @@ struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT,
|
||||
"TX queue: %d is full, depth: %d\n",
|
||||
qnum, txq->axq_depth);
|
||||
ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb));
|
||||
ath_mac80211_stop_queue(sc, skb_queue);
|
||||
txq->stopped = 1;
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
return NULL;
|
||||
@ -1569,7 +1577,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
|
||||
|
||||
bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
|
||||
|
||||
if (conf_is_ht(&sc->hw->conf) && !is_pae(skb))
|
||||
if (conf_is_ht(&hw->conf) && !is_pae(skb))
|
||||
bf->bf_state.bf_type |= BUF_HT;
|
||||
|
||||
bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq);
|
||||
@ -1698,8 +1706,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
* on the queue */
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
|
||||
ieee80211_stop_queue(sc->hw,
|
||||
skb_get_queue_mapping(skb));
|
||||
ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
|
||||
txq->stopped = 1;
|
||||
}
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
@ -1939,7 +1946,7 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
|
||||
sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) {
|
||||
qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
|
||||
if (qnum != -1) {
|
||||
ieee80211_wake_queue(sc->hw, qnum);
|
||||
ath_mac80211_start_queue(sc, qnum);
|
||||
txq->stopped = 0;
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +99,22 @@ static struct {
|
||||
{ ATMEL_FW_TYPE_506, "atmel_at76c506", "bin" },
|
||||
{ ATMEL_FW_TYPE_NONE, NULL, NULL }
|
||||
};
|
||||
MODULE_FIRMWARE("atmel_at76c502-wpa.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c502.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c502d-wpa.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c502d.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c502e-wpa.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c502e.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c502_3com-wpa.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c502_3com.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c504-wpa.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c504.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c504_2958-wpa.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c504_2958.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c504a_2958-wpa.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c504a_2958.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c506-wpa.bin");
|
||||
MODULE_FIRMWARE("atmel_at76c506.bin");
|
||||
|
||||
#define MAX_SSID_LENGTH 32
|
||||
#define MGMT_JIFFIES (256 * HZ / 100)
|
||||
|
@ -1157,18 +1157,17 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
|
||||
}
|
||||
|
||||
static int dma_tx_fragment(struct b43_dmaring *ring,
|
||||
struct sk_buff **in_skb)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *skb = *in_skb;
|
||||
const struct b43_dma_ops *ops = ring->ops;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct b43_private_tx_info *priv_info = b43_get_priv_tx_info(info);
|
||||
u8 *header;
|
||||
int slot, old_top_slot, old_used_slots;
|
||||
int err;
|
||||
struct b43_dmadesc_generic *desc;
|
||||
struct b43_dmadesc_meta *meta;
|
||||
struct b43_dmadesc_meta *meta_hdr;
|
||||
struct sk_buff *bounce_skb;
|
||||
u16 cookie;
|
||||
size_t hdrsize = b43_txhdr_size(ring->dev);
|
||||
|
||||
@ -1212,34 +1211,28 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
||||
|
||||
meta->skb = skb;
|
||||
meta->is_last_fragment = 1;
|
||||
priv_info->bouncebuffer = NULL;
|
||||
|
||||
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
|
||||
/* create a bounce buffer in zone_dma on mapping failure. */
|
||||
if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
|
||||
bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
|
||||
if (!bounce_skb) {
|
||||
priv_info->bouncebuffer = kmalloc(skb->len, GFP_ATOMIC | GFP_DMA);
|
||||
if (!priv_info->bouncebuffer) {
|
||||
ring->current_slot = old_top_slot;
|
||||
ring->used_slots = old_used_slots;
|
||||
err = -ENOMEM;
|
||||
goto out_unmap_hdr;
|
||||
}
|
||||
memcpy(priv_info->bouncebuffer, skb->data, skb->len);
|
||||
|
||||
memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
|
||||
memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
|
||||
bounce_skb->dev = skb->dev;
|
||||
skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
|
||||
info = IEEE80211_SKB_CB(bounce_skb);
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = bounce_skb;
|
||||
*in_skb = bounce_skb;
|
||||
meta->skb = skb;
|
||||
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
|
||||
meta->dmaaddr = map_descbuffer(ring, priv_info->bouncebuffer, skb->len, 1);
|
||||
if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
|
||||
kfree(priv_info->bouncebuffer);
|
||||
priv_info->bouncebuffer = NULL;
|
||||
ring->current_slot = old_top_slot;
|
||||
ring->used_slots = old_used_slots;
|
||||
err = -EIO;
|
||||
goto out_free_bounce;
|
||||
goto out_unmap_hdr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1256,8 +1249,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
||||
ops->poke_tx(ring, next_slot(ring, slot));
|
||||
return 0;
|
||||
|
||||
out_free_bounce:
|
||||
dev_kfree_skb_any(skb);
|
||||
out_unmap_hdr:
|
||||
unmap_descbuffer(ring, meta_hdr->dmaaddr,
|
||||
hdrsize, 1);
|
||||
@ -1362,11 +1353,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
|
||||
* static, so we don't need to store it per frame. */
|
||||
ring->queue_prio = skb_get_queue_mapping(skb);
|
||||
|
||||
/* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
|
||||
* into the skb data or cb now. */
|
||||
hdr = NULL;
|
||||
info = NULL;
|
||||
err = dma_tx_fragment(ring, &skb);
|
||||
err = dma_tx_fragment(ring, skb);
|
||||
if (unlikely(err == -ENOKEY)) {
|
||||
/* Drop this packet, as we don't have the encryption key
|
||||
* anymore and must not transmit it unencrypted. */
|
||||
@ -1413,12 +1400,17 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
||||
B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
|
||||
desc = ops->idx2desc(ring, slot, &meta);
|
||||
|
||||
if (meta->skb)
|
||||
unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len,
|
||||
1);
|
||||
else
|
||||
if (meta->skb) {
|
||||
struct b43_private_tx_info *priv_info =
|
||||
b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
|
||||
|
||||
unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
|
||||
kfree(priv_info->bouncebuffer);
|
||||
priv_info->bouncebuffer = NULL;
|
||||
} else {
|
||||
unmap_descbuffer(ring, meta->dmaaddr,
|
||||
b43_txhdr_size(dev), 1);
|
||||
}
|
||||
|
||||
if (meta->is_last_fragment) {
|
||||
struct ieee80211_tx_info *info;
|
||||
|
@ -761,7 +761,11 @@ data_ready:
|
||||
rx_error:
|
||||
if (err_msg)
|
||||
b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
|
||||
b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
|
||||
if (q->rev >= 8)
|
||||
b43_piorx_write32(q, B43_PIO8_RXCTL, B43_PIO8_RXCTL_DATARDY);
|
||||
else
|
||||
b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
#define B43_XMIT_H_
|
||||
|
||||
#include "main.h"
|
||||
#include <net/mac80211.h>
|
||||
|
||||
|
||||
#define _b43_declare_plcp_hdr(size) \
|
||||
struct b43_plcp_hdr##size { \
|
||||
@ -332,4 +334,21 @@ static inline u8 b43_kidx_to_raw(struct b43_wldev *dev, u8 firmware_kidx)
|
||||
return raw_kidx;
|
||||
}
|
||||
|
||||
/* struct b43_private_tx_info - TX info private to b43.
|
||||
* The structure is placed in (struct ieee80211_tx_info *)->rate_driver_data
|
||||
*
|
||||
* @bouncebuffer: DMA Bouncebuffer (if used)
|
||||
*/
|
||||
struct b43_private_tx_info {
|
||||
void *bouncebuffer;
|
||||
};
|
||||
|
||||
static inline struct b43_private_tx_info *
|
||||
b43_get_priv_tx_info(struct ieee80211_tx_info *info)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(struct b43_private_tx_info) >
|
||||
sizeof(info->rate_driver_data));
|
||||
return (struct b43_private_tx_info *)info->rate_driver_data;
|
||||
}
|
||||
|
||||
#endif /* B43_XMIT_H_ */
|
||||
|
@ -8462,6 +8462,12 @@ static int ipw2100_get_firmware(struct ipw2100_priv *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_FIRMWARE(IPW2100_FW_NAME("-i"));
|
||||
#ifdef CONFIG_IPW2100_MONITOR
|
||||
MODULE_FIRMWARE(IPW2100_FW_NAME("-p"));
|
||||
#endif
|
||||
MODULE_FIRMWARE(IPW2100_FW_NAME(""));
|
||||
|
||||
static void ipw2100_release_firmware(struct ipw2100_priv *priv,
|
||||
struct ipw2100_fw *fw)
|
||||
{
|
||||
|
@ -80,6 +80,11 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_AUTHOR(DRV_COPYRIGHT);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("ipw2200-ibss.fw");
|
||||
#ifdef CONFIG_IPW2200_MONITOR
|
||||
MODULE_FIRMWARE("ipw2200-sniffer.fw");
|
||||
#endif
|
||||
MODULE_FIRMWARE("ipw2200-bss.fw");
|
||||
|
||||
static int cmdlog = 0;
|
||||
static int debug = 0;
|
||||
|
@ -564,7 +564,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
|
||||
return;
|
||||
}
|
||||
|
||||
skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
|
||||
skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
IWL_ERR(priv, "alloc_skb failed\n");
|
||||
return;
|
||||
@ -575,6 +575,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
|
||||
(struct ieee80211_hdr *)rxb_addr(rxb),
|
||||
le32_to_cpu(rx_end->status), stats);
|
||||
|
||||
skb_reserve(skb, IWL_LINK_HDR_MAX);
|
||||
skb_add_rx_frag(skb, 0, rxb->page,
|
||||
(void *)rx_hdr->payload - (void *)pkt, len);
|
||||
|
||||
|
@ -1449,14 +1449,14 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
|
||||
|
||||
if (is_ht40 &&
|
||||
(priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
|
||||
(priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
|
||||
ctrl_chan_high = 1;
|
||||
|
||||
cmd.band = band;
|
||||
cmd.expect_beacon = 0;
|
||||
cmd.channel = cpu_to_le16(channel);
|
||||
cmd.rxon_flags = priv->active_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->active_rxon.filter_flags;
|
||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
if (ch_info)
|
||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
@ -1473,8 +1473,10 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
|
||||
return rc;
|
||||
priv->switch_rxon.channel = cpu_to_le16(channel);
|
||||
priv->switch_rxon.switch_in_progress = true;
|
||||
|
||||
return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2228,7 +2230,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
|
||||
.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl4965_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = true,
|
||||
|
@ -661,9 +661,13 @@ int iwl5000_alive_notify(struct iwl_priv *priv)
|
||||
iwl_txq_ctx_activate(priv, i);
|
||||
iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
|
||||
}
|
||||
/* TODO - need to initialize those FIFOs inside the loop above,
|
||||
* not only mark them as active */
|
||||
iwl_txq_ctx_activate(priv, 4);
|
||||
|
||||
/*
|
||||
* TODO - need to initialize these queues and map them to FIFOs
|
||||
* in the loop above, not only mark them as active. We do this
|
||||
* because we want the first aggregation queue to be queue #10,
|
||||
* but do not use 8 or 9 otherwise yet.
|
||||
*/
|
||||
iwl_txq_ctx_activate(priv, 7);
|
||||
iwl_txq_ctx_activate(priv, 8);
|
||||
iwl_txq_ctx_activate(priv, 9);
|
||||
@ -1387,8 +1391,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
priv->active_rxon.channel, channel);
|
||||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
cmd.channel = cpu_to_le16(channel);
|
||||
cmd.rxon_flags = priv->active_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->active_rxon.filter_flags;
|
||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, channel);
|
||||
if (ch_info)
|
||||
@ -1398,6 +1402,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
priv->active_rxon.channel, channel);
|
||||
return -EFAULT;
|
||||
}
|
||||
priv->switch_rxon.channel = cpu_to_le16(channel);
|
||||
priv->switch_rxon.switch_in_progress = true;
|
||||
|
||||
return iwl_send_cmd_sync(priv, &hcmd);
|
||||
}
|
||||
|
@ -90,11 +90,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
|
||||
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
|
||||
|
||||
/* no locking required for register write */
|
||||
if (priv->cfg->pa_type == IWL_PA_HYBRID) {
|
||||
/* 2x2 hybrid phy type */
|
||||
iwl_write32(priv, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB);
|
||||
} else if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
|
||||
if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
|
||||
/* 2x2 IPA phy type */
|
||||
iwl_write32(priv, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
|
||||
@ -166,9 +162,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
BIT(IWL_CALIB_XTAL) |
|
||||
BIT(IWL_CALIB_LO) |
|
||||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_TX_IQ_PERD) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -188,8 +182,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
|
||||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
cmd.channel = cpu_to_le16(channel);
|
||||
cmd.rxon_flags = priv->active_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->active_rxon.filter_flags;
|
||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, channel);
|
||||
if (ch_info)
|
||||
@ -199,6 +193,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
priv->active_rxon.channel, channel);
|
||||
return -EFAULT;
|
||||
}
|
||||
priv->switch_rxon.channel = cpu_to_le16(channel);
|
||||
priv->switch_rxon.switch_in_progress = true;
|
||||
|
||||
return iwl_send_cmd_sync(priv, &hcmd);
|
||||
}
|
||||
@ -279,98 +275,6 @@ static struct iwl_ops iwl6050_ops = {
|
||||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* "h": Hybrid configuration, use both internal and external Power Amplifier
|
||||
*/
|
||||
struct iwl_cfg iwl6000h_2agn_cfg = {
|
||||
.name = "6000 Series 2x2 AGN",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_HYBRID,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000h_2abg_cfg = {
|
||||
.name = "6000 Series 2x2 ABG",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_HYBRID,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000h_2bg_cfg = {
|
||||
.name = "6000 Series 2x2 BG",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_HYBRID,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
/*
|
||||
* "i": Internal configuration, use internal Power Amplifier
|
||||
*/
|
||||
|
@ -122,6 +122,17 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* receive commit_rxon request
|
||||
* abort any previous channel switch if still in process
|
||||
*/
|
||||
if (priv->switch_rxon.switch_in_progress &&
|
||||
(priv->switch_rxon.channel != priv->staging_rxon.channel)) {
|
||||
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
|
||||
le16_to_cpu(priv->switch_rxon.channel));
|
||||
priv->switch_rxon.switch_in_progress = false;
|
||||
}
|
||||
|
||||
/* If we don't need to send a full RXON, we can use
|
||||
* iwl_rxon_assoc_cmd which is used to reconfigure filter
|
||||
* and other flags for the current radio configuration. */
|
||||
@ -133,6 +144,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
||||
}
|
||||
|
||||
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
|
||||
iwl_print_rx_config_cmd(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -228,6 +240,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
||||
}
|
||||
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
|
||||
}
|
||||
iwl_print_rx_config_cmd(priv);
|
||||
|
||||
iwl_init_sensitivity(priv);
|
||||
|
||||
@ -1071,6 +1084,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
|
||||
u32 inta = 0;
|
||||
u32 handled = 0;
|
||||
unsigned long flags;
|
||||
u32 i;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
u32 inta_mask;
|
||||
#endif
|
||||
@ -1181,12 +1195,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
|
||||
if (inta & CSR_INT_BIT_WAKEUP) {
|
||||
IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
|
||||
iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
|
||||
iwl_txq_update_write_ptr(priv, &priv->txq[0]);
|
||||
iwl_txq_update_write_ptr(priv, &priv->txq[1]);
|
||||
iwl_txq_update_write_ptr(priv, &priv->txq[2]);
|
||||
iwl_txq_update_write_ptr(priv, &priv->txq[3]);
|
||||
iwl_txq_update_write_ptr(priv, &priv->txq[4]);
|
||||
iwl_txq_update_write_ptr(priv, &priv->txq[5]);
|
||||
for (i = 0; i < priv->hw_params.max_txq_num; i++)
|
||||
iwl_txq_update_write_ptr(priv, &priv->txq[i]);
|
||||
|
||||
priv->isr_stats.wakeup++;
|
||||
|
||||
@ -1653,6 +1663,7 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||
u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
|
||||
u32 ptr; /* SRAM byte address of log data */
|
||||
u32 ev, time, data; /* event log data */
|
||||
unsigned long reg_flags;
|
||||
|
||||
if (num_events == 0)
|
||||
return;
|
||||
@ -1668,27 +1679,39 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||
|
||||
ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
|
||||
|
||||
/* Make sure device is powered up for SRAM reads */
|
||||
spin_lock_irqsave(&priv->reg_lock, reg_flags);
|
||||
iwl_grab_nic_access(priv);
|
||||
|
||||
/* Set starting address; reads will auto-increment */
|
||||
_iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
|
||||
rmb();
|
||||
|
||||
/* "time" is actually "data" for mode 0 (no timestamp).
|
||||
* place event id # at far right for easier visual parsing. */
|
||||
for (i = 0; i < num_events; i++) {
|
||||
ev = iwl_read_targ_mem(priv, ptr);
|
||||
ptr += sizeof(u32);
|
||||
time = iwl_read_targ_mem(priv, ptr);
|
||||
ptr += sizeof(u32);
|
||||
ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
|
||||
time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
|
||||
if (mode == 0) {
|
||||
/* data, ev */
|
||||
trace_iwlwifi_dev_ucode_event(priv, 0, time, ev);
|
||||
IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
|
||||
} else {
|
||||
data = iwl_read_targ_mem(priv, ptr);
|
||||
ptr += sizeof(u32);
|
||||
data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
|
||||
IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
|
||||
time, data, ev);
|
||||
trace_iwlwifi_dev_ucode_event(priv, time, data, ev);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow device to power down */
|
||||
iwl_release_nic_access(priv);
|
||||
spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
|
||||
}
|
||||
|
||||
/* For sanity check only. Actual size is determined by uCode, typ. 512 */
|
||||
#define MAX_EVENT_LOG_SIZE (512)
|
||||
|
||||
void iwl_dump_nic_event_log(struct iwl_priv *priv)
|
||||
{
|
||||
u32 base; /* SRAM byte address of event log header */
|
||||
@ -1714,6 +1737,18 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
|
||||
num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
|
||||
next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
|
||||
|
||||
if (capacity > MAX_EVENT_LOG_SIZE) {
|
||||
IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
|
||||
capacity, MAX_EVENT_LOG_SIZE);
|
||||
capacity = MAX_EVENT_LOG_SIZE;
|
||||
}
|
||||
|
||||
if (next_entry > MAX_EVENT_LOG_SIZE) {
|
||||
IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
|
||||
next_entry, MAX_EVENT_LOG_SIZE);
|
||||
next_entry = MAX_EVENT_LOG_SIZE;
|
||||
}
|
||||
|
||||
size = num_wraps ? capacity : next_entry;
|
||||
|
||||
/* bail out if nothing in log */
|
||||
@ -1899,19 +1934,17 @@ static void __iwl_down(struct iwl_priv *priv)
|
||||
|
||||
/* device going down, Stop using ICT table */
|
||||
iwl_disable_ict(priv);
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
iwl_clear_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
iwl_txq_ctx_stop(priv);
|
||||
iwl_rxq_stop(priv);
|
||||
|
||||
iwl_write_prph(priv, APMG_CLK_DIS_REG,
|
||||
APMG_CLK_VAL_DMA_CLK_RQT);
|
||||
|
||||
/* Power-down device's busmaster DMA clocks */
|
||||
iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
|
||||
udelay(5);
|
||||
|
||||
/* Make sure (redundant) we've released our request to stay awake */
|
||||
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
|
||||
/* Stop the device, and put it in low power state */
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
|
||||
@ -3439,14 +3472,6 @@ static struct pci_device_id iwl_hw_card_ids[] = {
|
||||
{IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
|
||||
|
||||
/* 6x00 Series */
|
||||
{IWL_PCI_DEVICE(0x008D, 0x1301, iwl6000h_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008D, 0x1321, iwl6000h_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008D, 0x1326, iwl6000h_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008D, 0x1306, iwl6000h_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008D, 0x1307, iwl6000h_2bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008E, 0x1311, iwl6000h_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008E, 0x1316, iwl6000h_2abg_cfg)},
|
||||
|
||||
{IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
|
||||
|
@ -2566,9 +2566,10 @@ struct iwl_scan_channel {
|
||||
/**
|
||||
* struct iwl_ssid_ie - directed scan network information element
|
||||
*
|
||||
* Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field
|
||||
* in struct iwl_scan_channel; each channel may select different ssids from
|
||||
* among the 4 entries. SSID IEs get transmitted in reverse order of entry.
|
||||
* Up to 20 of these may appear in REPLY_SCAN_CMD (Note: Only 4 are in
|
||||
* 3945 SCAN api), selected by "type" bit field in struct iwl_scan_channel;
|
||||
* each channel may select different ssids from among the 20 (4) entries.
|
||||
* SSID IEs get transmitted in reverse order of entry.
|
||||
*/
|
||||
struct iwl_ssid_ie {
|
||||
u8 id;
|
||||
|
@ -1316,19 +1316,24 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
|
||||
struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
|
||||
|
||||
if (!le32_to_cpu(csa->status)) {
|
||||
rxon->channel = csa->channel;
|
||||
priv->staging_rxon.channel = csa->channel;
|
||||
IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
|
||||
le16_to_cpu(csa->channel));
|
||||
} else
|
||||
IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
|
||||
le16_to_cpu(csa->channel));
|
||||
if (priv->switch_rxon.switch_in_progress) {
|
||||
if (!le32_to_cpu(csa->status) &&
|
||||
(csa->channel == priv->switch_rxon.channel)) {
|
||||
rxon->channel = csa->channel;
|
||||
priv->staging_rxon.channel = csa->channel;
|
||||
IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
|
||||
le16_to_cpu(csa->channel));
|
||||
} else
|
||||
IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
|
||||
le16_to_cpu(csa->channel));
|
||||
|
||||
priv->switch_rxon.switch_in_progress = false;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rx_csa);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
|
||||
void iwl_print_rx_config_cmd(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
|
||||
|
||||
@ -1346,6 +1351,7 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
|
||||
IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
|
||||
IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_print_rx_config_cmd);
|
||||
#endif
|
||||
/**
|
||||
* iwl_irq_handle_error - called for HW or SW error interrupt from card
|
||||
@ -2310,12 +2316,6 @@ static void iwl_ht_conf(struct iwl_priv *priv,
|
||||
>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
|
||||
maxstreams += 1;
|
||||
|
||||
ht_conf->sm_ps =
|
||||
(u8)((ht_cap->cap & IEEE80211_HT_CAP_SM_PS)
|
||||
>> 2);
|
||||
IWL_DEBUG_MAC80211(priv, "sm_ps: 0x%x\n",
|
||||
ht_conf->sm_ps);
|
||||
|
||||
if ((ht_cap->mcs.rx_mask[1] == 0) &&
|
||||
(ht_cap->mcs.rx_mask[2] == 0))
|
||||
ht_conf->single_chain_sufficient = true;
|
||||
@ -2689,14 +2689,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
goto set_ch_out;
|
||||
}
|
||||
|
||||
if (iwl_is_associated(priv) &&
|
||||
(le16_to_cpu(priv->active_rxon.channel) != ch) &&
|
||||
priv->cfg->ops->lib->set_channel_switch) {
|
||||
ret = priv->cfg->ops->lib->set_channel_switch(priv,
|
||||
ch);
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* Configure HT40 channels */
|
||||
@ -2731,6 +2723,22 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
iwl_set_flags_for_band(priv, conf->channel->band);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
if (iwl_is_associated(priv) &&
|
||||
(le16_to_cpu(priv->active_rxon.channel) != ch) &&
|
||||
priv->cfg->ops->lib->set_channel_switch) {
|
||||
iwl_set_rate(priv);
|
||||
/*
|
||||
* at this point, staging_rxon has the
|
||||
* configuration for channel switch
|
||||
*/
|
||||
ret = priv->cfg->ops->lib->set_channel_switch(priv,
|
||||
ch);
|
||||
if (!ret) {
|
||||
iwl_print_rx_config_cmd(priv);
|
||||
goto out;
|
||||
}
|
||||
priv->switch_rxon.switch_in_progress = false;
|
||||
}
|
||||
set_ch_out:
|
||||
/* The list of supported rates and rate mask can be different
|
||||
* for each band; since the band may have changed, reset
|
||||
|
@ -579,6 +579,7 @@ int iwl_pci_resume(struct pci_dev *pdev);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
void iwl_dump_nic_event_log(struct iwl_priv *priv);
|
||||
void iwl_dump_nic_error_log(struct iwl_priv *priv);
|
||||
void iwl_print_rx_config_cmd(struct iwl_priv *priv);
|
||||
#else
|
||||
static inline void iwl_dump_nic_event_log(struct iwl_priv *priv)
|
||||
{
|
||||
@ -587,6 +588,10 @@ static inline void iwl_dump_nic_event_log(struct iwl_priv *priv)
|
||||
static inline void iwl_dump_nic_error_log(struct iwl_priv *priv)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void iwl_clear_isr_stats(struct iwl_priv *priv);
|
||||
|
@ -324,8 +324,9 @@ struct iwl_channel_info {
|
||||
#define IWL_MIN_NUM_QUEUES 10
|
||||
|
||||
/*
|
||||
* uCode queue management definitions ...
|
||||
* Queue #4 is the command queue for 3945/4965/5x00/1000/6x00.
|
||||
* Queue #4 is the command queue for 3945/4965/5x00/1000/6x00,
|
||||
* the driver maps it into the appropriate device FIFO for the
|
||||
* uCode.
|
||||
*/
|
||||
#define IWL_CMD_QUEUE_NUM 4
|
||||
|
||||
@ -926,13 +927,11 @@ enum iwl_access_mode {
|
||||
/**
|
||||
* enum iwl_pa_type - Power Amplifier type
|
||||
* @IWL_PA_SYSTEM: based on uCode configuration
|
||||
* @IWL_PA_HYBRID: use both Internal and external PA
|
||||
* @IWL_PA_INTERNAL: use Internal only
|
||||
*/
|
||||
enum iwl_pa_type {
|
||||
IWL_PA_SYSTEM = 0,
|
||||
IWL_PA_HYBRID = 1,
|
||||
IWL_PA_INTERNAL = 2,
|
||||
IWL_PA_INTERNAL = 1,
|
||||
};
|
||||
|
||||
/* interrupt statistics */
|
||||
@ -993,6 +992,17 @@ struct traffic_stats {
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* iwl_switch_rxon: "channel switch" structure
|
||||
*
|
||||
* @ switch_in_progress: channel switch in progress
|
||||
* @ channel: new channel
|
||||
*/
|
||||
struct iwl_switch_rxon {
|
||||
bool switch_in_progress;
|
||||
__le16 channel;
|
||||
};
|
||||
|
||||
struct iwl_priv {
|
||||
|
||||
/* ieee device used by generic ieee processing code */
|
||||
@ -1086,7 +1096,7 @@ struct iwl_priv {
|
||||
const struct iwl_rxon_cmd active_rxon;
|
||||
struct iwl_rxon_cmd staging_rxon;
|
||||
|
||||
struct iwl_rxon_cmd recovery_rxon;
|
||||
struct iwl_switch_rxon switch_rxon;
|
||||
|
||||
/* 1st responses from initialize and runtime uCode images.
|
||||
* 4965's initialize alive response contains some calibration data. */
|
||||
|
@ -199,13 +199,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
|
||||
IWL_DEBUG_INFO(priv, "Command %s aborted: RF KILL Switch\n",
|
||||
IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n",
|
||||
get_cmd_string(cmd->id));
|
||||
ret = -ECANCELED;
|
||||
goto fail;
|
||||
}
|
||||
if (test_bit(STATUS_FW_ERROR, &priv->status)) {
|
||||
IWL_DEBUG_INFO(priv, "Command %s failed: FW Error\n",
|
||||
IWL_ERR(priv, "Command %s failed: FW Error\n",
|
||||
get_cmd_string(cmd->id));
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
|
@ -200,6 +200,26 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
|
||||
|
||||
/* this bit wakes up the NIC */
|
||||
_iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
|
||||
/*
|
||||
* These bits say the device is running, and should keep running for
|
||||
* at least a short while (at least as long as MAC_ACCESS_REQ stays 1),
|
||||
* but they do not indicate that embedded SRAM is restored yet;
|
||||
* 3945 and 4965 have volatile SRAM, and must save/restore contents
|
||||
* to/from host DRAM when sleeping/waking for power-saving.
|
||||
* Each direction takes approximately 1/4 millisecond; with this
|
||||
* overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a
|
||||
* series of register accesses are expected (e.g. reading Event Log),
|
||||
* to keep device from sleeping.
|
||||
*
|
||||
* CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that
|
||||
* SRAM is okay/restored. We don't check that here because this call
|
||||
* is just for hardware register access; but GP1 MAC_SLEEP check is a
|
||||
* good idea before accessing 3945/4965 SRAM (e.g. reading Event Log).
|
||||
*
|
||||
* 5000 series and later (including 1000 series) have non-volatile SRAM,
|
||||
* and do not save/restore SRAM when power cycling.
|
||||
*/
|
||||
ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
|
||||
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
|
||||
|
@ -254,7 +254,8 @@
|
||||
* device. A queue maps to only one (selectable by driver) Tx DMA channel,
|
||||
* but one DMA channel may take input from several queues.
|
||||
*
|
||||
* Tx DMA channels have dedicated purposes. For 4965, they are used as follows:
|
||||
* Tx DMA channels have dedicated purposes. For 4965, they are used as follows
|
||||
* (cf. default_queue_to_tx_fifo in iwl-4965.c):
|
||||
*
|
||||
* 0 -- EDCA BK (background) frames, lowest priority
|
||||
* 1 -- EDCA BE (best effort) frames, normal priority
|
||||
@ -265,9 +266,21 @@
|
||||
* 6 -- HCCA long frames
|
||||
* 7 -- not used by driver (device-internal only)
|
||||
*
|
||||
* For 5000 series and up, they are used slightly differently
|
||||
* (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c):
|
||||
*
|
||||
* 0 -- EDCA BK (background) frames, lowest priority
|
||||
* 1 -- EDCA BE (best effort) frames, normal priority
|
||||
* 2 -- EDCA VI (video) frames, higher priority
|
||||
* 3 -- EDCA VO (voice) and management frames, highest priority
|
||||
* 4 -- (TBD)
|
||||
* 5 -- HCCA short frames
|
||||
* 6 -- HCCA long frames
|
||||
* 7 -- Commands
|
||||
*
|
||||
* Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.
|
||||
* In addition, driver can map queues 7-15 to Tx DMA/FIFO channels 0-3 to
|
||||
* support 11n aggregation via EDCA DMA channels.
|
||||
* In addition, driver can map the remaining queues to Tx DMA/FIFO
|
||||
* channels 0-3 to support 11n aggregation via EDCA DMA channels.
|
||||
*
|
||||
* The driver sets up each queue to work in one of two modes:
|
||||
*
|
||||
|
@ -140,6 +140,8 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
|
||||
reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
|
||||
|
||||
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
|
||||
IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup, GP1 = 0x%x\n",
|
||||
reg);
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
goto exit_unlock;
|
||||
@ -937,12 +939,13 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
|
||||
iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
|
||||
return;
|
||||
|
||||
skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
|
||||
skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
IWL_ERR(priv, "alloc_skb failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
skb_reserve(skb, IWL_LINK_HDR_MAX);
|
||||
skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
|
||||
|
||||
/* mac80211 currently doesn't support paged SKB. Convert it to
|
||||
|
@ -581,6 +581,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
|
||||
u8 rate;
|
||||
bool is_active = false;
|
||||
int chan_mod;
|
||||
u8 active_chains;
|
||||
|
||||
conf = ieee80211_get_hw_conf(priv->hw);
|
||||
|
||||
@ -734,9 +735,22 @@ static void iwl_bg_request_scan(struct work_struct *data)
|
||||
rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
|
||||
scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
|
||||
|
||||
/* In power save mode use one chain, otherwise use all chains */
|
||||
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
|
||||
/* rx_ant has been set to all valid chains previously */
|
||||
active_chains = rx_ant &
|
||||
((u8)(priv->chain_noise_data.active_chains));
|
||||
if (!active_chains)
|
||||
active_chains = rx_ant;
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
|
||||
priv->chain_noise_data.active_chains);
|
||||
|
||||
rx_ant = first_antenna(active_chains);
|
||||
}
|
||||
/* MIMO is not used here, but value is required */
|
||||
rx_chain |= ANT_ABC << RXON_RX_CHAIN_VALID_POS;
|
||||
rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
|
||||
rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
|
||||
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
|
||||
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
|
||||
rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
|
||||
scan->rx_chain = cpu_to_le16(rx_chain);
|
||||
|
@ -96,7 +96,8 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
|
||||
reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
|
||||
|
||||
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
|
||||
IWL_DEBUG_INFO(priv, "Requesting wakeup, GP1 = 0x%x\n", reg);
|
||||
IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup, GP1 = 0x%x\n",
|
||||
txq_id, reg);
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
return ret;
|
||||
@ -364,8 +365,13 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
|
||||
|
||||
txq->need_update = 0;
|
||||
|
||||
/* aggregation TX queues will get their ID when aggregation begins */
|
||||
if (txq_id <= IWL_TX_FIFO_AC3)
|
||||
/*
|
||||
* Aggregation TX queues will get their ID when aggregation begins;
|
||||
* they overwrite the setting done here. The command FIFO doesn't
|
||||
* need an swq_id so don't set one to catch errors, all others can
|
||||
* be set up to the identity mapping.
|
||||
*/
|
||||
if (txq_id != IWL_CMD_QUEUE_NUM)
|
||||
txq->swq_id = txq_id;
|
||||
|
||||
/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
|
||||
|
@ -1570,6 +1570,7 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||
u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
|
||||
u32 ptr; /* SRAM byte address of log data */
|
||||
u32 ev, time, data; /* event log data */
|
||||
unsigned long reg_flags;
|
||||
|
||||
if (num_events == 0)
|
||||
return;
|
||||
@ -1583,26 +1584,38 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||
|
||||
ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
|
||||
|
||||
/* Make sure device is powered up for SRAM reads */
|
||||
spin_lock_irqsave(&priv->reg_lock, reg_flags);
|
||||
iwl_grab_nic_access(priv);
|
||||
|
||||
/* Set starting address; reads will auto-increment */
|
||||
_iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
|
||||
rmb();
|
||||
|
||||
/* "time" is actually "data" for mode 0 (no timestamp).
|
||||
* place event id # at far right for easier visual parsing. */
|
||||
for (i = 0; i < num_events; i++) {
|
||||
ev = iwl_read_targ_mem(priv, ptr);
|
||||
ptr += sizeof(u32);
|
||||
time = iwl_read_targ_mem(priv, ptr);
|
||||
ptr += sizeof(u32);
|
||||
ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
|
||||
time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
|
||||
if (mode == 0) {
|
||||
/* data, ev */
|
||||
IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
|
||||
trace_iwlwifi_dev_ucode_event(priv, 0, time, ev);
|
||||
} else {
|
||||
data = iwl_read_targ_mem(priv, ptr);
|
||||
ptr += sizeof(u32);
|
||||
data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
|
||||
IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev);
|
||||
trace_iwlwifi_dev_ucode_event(priv, time, data, ev);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow device to power down */
|
||||
iwl_release_nic_access(priv);
|
||||
spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
|
||||
}
|
||||
|
||||
/* For sanity check only. Actual size is determined by uCode, typ. 512 */
|
||||
#define IWL3945_MAX_EVENT_LOG_SIZE (512)
|
||||
|
||||
void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
|
||||
{
|
||||
u32 base; /* SRAM byte address of event log header */
|
||||
@ -1624,6 +1637,18 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
|
||||
num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
|
||||
next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
|
||||
|
||||
if (capacity > IWL3945_MAX_EVENT_LOG_SIZE) {
|
||||
IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
|
||||
capacity, IWL3945_MAX_EVENT_LOG_SIZE);
|
||||
capacity = IWL3945_MAX_EVENT_LOG_SIZE;
|
||||
}
|
||||
|
||||
if (next_entry > IWL3945_MAX_EVENT_LOG_SIZE) {
|
||||
IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
|
||||
next_entry, IWL3945_MAX_EVENT_LOG_SIZE);
|
||||
next_entry = IWL3945_MAX_EVENT_LOG_SIZE;
|
||||
}
|
||||
|
||||
size = num_wraps ? capacity : next_entry;
|
||||
|
||||
/* bail out if nothing in log */
|
||||
@ -2575,9 +2600,8 @@ static void __iwl3945_down(struct iwl_priv *priv)
|
||||
iwl3945_hw_txq_ctx_stop(priv);
|
||||
iwl3945_hw_rxq_stop(priv);
|
||||
|
||||
iwl_write_prph(priv, APMG_CLK_DIS_REG,
|
||||
APMG_CLK_VAL_DMA_CLK_RQT);
|
||||
|
||||
/* Power-down device's busmaster DMA clocks */
|
||||
iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
|
||||
udelay(5);
|
||||
|
||||
/* Stop the device, and put it in low power state */
|
||||
|
@ -399,6 +399,9 @@ static struct iwm_if_ops if_sdio_ops = {
|
||||
.calib_lmac_name = "iwmc3200wifi-calib-sdio.bin",
|
||||
.lmac_name = "iwmc3200wifi-lmac-sdio.bin",
|
||||
};
|
||||
MODULE_FIRMWARE("iwmc3200wifi-umac-sdio.bin");
|
||||
MODULE_FIRMWARE("iwmc3200wifi-calib-sdio.bin");
|
||||
MODULE_FIRMWARE("iwmc3200wifi-lmac-sdio.bin");
|
||||
|
||||
static int iwm_sdio_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
|
@ -48,6 +48,7 @@
|
||||
MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>");
|
||||
MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("libertas_cs_helper.fw");
|
||||
|
||||
|
||||
|
||||
|
@ -99,6 +99,12 @@ static struct if_sdio_model if_sdio_models[] = {
|
||||
.firmware = "sd8688.bin",
|
||||
},
|
||||
};
|
||||
MODULE_FIRMWARE("sd8385_helper.bin");
|
||||
MODULE_FIRMWARE("sd8385.bin");
|
||||
MODULE_FIRMWARE("sd8686_helper.bin");
|
||||
MODULE_FIRMWARE("sd8686.bin");
|
||||
MODULE_FIRMWARE("sd8688_helper.bin");
|
||||
MODULE_FIRMWARE("sd8688.bin");
|
||||
|
||||
struct if_sdio_packet {
|
||||
struct if_sdio_packet *next;
|
||||
|
@ -902,6 +902,10 @@ static int if_spi_calculate_fw_names(u16 card_id,
|
||||
chip_id_to_device_name[i].name);
|
||||
return 0;
|
||||
}
|
||||
MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
|
||||
MODULE_FIRMWARE("libertas/gspi8385.bin");
|
||||
MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
|
||||
MODULE_FIRMWARE("libertas/gspi8686.bin");
|
||||
|
||||
static int __devinit if_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
|
@ -28,6 +28,8 @@
|
||||
static char *lbs_fw_name = "usb8388.bin";
|
||||
module_param_named(fw_name, lbs_fw_name, charp, 0644);
|
||||
|
||||
MODULE_FIRMWARE("usb8388.bin");
|
||||
|
||||
static struct usb_device_id if_usb_table[] = {
|
||||
/* Enter the device signature inside */
|
||||
{ USB_DEVICE(0x1286, 0x2001) },
|
||||
|
@ -23,6 +23,8 @@
|
||||
static char *lbtf_fw_name = "lbtf_usb.bin";
|
||||
module_param_named(fw_name, lbtf_fw_name, charp, 0644);
|
||||
|
||||
MODULE_FIRMWARE("lbtf_usb.bin");
|
||||
|
||||
static struct usb_device_id if_usb_table[] = {
|
||||
/* Enter the device signature inside */
|
||||
{ USB_DEVICE(0x1286, 0x2001) },
|
||||
|
@ -400,6 +400,9 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_FIRMWARE("mwl8k/helper_8687.fw");
|
||||
MODULE_FIRMWARE("mwl8k/fmimage_8687.fw");
|
||||
|
||||
struct mwl8k_cmd_pkt {
|
||||
__le16 code;
|
||||
__le16 length;
|
||||
|
@ -28,6 +28,12 @@ static const struct fw_info orinoco_fw[] = {
|
||||
{ NULL, "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
|
||||
{ "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", NULL, 0x00003100, 512 }
|
||||
};
|
||||
MODULE_FIRMWARE("agere_sta_fw.bin");
|
||||
MODULE_FIRMWARE("agere_ap_fw.bin");
|
||||
MODULE_FIRMWARE("prism_sta_fw.bin");
|
||||
MODULE_FIRMWARE("prism_ap_fw.bin");
|
||||
MODULE_FIRMWARE("symbol_sp24t_prim_fw");
|
||||
MODULE_FIRMWARE("symbol_sp24t_sec_fw");
|
||||
|
||||
/* Structure used to access fields in FW
|
||||
* Make sure LE decoding macros are used
|
||||
|
@ -40,6 +40,9 @@
|
||||
#define ISL3877_IMAGE_FILE "isl3877"
|
||||
#define ISL3886_IMAGE_FILE "isl3886"
|
||||
#define ISL3890_IMAGE_FILE "isl3890"
|
||||
MODULE_FIRMWARE(ISL3877_IMAGE_FILE);
|
||||
MODULE_FIRMWARE(ISL3886_IMAGE_FILE);
|
||||
MODULE_FIRMWARE(ISL3890_IMAGE_FILE);
|
||||
|
||||
static int prism54_bring_down(islpci_private *);
|
||||
static int islpci_alloc_memory(islpci_private *);
|
||||
|
@ -2074,7 +2074,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)
|
||||
del_timer(&local->timer);
|
||||
local->timer.expires = jiffies + HZ * 5;
|
||||
local->timer.data = (long)local;
|
||||
if (status == CCS_START_NETWORK) {
|
||||
if (cmd == CCS_START_NETWORK) {
|
||||
DEBUG(0,
|
||||
"ray_cs interrupt network \"%s\" start failed\n",
|
||||
local->sparm.b4.a_current_ess_id);
|
||||
|
@ -1072,6 +1072,8 @@ static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version,
|
||||
auth_mode = NDIS_80211_AUTH_SHARED;
|
||||
else if (auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
|
||||
auth_mode = NDIS_80211_AUTH_OPEN;
|
||||
else if (auth_type == NL80211_AUTHTYPE_AUTOMATIC)
|
||||
auth_mode = NDIS_80211_AUTH_AUTO_SWITCH;
|
||||
else
|
||||
return -ENOTSUPP;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -1341,6 +1341,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2x00pci_register_read(rt2x00dev, CSR0, ®);
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2420) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2421)) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -1505,6 +1505,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2x00pci_register_read(rt2x00dev, CSR0, ®);
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2523) &&
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -715,139 +715,6 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
|
||||
qual->vgc_level = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: This function is directly ported from legacy driver, but
|
||||
* despite it being declared it was never called. Although link tuning
|
||||
* sounds like a good idea, and usually works well for the other drivers,
|
||||
* it does _not_ work with rt2500usb. Enabling this function will result
|
||||
* in TX capabilities only until association kicks in. Immediately
|
||||
* after the successful association all TX frames will be kept in the
|
||||
* hardware queue and never transmitted.
|
||||
*/
|
||||
#if 0
|
||||
static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
|
||||
u16 bbp_thresh;
|
||||
u16 vgc_bound;
|
||||
u16 sens;
|
||||
u16 r24;
|
||||
u16 r25;
|
||||
u16 r61;
|
||||
u16 r17_sens;
|
||||
u8 r17;
|
||||
u8 up_bound;
|
||||
u8 low_bound;
|
||||
|
||||
/*
|
||||
* Read current r17 value, as well as the sensitivity values
|
||||
* for the r17 register.
|
||||
*/
|
||||
rt2500usb_bbp_read(rt2x00dev, 17, &r17);
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound);
|
||||
up_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER);
|
||||
low_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCLOWER);
|
||||
|
||||
/*
|
||||
* If we are not associated, we should go straight to the
|
||||
* dynamic CCA tuning.
|
||||
*/
|
||||
if (!rt2x00dev->intf_associated)
|
||||
goto dynamic_cca_tune;
|
||||
|
||||
/*
|
||||
* Determine the BBP tuning threshold and correctly
|
||||
* set BBP 24, 25 and 61.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &bbp_thresh);
|
||||
bbp_thresh = rt2x00_get_field16(bbp_thresh, EEPROM_BBPTUNE_THRESHOLD);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &r24);
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &r25);
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &r61);
|
||||
|
||||
if ((rssi + bbp_thresh) > 0) {
|
||||
r24 = rt2x00_get_field16(r24, EEPROM_BBPTUNE_R24_HIGH);
|
||||
r25 = rt2x00_get_field16(r25, EEPROM_BBPTUNE_R25_HIGH);
|
||||
r61 = rt2x00_get_field16(r61, EEPROM_BBPTUNE_R61_HIGH);
|
||||
} else {
|
||||
r24 = rt2x00_get_field16(r24, EEPROM_BBPTUNE_R24_LOW);
|
||||
r25 = rt2x00_get_field16(r25, EEPROM_BBPTUNE_R25_LOW);
|
||||
r61 = rt2x00_get_field16(r61, EEPROM_BBPTUNE_R61_LOW);
|
||||
}
|
||||
|
||||
rt2500usb_bbp_write(rt2x00dev, 24, r24);
|
||||
rt2500usb_bbp_write(rt2x00dev, 25, r25);
|
||||
rt2500usb_bbp_write(rt2x00dev, 61, r61);
|
||||
|
||||
/*
|
||||
* A too low RSSI will cause too much false CCA which will
|
||||
* then corrupt the R17 tuning. To remidy this the tuning should
|
||||
* be stopped (While making sure the R17 value will not exceed limits)
|
||||
*/
|
||||
if (rssi >= -40) {
|
||||
if (r17 != 0x60)
|
||||
rt2500usb_bbp_write(rt2x00dev, 17, 0x60);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special big-R17 for short distance
|
||||
*/
|
||||
if (rssi >= -58) {
|
||||
sens = rt2x00_get_field16(r17_sens, EEPROM_BBPTUNE_R17_LOW);
|
||||
if (r17 != sens)
|
||||
rt2500usb_bbp_write(rt2x00dev, 17, sens);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special mid-R17 for middle distance
|
||||
*/
|
||||
if (rssi >= -74) {
|
||||
sens = rt2x00_get_field16(r17_sens, EEPROM_BBPTUNE_R17_HIGH);
|
||||
if (r17 != sens)
|
||||
rt2500usb_bbp_write(rt2x00dev, 17, sens);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Leave short or middle distance condition, restore r17
|
||||
* to the dynamic tuning range.
|
||||
*/
|
||||
low_bound = 0x32;
|
||||
if (rssi < -77)
|
||||
up_bound -= (-77 - rssi);
|
||||
|
||||
if (up_bound < low_bound)
|
||||
up_bound = low_bound;
|
||||
|
||||
if (r17 > up_bound) {
|
||||
rt2500usb_bbp_write(rt2x00dev, 17, up_bound);
|
||||
rt2x00dev->link.vgc_level = up_bound;
|
||||
return;
|
||||
}
|
||||
|
||||
dynamic_cca_tune:
|
||||
|
||||
/*
|
||||
* R17 is inside the dynamic tuning range,
|
||||
* start tuning the link based on the false cca counter.
|
||||
*/
|
||||
if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
|
||||
rt2500usb_bbp_write(rt2x00dev, 17, ++r17);
|
||||
rt2x00dev->link.vgc_level = r17;
|
||||
} else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
|
||||
rt2500usb_bbp_write(rt2x00dev, 17, --r17);
|
||||
rt2x00dev->link.vgc_level = r17;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define rt2500usb_link_tuner NULL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialization functions.
|
||||
*/
|
||||
@ -1542,6 +1409,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) ||
|
||||
rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
|
||||
@ -1910,7 +1778,6 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
|
||||
.rfkill_poll = rt2500usb_rfkill_poll,
|
||||
.link_stats = rt2500usb_link_stats,
|
||||
.reset_tuner = rt2500usb_reset_tuner,
|
||||
.link_tuner = rt2500usb_link_tuner,
|
||||
.write_tx_desc = rt2500usb_write_tx_desc,
|
||||
.write_tx_data = rt2x00usb_write_tx_data,
|
||||
.write_beacon = rt2500usb_write_beacon,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,12 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
|
||||
Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
|
||||
Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
|
||||
Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
|
||||
Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
|
||||
Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -361,6 +368,35 @@
|
||||
#define RF_CSR_CFG_WRITE FIELD32(0x00010000)
|
||||
#define RF_CSR_CFG_BUSY FIELD32(0x00020000)
|
||||
|
||||
/*
|
||||
* EFUSE_CSR: RT30x0 EEPROM
|
||||
*/
|
||||
#define EFUSE_CTRL 0x0580
|
||||
#define EFUSE_CTRL_ADDRESS_IN FIELD32(0x03fe0000)
|
||||
#define EFUSE_CTRL_MODE FIELD32(0x000000c0)
|
||||
#define EFUSE_CTRL_KICK FIELD32(0x40000000)
|
||||
#define EFUSE_CTRL_PRESENT FIELD32(0x80000000)
|
||||
|
||||
/*
|
||||
* EFUSE_DATA0
|
||||
*/
|
||||
#define EFUSE_DATA0 0x0590
|
||||
|
||||
/*
|
||||
* EFUSE_DATA1
|
||||
*/
|
||||
#define EFUSE_DATA1 0x0594
|
||||
|
||||
/*
|
||||
* EFUSE_DATA2
|
||||
*/
|
||||
#define EFUSE_DATA2 0x0598
|
||||
|
||||
/*
|
||||
* EFUSE_DATA3
|
||||
*/
|
||||
#define EFUSE_DATA3 0x059c
|
||||
|
||||
/*
|
||||
* MAC Control/Status Registers(CSR).
|
||||
* Some values are set in TU, whereas 1 TU == 1024 us.
|
||||
|
@ -1,9 +1,15 @@
|
||||
/*
|
||||
Copyright (C) 2009 Bartlomiej Zolnierkiewicz
|
||||
Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
|
||||
Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com>
|
||||
|
||||
Based on the original rt2800pci.c and rt2800usb.c:
|
||||
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Based on the original rt2800pci.c and rt2800usb.c.
|
||||
Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
|
||||
Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
|
||||
Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
|
||||
Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
|
||||
Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
|
||||
Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -555,7 +561,8 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
|
||||
rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®);
|
||||
rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1);
|
||||
rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync);
|
||||
rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1);
|
||||
rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE,
|
||||
(conf->sync == TSF_SYNC_BEACON));
|
||||
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
|
||||
}
|
||||
|
||||
@ -769,7 +776,7 @@ static void rt2800_config_channel_rt3x(struct rt2x00_dev *rt2x00dev,
|
||||
u8 rfcsr;
|
||||
|
||||
rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
|
||||
rt2800_rfcsr_write(rt2x00dev, 2, rf->rf3);
|
||||
rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);
|
||||
|
||||
rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
|
||||
rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2);
|
||||
@ -801,10 +808,15 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
unsigned int tx_pin;
|
||||
u8 bbp;
|
||||
|
||||
if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
|
||||
rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info);
|
||||
else
|
||||
if ((rt2x00_rt(&rt2x00dev->chip, RT3070) ||
|
||||
rt2x00_rt(&rt2x00dev->chip, RT3090)) &&
|
||||
(rt2x00_rf(&rt2x00dev->chip, RF2020) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF3020) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF3021) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF3022)))
|
||||
rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info);
|
||||
else
|
||||
rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info);
|
||||
|
||||
/*
|
||||
* Change BBP settings
|
||||
@ -1084,7 +1096,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||
/*
|
||||
* Wait untill BBP and RF are ready.
|
||||
* Wait until BBP and RF are ready.
|
||||
*/
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2800_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
@ -1659,6 +1671,466 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_init_rfcsr);
|
||||
|
||||
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
rt2800_register_read(rt2x00dev, EFUSE_CTRL, ®);
|
||||
|
||||
return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
|
||||
|
||||
static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, ®);
|
||||
rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i);
|
||||
rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0);
|
||||
rt2x00_set_field32(®, EFUSE_CTRL_KICK, 1);
|
||||
rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
|
||||
|
||||
/* Wait until the EEPROM has been loaded */
|
||||
rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, ®);
|
||||
|
||||
/* Apparently the data is read from end to start */
|
||||
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3,
|
||||
(u32 *)&rt2x00dev->eeprom[i]);
|
||||
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2,
|
||||
(u32 *)&rt2x00dev->eeprom[i + 2]);
|
||||
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1,
|
||||
(u32 *)&rt2x00dev->eeprom[i + 4]);
|
||||
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0,
|
||||
(u32 *)&rt2x00dev->eeprom[i + 6]);
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
}
|
||||
|
||||
void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8)
|
||||
rt2800_efuse_read(rt2x00dev, i);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse);
|
||||
|
||||
int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u16 word;
|
||||
u8 *mac;
|
||||
u8 default_lna_gain;
|
||||
|
||||
/*
|
||||
* Start validation of the data that has been read.
|
||||
*/
|
||||
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
if (!is_valid_ether_addr(mac)) {
|
||||
random_ether_addr(mac);
|
||||
EEPROM(rt2x00dev, "MAC: %pM\n", mac);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1);
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
|
||||
EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
|
||||
} else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) {
|
||||
/*
|
||||
* There is a max of 2 RX streams for RT28x0 series
|
||||
*/
|
||||
if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2)
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
|
||||
EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
|
||||
if ((word & 0x00ff) == 0x00ff) {
|
||||
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
|
||||
LED_MODE_TXRX_ACTIVITY);
|
||||
rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8);
|
||||
EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
|
||||
}
|
||||
|
||||
/*
|
||||
* During the LNA validation we are going to use
|
||||
* lna0 as correct value. Note that EEPROM_LNA
|
||||
* is never validated.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
|
||||
default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
|
||||
if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
|
||||
rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
|
||||
default_lna_gain);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
|
||||
if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
|
||||
rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
|
||||
default_lna_gain);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_validate_eeprom);
|
||||
|
||||
int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
u16 value;
|
||||
u16 eeprom;
|
||||
|
||||
/*
|
||||
* Read EEPROM word for configuration.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
|
||||
|
||||
/*
|
||||
* Identify RF chipset.
|
||||
*/
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2800_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||
struct rt2x00_chip *chip = &rt2x00dev->chip;
|
||||
|
||||
/*
|
||||
* The check for rt2860 is not a typo, some rt2870 hardware
|
||||
* identifies itself as rt2860 in the CSR register.
|
||||
*/
|
||||
if (rt2x00_check_rev(chip, 0xfff00000, 0x28600000) ||
|
||||
rt2x00_check_rev(chip, 0xfff00000, 0x28700000) ||
|
||||
rt2x00_check_rev(chip, 0xfff00000, 0x28800000)) {
|
||||
rt2x00_set_chip_rt(rt2x00dev, RT2870);
|
||||
} else if (rt2x00_check_rev(chip, 0xffff0000, 0x30700000)) {
|
||||
rt2x00_set_chip_rt(rt2x00dev, RT3070);
|
||||
} else {
|
||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2820) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2850) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2720) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2750) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2020) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3021) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3022)) {
|
||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Identify default antenna configuration.
|
||||
*/
|
||||
rt2x00dev->default_ant.tx =
|
||||
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH);
|
||||
rt2x00dev->default_ant.rx =
|
||||
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH);
|
||||
|
||||
/*
|
||||
* Read frequency offset and RF programming sequence.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
|
||||
rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
|
||||
|
||||
/*
|
||||
* Read external LNA informations.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
|
||||
|
||||
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
|
||||
__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
|
||||
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
|
||||
__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Detect if this device has an hardware controlled radio.
|
||||
*/
|
||||
if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO))
|
||||
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Store led settings, for correct led behaviour.
|
||||
*/
|
||||
#ifdef CONFIG_RT2X00_LIB_LEDS
|
||||
rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
|
||||
rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
|
||||
rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg);
|
||||
#endif /* CONFIG_RT2X00_LIB_LEDS */
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_init_eeprom);
|
||||
|
||||
/*
|
||||
* RF value list for rt28x0
|
||||
* Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
|
||||
*/
|
||||
static const struct rf_channel rf_vals[] = {
|
||||
{ 1, 0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },
|
||||
{ 2, 0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f },
|
||||
{ 3, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b },
|
||||
{ 4, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f },
|
||||
{ 5, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b },
|
||||
{ 6, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f },
|
||||
{ 7, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b },
|
||||
{ 8, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f },
|
||||
{ 9, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b },
|
||||
{ 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f },
|
||||
{ 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b },
|
||||
{ 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f },
|
||||
{ 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b },
|
||||
{ 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 },
|
||||
|
||||
/* 802.11 UNI / HyperLan 2 */
|
||||
{ 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 },
|
||||
{ 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 },
|
||||
{ 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 },
|
||||
{ 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 },
|
||||
{ 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b },
|
||||
{ 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b },
|
||||
{ 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 },
|
||||
{ 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 },
|
||||
{ 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b },
|
||||
{ 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 },
|
||||
{ 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 },
|
||||
{ 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 },
|
||||
|
||||
/* 802.11 HyperLan 2 */
|
||||
{ 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 },
|
||||
{ 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 },
|
||||
{ 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 },
|
||||
{ 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 },
|
||||
{ 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 },
|
||||
{ 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b },
|
||||
{ 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 },
|
||||
{ 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 },
|
||||
{ 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 },
|
||||
{ 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 },
|
||||
{ 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b },
|
||||
{ 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 },
|
||||
{ 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b },
|
||||
{ 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 },
|
||||
{ 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b },
|
||||
{ 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 },
|
||||
|
||||
/* 802.11 UNII */
|
||||
{ 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 },
|
||||
{ 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 },
|
||||
{ 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f },
|
||||
{ 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f },
|
||||
{ 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 },
|
||||
{ 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 },
|
||||
{ 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 },
|
||||
{ 167, 0x18402ec4, 0x184c03d2, 0x18179855, 0x1815531f },
|
||||
{ 169, 0x18402ec4, 0x184c03d2, 0x18179855, 0x18155327 },
|
||||
{ 171, 0x18402ec4, 0x184c03d6, 0x18179855, 0x18155307 },
|
||||
{ 173, 0x18402ec4, 0x184c03d6, 0x18179855, 0x1815530f },
|
||||
|
||||
/* 802.11 Japan */
|
||||
{ 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b },
|
||||
{ 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 },
|
||||
{ 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b },
|
||||
{ 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 },
|
||||
{ 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 },
|
||||
{ 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b },
|
||||
{ 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 },
|
||||
};
|
||||
|
||||
/*
|
||||
* RF value list for rt3070
|
||||
* Supports: 2.4 GHz
|
||||
*/
|
||||
static const struct rf_channel rf_vals_302x[] = {
|
||||
{1, 241, 2, 2 },
|
||||
{2, 241, 2, 7 },
|
||||
{3, 242, 2, 2 },
|
||||
{4, 242, 2, 7 },
|
||||
{5, 243, 2, 2 },
|
||||
{6, 243, 2, 7 },
|
||||
{7, 244, 2, 2 },
|
||||
{8, 244, 2, 7 },
|
||||
{9, 245, 2, 2 },
|
||||
{10, 245, 2, 7 },
|
||||
{11, 246, 2, 2 },
|
||||
{12, 246, 2, 7 },
|
||||
{13, 247, 2, 2 },
|
||||
{14, 248, 2, 4 },
|
||||
};
|
||||
|
||||
int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct rt2x00_chip *chip = &rt2x00dev->chip;
|
||||
struct hw_mode_spec *spec = &rt2x00dev->spec;
|
||||
struct channel_info *info;
|
||||
char *tx_power1;
|
||||
char *tx_power2;
|
||||
unsigned int i;
|
||||
u16 eeprom;
|
||||
|
||||
/*
|
||||
* Initialize all hw fields.
|
||||
*/
|
||||
rt2x00dev->hw->flags =
|
||||
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_PS_NULLFUNC_STACK;
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev))
|
||||
rt2x00dev->hw->extra_tx_headroom =
|
||||
TXINFO_DESC_SIZE + TXWI_DESC_SIZE;
|
||||
else if (rt2x00_intf_is_pci(rt2x00dev))
|
||||
rt2x00dev->hw->extra_tx_headroom = TXWI_DESC_SIZE;
|
||||
|
||||
SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
|
||||
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
|
||||
rt2x00_eeprom_addr(rt2x00dev,
|
||||
EEPROM_MAC_ADDR_0));
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
|
||||
|
||||
/*
|
||||
* Initialize hw_mode information.
|
||||
*/
|
||||
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
||||
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
||||
|
||||
if (rt2x00_rf(chip, RF2820) ||
|
||||
rt2x00_rf(chip, RF2720) ||
|
||||
(rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(chip, RF3052))) {
|
||||
spec->num_channels = 14;
|
||||
spec->channels = rf_vals;
|
||||
} else if (rt2x00_rf(chip, RF2850) || rt2x00_rf(chip, RF2750)) {
|
||||
spec->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals);
|
||||
spec->channels = rf_vals;
|
||||
} else if (rt2x00_rf(chip, RF3020) ||
|
||||
rt2x00_rf(chip, RF2020) ||
|
||||
rt2x00_rf(chip, RF3021) ||
|
||||
rt2x00_rf(chip, RF3022)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_302x);
|
||||
spec->channels = rf_vals_302x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize HT information.
|
||||
*/
|
||||
spec->ht.ht_supported = true;
|
||||
spec->ht.cap =
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
|
||||
IEEE80211_HT_CAP_GRN_FLD |
|
||||
IEEE80211_HT_CAP_SGI_20 |
|
||||
IEEE80211_HT_CAP_SGI_40 |
|
||||
IEEE80211_HT_CAP_TX_STBC |
|
||||
IEEE80211_HT_CAP_RX_STBC |
|
||||
IEEE80211_HT_CAP_PSMP_SUPPORT;
|
||||
spec->ht.ampdu_factor = 3;
|
||||
spec->ht.ampdu_density = 4;
|
||||
spec->ht.mcs.tx_params =
|
||||
IEEE80211_HT_MCS_TX_DEFINED |
|
||||
IEEE80211_HT_MCS_TX_RX_DIFF |
|
||||
((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) <<
|
||||
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
|
||||
|
||||
switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) {
|
||||
case 3:
|
||||
spec->ht.mcs.rx_mask[2] = 0xff;
|
||||
case 2:
|
||||
spec->ht.mcs.rx_mask[1] = 0xff;
|
||||
case 1:
|
||||
spec->ht.mcs.rx_mask[0] = 0xff;
|
||||
spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create channel information array
|
||||
*/
|
||||
info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
spec->channels_info = info;
|
||||
|
||||
tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
|
||||
tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
|
||||
|
||||
for (i = 0; i < 14; i++) {
|
||||
info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]);
|
||||
info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]);
|
||||
}
|
||||
|
||||
if (spec->num_channels > 14) {
|
||||
tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
|
||||
tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
|
||||
|
||||
for (i = 14; i < spec->num_channels; i++) {
|
||||
info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]);
|
||||
info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_probe_hw_mode);
|
||||
|
||||
/*
|
||||
* IEEE80211 stack callback functions.
|
||||
*/
|
||||
|
@ -23,6 +23,8 @@
|
||||
struct rt2800_ops {
|
||||
void (*register_read)(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset, u32 *value);
|
||||
void (*register_read_lock)(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset, u32 *value);
|
||||
void (*register_write)(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset, u32 value);
|
||||
void (*register_write_lock)(struct rt2x00_dev *rt2x00dev,
|
||||
@ -49,6 +51,15 @@ static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
|
||||
rt2800ops->register_read(rt2x00dev, offset, value);
|
||||
}
|
||||
|
||||
static inline void rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
u32 *value)
|
||||
{
|
||||
const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
|
||||
|
||||
rt2800ops->register_read_lock(rt2x00dev, offset, value);
|
||||
}
|
||||
|
||||
static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
u32 value)
|
||||
@ -129,6 +140,12 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev);
|
||||
int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev);
|
||||
int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev);
|
||||
int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev);
|
||||
int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev);
|
||||
int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
extern const struct ieee80211_ops rt2800_mac80211_ops;
|
||||
|
||||
#endif /* RT2800LIB_H */
|
||||
|
@ -1,5 +1,12 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
|
||||
Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
|
||||
Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
|
||||
Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
|
||||
Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
|
||||
Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -145,43 +152,25 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
|
||||
EEPROM_SIZE / sizeof(u16));
|
||||
}
|
||||
|
||||
static void rt2800pci_efuse_read(struct rt2x00_dev *rt2x00dev,
|
||||
unsigned int i)
|
||||
static int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
rt2800_register_read(rt2x00dev, EFUSE_CTRL, ®);
|
||||
rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i);
|
||||
rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0);
|
||||
rt2x00_set_field32(®, EFUSE_CTRL_KICK, 1);
|
||||
rt2800_register_write(rt2x00dev, EFUSE_CTRL, reg);
|
||||
|
||||
/* Wait until the EEPROM has been loaded */
|
||||
rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, ®);
|
||||
|
||||
/* Apparently the data is read from end to start */
|
||||
rt2800_register_read(rt2x00dev, EFUSE_DATA3,
|
||||
(u32 *)&rt2x00dev->eeprom[i]);
|
||||
rt2800_register_read(rt2x00dev, EFUSE_DATA2,
|
||||
(u32 *)&rt2x00dev->eeprom[i + 2]);
|
||||
rt2800_register_read(rt2x00dev, EFUSE_DATA1,
|
||||
(u32 *)&rt2x00dev->eeprom[i + 4]);
|
||||
rt2800_register_read(rt2x00dev, EFUSE_DATA0,
|
||||
(u32 *)&rt2x00dev->eeprom[i + 6]);
|
||||
return rt2800_efuse_detect(rt2x00dev);
|
||||
}
|
||||
|
||||
static void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
|
||||
static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8)
|
||||
rt2800pci_efuse_read(rt2x00dev, i);
|
||||
rt2800_read_eeprom_efuse(rt2x00dev);
|
||||
}
|
||||
#else
|
||||
static inline void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
}
|
||||
@ -1079,379 +1068,28 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
|
||||
*/
|
||||
static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u16 word;
|
||||
u8 *mac;
|
||||
u8 default_lna_gain;
|
||||
|
||||
/*
|
||||
* Read EEPROM into buffer
|
||||
*/
|
||||
switch(rt2x00dev->chip.rt) {
|
||||
switch (rt2x00dev->chip.rt) {
|
||||
case RT2880:
|
||||
case RT3052:
|
||||
rt2800pci_read_eeprom_soc(rt2x00dev);
|
||||
break;
|
||||
case RT3090:
|
||||
rt2800pci_read_eeprom_efuse(rt2x00dev);
|
||||
break;
|
||||
default:
|
||||
rt2800pci_read_eeprom_pci(rt2x00dev);
|
||||
if (rt2800pci_efuse_detect(rt2x00dev))
|
||||
rt2800pci_read_eeprom_efuse(rt2x00dev);
|
||||
else
|
||||
rt2800pci_read_eeprom_pci(rt2x00dev);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start validation of the data that has been read.
|
||||
*/
|
||||
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
if (!is_valid_ether_addr(mac)) {
|
||||
random_ether_addr(mac);
|
||||
EEPROM(rt2x00dev, "MAC: %pM\n", mac);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1);
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
|
||||
EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
|
||||
} else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) {
|
||||
/*
|
||||
* There is a max of 2 RX streams for RT2860 series
|
||||
*/
|
||||
if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2)
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
|
||||
EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
|
||||
if ((word & 0x00ff) == 0x00ff) {
|
||||
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
|
||||
LED_MODE_TXRX_ACTIVITY);
|
||||
rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8);
|
||||
EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
|
||||
}
|
||||
|
||||
/*
|
||||
* During the LNA validation we are going to use
|
||||
* lna0 as correct value. Note that EEPROM_LNA
|
||||
* is never validated.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
|
||||
default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
|
||||
if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
|
||||
rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
|
||||
default_lna_gain);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
|
||||
if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
|
||||
rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
|
||||
default_lna_gain);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt2800pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
u16 value;
|
||||
u16 eeprom;
|
||||
|
||||
/*
|
||||
* Read EEPROM word for configuration.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
|
||||
|
||||
/*
|
||||
* Identify RF chipset.
|
||||
*/
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2800_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2820) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2850) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2720) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2750) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2020) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3021) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3022)) {
|
||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Identify default antenna configuration.
|
||||
*/
|
||||
rt2x00dev->default_ant.tx =
|
||||
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH);
|
||||
rt2x00dev->default_ant.rx =
|
||||
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH);
|
||||
|
||||
/*
|
||||
* Read frequency offset and RF programming sequence.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
|
||||
rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
|
||||
|
||||
/*
|
||||
* Read external LNA informations.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
|
||||
|
||||
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
|
||||
__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
|
||||
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
|
||||
__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Detect if this device has an hardware controlled radio.
|
||||
*/
|
||||
if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO))
|
||||
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Store led settings, for correct led behaviour.
|
||||
*/
|
||||
#ifdef CONFIG_RT2X00_LIB_LEDS
|
||||
rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
|
||||
rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
|
||||
rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg);
|
||||
#endif /* CONFIG_RT2X00_LIB_LEDS */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* RF value list for rt2860
|
||||
* Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
|
||||
*/
|
||||
static const struct rf_channel rf_vals[] = {
|
||||
{ 1, 0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },
|
||||
{ 2, 0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f },
|
||||
{ 3, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b },
|
||||
{ 4, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f },
|
||||
{ 5, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b },
|
||||
{ 6, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f },
|
||||
{ 7, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b },
|
||||
{ 8, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f },
|
||||
{ 9, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b },
|
||||
{ 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f },
|
||||
{ 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b },
|
||||
{ 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f },
|
||||
{ 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b },
|
||||
{ 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 },
|
||||
|
||||
/* 802.11 UNI / HyperLan 2 */
|
||||
{ 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 },
|
||||
{ 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 },
|
||||
{ 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 },
|
||||
{ 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 },
|
||||
{ 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b },
|
||||
{ 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b },
|
||||
{ 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 },
|
||||
{ 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 },
|
||||
{ 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b },
|
||||
{ 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 },
|
||||
{ 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 },
|
||||
{ 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 },
|
||||
|
||||
/* 802.11 HyperLan 2 */
|
||||
{ 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 },
|
||||
{ 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 },
|
||||
{ 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 },
|
||||
{ 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 },
|
||||
{ 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 },
|
||||
{ 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b },
|
||||
{ 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 },
|
||||
{ 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 },
|
||||
{ 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 },
|
||||
{ 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 },
|
||||
{ 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b },
|
||||
{ 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 },
|
||||
{ 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b },
|
||||
{ 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 },
|
||||
{ 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b },
|
||||
{ 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 },
|
||||
|
||||
/* 802.11 UNII */
|
||||
{ 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 },
|
||||
{ 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 },
|
||||
{ 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f },
|
||||
{ 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f },
|
||||
{ 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 },
|
||||
{ 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 },
|
||||
{ 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 },
|
||||
|
||||
/* 802.11 Japan */
|
||||
{ 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b },
|
||||
{ 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 },
|
||||
{ 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b },
|
||||
{ 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 },
|
||||
{ 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 },
|
||||
{ 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b },
|
||||
{ 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 },
|
||||
};
|
||||
|
||||
static int rt2800pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct hw_mode_spec *spec = &rt2x00dev->spec;
|
||||
struct channel_info *info;
|
||||
char *tx_power1;
|
||||
char *tx_power2;
|
||||
unsigned int i;
|
||||
u16 eeprom;
|
||||
|
||||
/*
|
||||
* Initialize all hw fields.
|
||||
*/
|
||||
rt2x00dev->hw->flags =
|
||||
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_PS_NULLFUNC_STACK;
|
||||
rt2x00dev->hw->extra_tx_headroom = TXWI_DESC_SIZE;
|
||||
|
||||
SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
|
||||
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
|
||||
rt2x00_eeprom_addr(rt2x00dev,
|
||||
EEPROM_MAC_ADDR_0));
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
|
||||
|
||||
/*
|
||||
* Initialize hw_mode information.
|
||||
*/
|
||||
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
||||
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
||||
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2820) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2720) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF3020) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF3021) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF3022) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2020) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF3052)) {
|
||||
spec->num_channels = 14;
|
||||
spec->channels = rf_vals;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF2850) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2750)) {
|
||||
spec->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals);
|
||||
spec->channels = rf_vals;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize HT information.
|
||||
*/
|
||||
spec->ht.ht_supported = true;
|
||||
spec->ht.cap =
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
|
||||
IEEE80211_HT_CAP_GRN_FLD |
|
||||
IEEE80211_HT_CAP_SGI_20 |
|
||||
IEEE80211_HT_CAP_SGI_40 |
|
||||
IEEE80211_HT_CAP_TX_STBC |
|
||||
IEEE80211_HT_CAP_RX_STBC |
|
||||
IEEE80211_HT_CAP_PSMP_SUPPORT;
|
||||
spec->ht.ampdu_factor = 3;
|
||||
spec->ht.ampdu_density = 4;
|
||||
spec->ht.mcs.tx_params =
|
||||
IEEE80211_HT_MCS_TX_DEFINED |
|
||||
IEEE80211_HT_MCS_TX_RX_DIFF |
|
||||
((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) <<
|
||||
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
|
||||
|
||||
switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) {
|
||||
case 3:
|
||||
spec->ht.mcs.rx_mask[2] = 0xff;
|
||||
case 2:
|
||||
spec->ht.mcs.rx_mask[1] = 0xff;
|
||||
case 1:
|
||||
spec->ht.mcs.rx_mask[0] = 0xff;
|
||||
spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create channel information array
|
||||
*/
|
||||
info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
spec->channels_info = info;
|
||||
|
||||
tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
|
||||
tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
|
||||
|
||||
for (i = 0; i < 14; i++) {
|
||||
info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]);
|
||||
info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]);
|
||||
}
|
||||
|
||||
if (spec->num_channels > 14) {
|
||||
tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
|
||||
tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
|
||||
|
||||
for (i = 14; i < spec->num_channels; i++) {
|
||||
info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]);
|
||||
info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rt2800_validate_eeprom(rt2x00dev);
|
||||
}
|
||||
|
||||
static const struct rt2800_ops rt2800pci_rt2800_ops = {
|
||||
.register_read = rt2x00pci_register_read,
|
||||
.register_read_lock = rt2x00pci_register_read, /* same for PCI */
|
||||
.register_write = rt2x00pci_register_write,
|
||||
.register_write_lock = rt2x00pci_register_write, /* same for PCI */
|
||||
|
||||
@ -1465,8 +1103,6 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int retval;
|
||||
|
||||
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
|
||||
|
||||
rt2x00dev->priv = (void *)&rt2800pci_rt2800_ops;
|
||||
|
||||
/*
|
||||
@ -1476,14 +1112,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = rt2800pci_init_eeprom(rt2x00dev);
|
||||
retval = rt2800_init_eeprom(rt2x00dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* Initialize hw specifications.
|
||||
*/
|
||||
retval = rt2800pci_probe_hw_mode(rt2x00dev);
|
||||
retval = rt2800_probe_hw_mode(rt2x00dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
|
@ -1,5 +1,12 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
|
||||
Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
|
||||
Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
|
||||
Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
|
||||
Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
|
||||
Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -55,34 +62,6 @@
|
||||
#define TX_CTX_IDX(__x) TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)
|
||||
#define TX_DTX_IDX(__x) TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)
|
||||
|
||||
/*
|
||||
* EFUSE_CSR: RT3090 EEPROM
|
||||
*/
|
||||
#define EFUSE_CTRL 0x0580
|
||||
#define EFUSE_CTRL_ADDRESS_IN FIELD32(0x03fe0000)
|
||||
#define EFUSE_CTRL_MODE FIELD32(0x000000c0)
|
||||
#define EFUSE_CTRL_KICK FIELD32(0x40000000)
|
||||
|
||||
/*
|
||||
* EFUSE_DATA0
|
||||
*/
|
||||
#define EFUSE_DATA0 0x0590
|
||||
|
||||
/*
|
||||
* EFUSE_DATA1
|
||||
*/
|
||||
#define EFUSE_DATA1 0x0594
|
||||
|
||||
/*
|
||||
* EFUSE_DATA2
|
||||
*/
|
||||
#define EFUSE_DATA2 0x0598
|
||||
|
||||
/*
|
||||
* EFUSE_DATA3
|
||||
*/
|
||||
#define EFUSE_DATA3 0x059c
|
||||
|
||||
/*
|
||||
* 8051 firmware image.
|
||||
*/
|
||||
|
@ -1,5 +1,9 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
|
||||
Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
|
||||
Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
Copyright (C) 2009 Axel Kollhofer <rain_maker@root-forum.org>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -594,16 +598,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
|
||||
rt2x00_desc_read(rxwi, 2, &rxwi2);
|
||||
rt2x00_desc_read(rxwi, 3, &rxwi3);
|
||||
|
||||
if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR))
|
||||
if (rt2x00_get_field32(rxd0, RXINFO_W0_CRC_ERROR))
|
||||
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
|
||||
|
||||
if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
|
||||
rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
|
||||
rxdesc->cipher_status =
|
||||
rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR);
|
||||
rt2x00_get_field32(rxd0, RXINFO_W0_CIPHER_ERROR);
|
||||
}
|
||||
|
||||
if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) {
|
||||
if (rt2x00_get_field32(rxd0, RXINFO_W0_DECRYPTED)) {
|
||||
/*
|
||||
* Hardware has stripped IV/EIV data from 802.11 frame during
|
||||
* decryption. Unfortunately the descriptor doesn't contain
|
||||
@ -618,10 +622,10 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
|
||||
rxdesc->flags |= RX_FLAG_MMIC_ERROR;
|
||||
}
|
||||
|
||||
if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS))
|
||||
if (rt2x00_get_field32(rxd0, RXINFO_W0_MY_BSS))
|
||||
rxdesc->dev_flags |= RXDONE_MY_BSS;
|
||||
|
||||
if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) {
|
||||
if (rt2x00_get_field32(rxd0, RXINFO_W0_L2PAD)) {
|
||||
rxdesc->dev_flags |= RXDONE_L2PAD;
|
||||
skbdesc->flags |= SKBDESC_L2_PADDED;
|
||||
}
|
||||
@ -667,400 +671,18 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
|
||||
*/
|
||||
static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u16 word;
|
||||
u8 *mac;
|
||||
u8 default_lna_gain;
|
||||
if (rt2800_efuse_detect(rt2x00dev))
|
||||
rt2800_read_eeprom_efuse(rt2x00dev);
|
||||
else
|
||||
rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,
|
||||
EEPROM_SIZE);
|
||||
|
||||
rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
|
||||
|
||||
/*
|
||||
* Start validation of the data that has been read.
|
||||
*/
|
||||
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
if (!is_valid_ether_addr(mac)) {
|
||||
random_ether_addr(mac);
|
||||
EEPROM(rt2x00dev, "MAC: %pM\n", mac);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1);
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
|
||||
EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
|
||||
} else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) {
|
||||
/*
|
||||
* There is a max of 2 RX streams for RT2870 series
|
||||
*/
|
||||
if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2)
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
|
||||
EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
|
||||
if ((word & 0x00ff) == 0x00ff) {
|
||||
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
|
||||
LED_MODE_TXRX_ACTIVITY);
|
||||
rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8);
|
||||
EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
|
||||
}
|
||||
|
||||
/*
|
||||
* During the LNA validation we are going to use
|
||||
* lna0 as correct value. Note that EEPROM_LNA
|
||||
* is never validated.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
|
||||
default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
|
||||
if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
|
||||
rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
|
||||
default_lna_gain);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
|
||||
if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
|
||||
rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
|
||||
default_lna_gain);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
u16 value;
|
||||
u16 eeprom;
|
||||
|
||||
/*
|
||||
* Read EEPROM word for configuration.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
|
||||
|
||||
/*
|
||||
* Identify RF chipset.
|
||||
*/
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2800_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
rt2x00_set_chip(rt2x00dev, RT2870, value, reg);
|
||||
|
||||
/*
|
||||
* The check for rt2860 is not a typo, some rt2870 hardware
|
||||
* identifies itself as rt2860 in the CSR register.
|
||||
*/
|
||||
if (!rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28600000) &&
|
||||
!rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28700000) &&
|
||||
!rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28800000) &&
|
||||
!rt2x00_check_rev(&rt2x00dev->chip, 0xffff0000, 0x30700000)) {
|
||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2820) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2850) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2720) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2750) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2020)) {
|
||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Identify default antenna configuration.
|
||||
*/
|
||||
rt2x00dev->default_ant.tx =
|
||||
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH);
|
||||
rt2x00dev->default_ant.rx =
|
||||
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH);
|
||||
|
||||
/*
|
||||
* Read frequency offset and RF programming sequence.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
|
||||
rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
|
||||
|
||||
/*
|
||||
* Read external LNA informations.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
|
||||
|
||||
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
|
||||
__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
|
||||
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
|
||||
__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Detect if this device has an hardware controlled radio.
|
||||
*/
|
||||
if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO))
|
||||
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Store led settings, for correct led behaviour.
|
||||
*/
|
||||
#ifdef CONFIG_RT2X00_LIB_LEDS
|
||||
rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
|
||||
rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
|
||||
rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ,
|
||||
&rt2x00dev->led_mcu_reg);
|
||||
#endif /* CONFIG_RT2X00_LIB_LEDS */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* RF value list for rt2870
|
||||
* Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
|
||||
*/
|
||||
static const struct rf_channel rf_vals[] = {
|
||||
{ 1, 0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },
|
||||
{ 2, 0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f },
|
||||
{ 3, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b },
|
||||
{ 4, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f },
|
||||
{ 5, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b },
|
||||
{ 6, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f },
|
||||
{ 7, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b },
|
||||
{ 8, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f },
|
||||
{ 9, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b },
|
||||
{ 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f },
|
||||
{ 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b },
|
||||
{ 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f },
|
||||
{ 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b },
|
||||
{ 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 },
|
||||
|
||||
/* 802.11 UNI / HyperLan 2 */
|
||||
{ 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 },
|
||||
{ 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 },
|
||||
{ 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 },
|
||||
{ 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 },
|
||||
{ 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b },
|
||||
{ 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b },
|
||||
{ 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 },
|
||||
{ 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 },
|
||||
{ 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b },
|
||||
{ 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 },
|
||||
{ 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 },
|
||||
{ 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 },
|
||||
|
||||
/* 802.11 HyperLan 2 */
|
||||
{ 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 },
|
||||
{ 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 },
|
||||
{ 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 },
|
||||
{ 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 },
|
||||
{ 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 },
|
||||
{ 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b },
|
||||
{ 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 },
|
||||
{ 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 },
|
||||
{ 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 },
|
||||
{ 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 },
|
||||
{ 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b },
|
||||
{ 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 },
|
||||
{ 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b },
|
||||
{ 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 },
|
||||
{ 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b },
|
||||
{ 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 },
|
||||
|
||||
/* 802.11 UNII */
|
||||
{ 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 },
|
||||
{ 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 },
|
||||
{ 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f },
|
||||
{ 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f },
|
||||
{ 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 },
|
||||
{ 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 },
|
||||
{ 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 },
|
||||
{ 167, 0x18402ec4, 0x184c03d2, 0x18179855, 0x1815531f },
|
||||
{ 169, 0x18402ec4, 0x184c03d2, 0x18179855, 0x18155327 },
|
||||
{ 171, 0x18402ec4, 0x184c03d6, 0x18179855, 0x18155307 },
|
||||
{ 173, 0x18402ec4, 0x184c03d6, 0x18179855, 0x1815530f },
|
||||
|
||||
/* 802.11 Japan */
|
||||
{ 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b },
|
||||
{ 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 },
|
||||
{ 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b },
|
||||
{ 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 },
|
||||
{ 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 },
|
||||
{ 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b },
|
||||
{ 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 },
|
||||
};
|
||||
|
||||
/*
|
||||
* RF value list for rt3070
|
||||
* Supports: 2.4 GHz
|
||||
*/
|
||||
static const struct rf_channel rf_vals_3070[] = {
|
||||
{1, 241, 2, 2 },
|
||||
{2, 241, 2, 7 },
|
||||
{3, 242, 2, 2 },
|
||||
{4, 242, 2, 7 },
|
||||
{5, 243, 2, 2 },
|
||||
{6, 243, 2, 7 },
|
||||
{7, 244, 2, 2 },
|
||||
{8, 244, 2, 7 },
|
||||
{9, 245, 2, 2 },
|
||||
{10, 245, 2, 7 },
|
||||
{11, 246, 2, 2 },
|
||||
{12, 246, 2, 7 },
|
||||
{13, 247, 2, 2 },
|
||||
{14, 248, 2, 4 },
|
||||
};
|
||||
|
||||
static int rt2800usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct hw_mode_spec *spec = &rt2x00dev->spec;
|
||||
struct channel_info *info;
|
||||
char *tx_power1;
|
||||
char *tx_power2;
|
||||
unsigned int i;
|
||||
u16 eeprom;
|
||||
|
||||
/*
|
||||
* Initialize all hw fields.
|
||||
*/
|
||||
rt2x00dev->hw->flags =
|
||||
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_PS_NULLFUNC_STACK;
|
||||
rt2x00dev->hw->extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE;
|
||||
|
||||
SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
|
||||
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
|
||||
rt2x00_eeprom_addr(rt2x00dev,
|
||||
EEPROM_MAC_ADDR_0));
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
|
||||
|
||||
/*
|
||||
* Initialize HT information.
|
||||
*/
|
||||
spec->ht.ht_supported = true;
|
||||
spec->ht.cap =
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
|
||||
IEEE80211_HT_CAP_GRN_FLD |
|
||||
IEEE80211_HT_CAP_SGI_20 |
|
||||
IEEE80211_HT_CAP_SGI_40 |
|
||||
IEEE80211_HT_CAP_TX_STBC |
|
||||
IEEE80211_HT_CAP_RX_STBC |
|
||||
IEEE80211_HT_CAP_PSMP_SUPPORT;
|
||||
spec->ht.ampdu_factor = 3;
|
||||
spec->ht.ampdu_density = 4;
|
||||
spec->ht.mcs.tx_params =
|
||||
IEEE80211_HT_MCS_TX_DEFINED |
|
||||
IEEE80211_HT_MCS_TX_RX_DIFF |
|
||||
((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) <<
|
||||
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
|
||||
|
||||
switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) {
|
||||
case 3:
|
||||
spec->ht.mcs.rx_mask[2] = 0xff;
|
||||
case 2:
|
||||
spec->ht.mcs.rx_mask[1] = 0xff;
|
||||
case 1:
|
||||
spec->ht.mcs.rx_mask[0] = 0xff;
|
||||
spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize hw_mode information.
|
||||
*/
|
||||
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
||||
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
||||
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2820) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2720)) {
|
||||
spec->num_channels = 14;
|
||||
spec->channels = rf_vals;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF2850) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2750)) {
|
||||
spec->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals);
|
||||
spec->channels = rf_vals;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF3020) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2020)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_3070);
|
||||
spec->channels = rf_vals_3070;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create channel information array
|
||||
*/
|
||||
info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
spec->channels_info = info;
|
||||
|
||||
tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
|
||||
tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
|
||||
|
||||
for (i = 0; i < 14; i++) {
|
||||
info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]);
|
||||
info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]);
|
||||
}
|
||||
|
||||
if (spec->num_channels > 14) {
|
||||
tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
|
||||
tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
|
||||
|
||||
for (i = 14; i < spec->num_channels; i++) {
|
||||
info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]);
|
||||
info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rt2800_validate_eeprom(rt2x00dev);
|
||||
}
|
||||
|
||||
static const struct rt2800_ops rt2800usb_rt2800_ops = {
|
||||
.register_read = rt2x00usb_register_read,
|
||||
.register_read_lock = rt2x00usb_register_read_lock,
|
||||
.register_write = rt2x00usb_register_write,
|
||||
.register_write_lock = rt2x00usb_register_write_lock,
|
||||
|
||||
@ -1074,8 +696,6 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int retval;
|
||||
|
||||
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
|
||||
|
||||
rt2x00dev->priv = (void *)&rt2800usb_rt2800_ops;
|
||||
|
||||
/*
|
||||
@ -1085,14 +705,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = rt2800usb_init_eeprom(rt2x00dev);
|
||||
retval = rt2800_init_eeprom(rt2x00dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* Initialize hw specifications.
|
||||
*/
|
||||
retval = rt2800usb_probe_hw_mode(rt2x00dev);
|
||||
retval = rt2800_probe_hw_mode(rt2x00dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
|
||||
Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
|
||||
Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
|
||||
Copyright (C) 2009 Axel Kollhofer <rain_maker@root-forum.org>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -111,25 +115,25 @@
|
||||
* AMSDU: rx with 802.3 header, not 802.11 header.
|
||||
*/
|
||||
|
||||
#define RXD_W0_BA FIELD32(0x00000001)
|
||||
#define RXD_W0_DATA FIELD32(0x00000002)
|
||||
#define RXD_W0_NULLDATA FIELD32(0x00000004)
|
||||
#define RXD_W0_FRAG FIELD32(0x00000008)
|
||||
#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000010)
|
||||
#define RXD_W0_MULTICAST FIELD32(0x00000020)
|
||||
#define RXD_W0_BROADCAST FIELD32(0x00000040)
|
||||
#define RXD_W0_MY_BSS FIELD32(0x00000080)
|
||||
#define RXD_W0_CRC_ERROR FIELD32(0x00000100)
|
||||
#define RXD_W0_CIPHER_ERROR FIELD32(0x00000600)
|
||||
#define RXD_W0_AMSDU FIELD32(0x00000800)
|
||||
#define RXD_W0_HTC FIELD32(0x00001000)
|
||||
#define RXD_W0_RSSI FIELD32(0x00002000)
|
||||
#define RXD_W0_L2PAD FIELD32(0x00004000)
|
||||
#define RXD_W0_AMPDU FIELD32(0x00008000)
|
||||
#define RXD_W0_DECRYPTED FIELD32(0x00010000)
|
||||
#define RXD_W0_PLCP_RSSI FIELD32(0x00020000)
|
||||
#define RXD_W0_CIPHER_ALG FIELD32(0x00040000)
|
||||
#define RXD_W0_LAST_AMSDU FIELD32(0x00080000)
|
||||
#define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000)
|
||||
#define RXINFO_W0_BA FIELD32(0x00000001)
|
||||
#define RXINFO_W0_DATA FIELD32(0x00000002)
|
||||
#define RXINFO_W0_NULLDATA FIELD32(0x00000004)
|
||||
#define RXINFO_W0_FRAG FIELD32(0x00000008)
|
||||
#define RXINFO_W0_UNICAST_TO_ME FIELD32(0x00000010)
|
||||
#define RXINFO_W0_MULTICAST FIELD32(0x00000020)
|
||||
#define RXINFO_W0_BROADCAST FIELD32(0x00000040)
|
||||
#define RXINFO_W0_MY_BSS FIELD32(0x00000080)
|
||||
#define RXINFO_W0_CRC_ERROR FIELD32(0x00000100)
|
||||
#define RXINFO_W0_CIPHER_ERROR FIELD32(0x00000600)
|
||||
#define RXINFO_W0_AMSDU FIELD32(0x00000800)
|
||||
#define RXINFO_W0_HTC FIELD32(0x00001000)
|
||||
#define RXINFO_W0_RSSI FIELD32(0x00002000)
|
||||
#define RXINFO_W0_L2PAD FIELD32(0x00004000)
|
||||
#define RXINFO_W0_AMPDU FIELD32(0x00008000)
|
||||
#define RXINFO_W0_DECRYPTED FIELD32(0x00010000)
|
||||
#define RXINFO_W0_PLCP_RSSI FIELD32(0x00020000)
|
||||
#define RXINFO_W0_CIPHER_ALG FIELD32(0x00040000)
|
||||
#define RXINFO_W0_LAST_AMSDU FIELD32(0x00080000)
|
||||
#define RXINFO_W0_PLCP_SIGNAL FIELD32(0xfff00000)
|
||||
|
||||
#endif /* RT2800USB_H */
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -171,6 +172,7 @@ struct rt2x00_chip {
|
||||
#define RT3052 0x3052 /* WSOC */
|
||||
#define RT3090 0x3090 /* 2.4GHz PCIe */
|
||||
#define RT2870 0x1600
|
||||
#define RT3070 0x1800
|
||||
|
||||
u16 rf;
|
||||
u32 rev;
|
||||
@ -312,13 +314,6 @@ struct link {
|
||||
*/
|
||||
struct avg_val avg_rssi;
|
||||
|
||||
/*
|
||||
* Currently precalculated percentages of successful
|
||||
* TX and RX frames.
|
||||
*/
|
||||
int rx_percentage;
|
||||
int tx_percentage;
|
||||
|
||||
/*
|
||||
* Work structure for scheduling periodic link tuning.
|
||||
*/
|
||||
@ -911,10 +906,6 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev,
|
||||
static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev,
|
||||
const u16 rt, const u16 rf, const u32 rev)
|
||||
{
|
||||
INFO(rt2x00dev,
|
||||
"Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n",
|
||||
rt, rf, rev);
|
||||
|
||||
rt2x00dev->chip.rt = rt;
|
||||
rt2x00dev->chip.rf = rf;
|
||||
rt2x00dev->chip.rev = rev;
|
||||
@ -932,6 +923,13 @@ static inline void rt2x00_set_chip_rf(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev);
|
||||
}
|
||||
|
||||
static inline void rt2x00_print_chip(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
INFO(rt2x00dev,
|
||||
"Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n",
|
||||
rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev);
|
||||
}
|
||||
|
||||
static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip)
|
||||
{
|
||||
return (chipset->rt == chip);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -430,7 +430,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
rx_status->mactime = rxdesc.timestamp;
|
||||
rx_status->rate_idx = rate_idx;
|
||||
rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi);
|
||||
rx_status->signal = rxdesc.rssi;
|
||||
rx_status->noise = rxdesc.noise;
|
||||
rx_status->flag = rxdesc.flags;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -222,19 +223,6 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
|
||||
struct sk_buff *skb,
|
||||
struct rxdone_entry_desc *rxdesc);
|
||||
|
||||
/**
|
||||
* rt2x00link_calculate_signal - Calculate signal quality
|
||||
* @rt2x00dev: Pointer to &struct rt2x00_dev.
|
||||
* @rssi: RX Frame RSSI
|
||||
*
|
||||
* Calculate the signal quality of a frame based on the rssi
|
||||
* measured during the receiving of the frame and the global
|
||||
* link quality statistics measured since the start of the
|
||||
* link tuning. The result is a value between 0 and 100 which
|
||||
* is an indication of the signal quality.
|
||||
*/
|
||||
int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi);
|
||||
|
||||
/**
|
||||
* rt2x00link_start_tuner - Start periodic link tuner work
|
||||
* @rt2x00dev: Pointer to &struct rt2x00_dev.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -35,24 +35,6 @@
|
||||
*/
|
||||
#define DEFAULT_RSSI -128
|
||||
|
||||
/*
|
||||
* When no TX/RX percentage could be calculated due to lack of
|
||||
* frames on the air, we fallback to a percentage of 50%.
|
||||
* This will assure we will get at least get some decent value
|
||||
* when the link tuner starts.
|
||||
* The value will be dropped and overwritten with the correct (measured)
|
||||
* value anyway during the first run of the link tuner.
|
||||
*/
|
||||
#define DEFAULT_PERCENTAGE 50
|
||||
|
||||
/*
|
||||
* Small helper macro for percentage calculation
|
||||
* This is a very simple macro with the only catch that it will
|
||||
* produce a default value in case no total value was provided.
|
||||
*/
|
||||
#define PERCENTAGE(__value, __total) \
|
||||
( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) )
|
||||
|
||||
/*
|
||||
* Helper struct and macro to work with moving/walking averages.
|
||||
* When adding a value to the average value the following calculation
|
||||
@ -91,27 +73,6 @@
|
||||
__new; \
|
||||
})
|
||||
|
||||
/*
|
||||
* For calculating the Signal quality we have determined
|
||||
* the total number of success and failed RX and TX frames.
|
||||
* With the addition of the average RSSI value we can determine
|
||||
* the link quality using the following algorithm:
|
||||
*
|
||||
* rssi_percentage = (avg_rssi * 100) / rssi_offset
|
||||
* rx_percentage = (rx_success * 100) / rx_total
|
||||
* tx_percentage = (tx_success * 100) / tx_total
|
||||
* avg_signal = ((WEIGHT_RSSI * avg_rssi) +
|
||||
* (WEIGHT_TX * tx_percentage) +
|
||||
* (WEIGHT_RX * rx_percentage)) / 100
|
||||
*
|
||||
* This value should then be checked to not be greater then 100.
|
||||
* This means the values of WEIGHT_RSSI, WEIGHT_RX, WEIGHT_TX must
|
||||
* sum up to 100 as well.
|
||||
*/
|
||||
#define WEIGHT_RSSI 20
|
||||
#define WEIGHT_RX 40
|
||||
#define WEIGHT_TX 40
|
||||
|
||||
static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct link_ant *ant = &rt2x00dev->link.ant;
|
||||
@ -304,46 +265,6 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
|
||||
ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi);
|
||||
}
|
||||
|
||||
static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct link *link = &rt2x00dev->link;
|
||||
struct link_qual *qual = &rt2x00dev->link.qual;
|
||||
|
||||
link->rx_percentage =
|
||||
PERCENTAGE(qual->rx_success, qual->rx_failed + qual->rx_success);
|
||||
link->tx_percentage =
|
||||
PERCENTAGE(qual->tx_success, qual->tx_failed + qual->tx_success);
|
||||
}
|
||||
|
||||
int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi)
|
||||
{
|
||||
struct link *link = &rt2x00dev->link;
|
||||
int rssi_percentage = 0;
|
||||
int signal;
|
||||
|
||||
/*
|
||||
* We need a positive value for the RSSI.
|
||||
*/
|
||||
if (rssi < 0)
|
||||
rssi += rt2x00dev->rssi_offset;
|
||||
|
||||
/*
|
||||
* Calculate the different percentages,
|
||||
* which will be used for the signal.
|
||||
*/
|
||||
rssi_percentage = PERCENTAGE(rssi, rt2x00dev->rssi_offset);
|
||||
|
||||
/*
|
||||
* Add the individual percentages and use the WEIGHT
|
||||
* defines to calculate the current link signal.
|
||||
*/
|
||||
signal = ((WEIGHT_RSSI * rssi_percentage) +
|
||||
(WEIGHT_TX * link->tx_percentage) +
|
||||
(WEIGHT_RX * link->rx_percentage)) / 100;
|
||||
|
||||
return max_t(int, signal, 100);
|
||||
}
|
||||
|
||||
void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct link *link = &rt2x00dev->link;
|
||||
@ -357,9 +278,6 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
|
||||
if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)
|
||||
return;
|
||||
|
||||
link->rx_percentage = DEFAULT_PERCENTAGE;
|
||||
link->tx_percentage = DEFAULT_PERCENTAGE;
|
||||
|
||||
rt2x00link_reset_tuner(rt2x00dev, false);
|
||||
|
||||
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||
@ -447,12 +365,6 @@ static void rt2x00link_tuner(struct work_struct *work)
|
||||
if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags))
|
||||
rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
|
||||
|
||||
/*
|
||||
* Precalculate a portion of the link signal which is
|
||||
* in based on the tx/rx success/failure counters.
|
||||
*/
|
||||
rt2x00link_precalculate_signal(rt2x00dev);
|
||||
|
||||
/*
|
||||
* Send a signal to the led to update the led signal strength.
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -310,6 +310,8 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
|
||||
rt2x00dev->irq = pci_dev->irq;
|
||||
rt2x00dev->name = pci_name(pci_dev);
|
||||
|
||||
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
|
||||
|
||||
/*
|
||||
* Determine RT chipset by reading PCI header.
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
Copyright (C) 2004 - 2009 Felix Fietkau <nbd@openwrt.org>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -93,6 +94,11 @@ int rt2x00soc_probe(struct platform_device *pdev,
|
||||
rt2x00dev->irq = platform_get_irq(pdev, 0);
|
||||
rt2x00dev->name = pdev->dev.driver->name;
|
||||
|
||||
/*
|
||||
* SoC devices mimic PCI behavior.
|
||||
*/
|
||||
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
|
||||
|
||||
rt2x00_set_chip_rt(rt2x00dev, chipset);
|
||||
|
||||
retval = rt2x00soc_alloc_reg(rt2x00dev);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -653,6 +653,8 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
|
||||
rt2x00dev->ops = ops;
|
||||
rt2x00dev->hw = hw;
|
||||
|
||||
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
|
||||
|
||||
retval = rt2x00usb_alloc_reg(rt2x00dev);
|
||||
if (retval)
|
||||
goto exit_free_device;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -26,6 +26,8 @@
|
||||
#ifndef RT2X00USB_H
|
||||
#define RT2X00USB_H
|
||||
|
||||
#include <linux/usb.h>
|
||||
|
||||
#define to_usb_device_intf(d) \
|
||||
({ \
|
||||
struct usb_interface *intf = to_usb_interface(d); \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -51,7 +51,7 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
|
||||
* These indirect registers work with busy bits,
|
||||
* and we will try maximal REGISTER_BUSY_COUNT times to access
|
||||
* the register while taking a REGISTER_BUSY_DELAY us delay
|
||||
* between each attampt. When the busy bit is still set at that time,
|
||||
* between each attempt. When the busy bit is still set at that time,
|
||||
* the access attempt is considered to have failed,
|
||||
* and we will print an error.
|
||||
*/
|
||||
@ -386,7 +386,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
|
||||
* The driver does not support the IV/EIV generation
|
||||
* in hardware. However it doesn't support the IV/EIV
|
||||
* inside the ieee80211 frame either, but requires it
|
||||
* to be provided seperately for the descriptor.
|
||||
* to be provided separately for the descriptor.
|
||||
* rt2x00lib will cut the IV/EIV data out of all frames
|
||||
* given to us by mac80211, but we must tell mac80211
|
||||
* to generate the IV/EIV data.
|
||||
@ -397,7 +397,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* SEC_CSR0 contains only single-bit fields to indicate
|
||||
* a particular key is valid. Because using the FIELD32()
|
||||
* defines directly will cause a lot of overhead we use
|
||||
* defines directly will cause a lot of overhead, we use
|
||||
* a calculation to determine the correct bit directly.
|
||||
*/
|
||||
mask = 1 << key->hw_key_idx;
|
||||
@ -425,11 +425,11 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* rt2x00lib can't determine the correct free
|
||||
* key_idx for pairwise keys. We have 2 registers
|
||||
* with key valid bits. The goal is simple, read
|
||||
* the first register, if that is full move to
|
||||
* with key valid bits. The goal is simple: read
|
||||
* the first register. If that is full, move to
|
||||
* the next register.
|
||||
* When both registers are full, we drop the key,
|
||||
* otherwise we use the first invalid entry.
|
||||
* When both registers are full, we drop the key.
|
||||
* Otherwise, we use the first invalid entry.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, SEC_CSR2, ®);
|
||||
if (reg && reg == ~0) {
|
||||
@ -464,8 +464,8 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
|
||||
&addr_entry, sizeof(addr_entry));
|
||||
|
||||
/*
|
||||
* Enable pairwise lookup table for given BSS idx,
|
||||
* without this received frames will not be decrypted
|
||||
* Enable pairwise lookup table for given BSS idx.
|
||||
* Without this, received frames will not be decrypted
|
||||
* by the hardware.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, SEC_CSR4, ®);
|
||||
@ -487,7 +487,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate
|
||||
* a particular key is valid. Because using the FIELD32()
|
||||
* defines directly will cause a lot of overhead we use
|
||||
* defines directly will cause a lot of overhead, we use
|
||||
* a calculation to determine the correct bit directly.
|
||||
*/
|
||||
if (key->hw_key_idx < 32) {
|
||||
@ -556,7 +556,7 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
|
||||
if (flags & CONFIG_UPDATE_TYPE) {
|
||||
/*
|
||||
* Clear current synchronisation setup.
|
||||
* For the Beacon base registers we only need to clear
|
||||
* For the Beacon base registers, we only need to clear
|
||||
* the first byte since that byte contains the VALID and OWNER
|
||||
* bits which (when set to 0) will invalidate the entire beacon.
|
||||
*/
|
||||
@ -1168,8 +1168,8 @@ static int rt61pci_check_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
return FW_BAD_LENGTH;
|
||||
|
||||
/*
|
||||
* The last 2 bytes in the firmware array are the crc checksum itself,
|
||||
* this means that we should never pass those 2 bytes to the crc
|
||||
* The last 2 bytes in the firmware array are the crc checksum itself.
|
||||
* This means that we should never pass those 2 bytes to the crc
|
||||
* algorithm.
|
||||
*/
|
||||
fw_crc = (data[len - 2] << 8 | data[len - 1]);
|
||||
@ -1986,7 +1986,7 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
|
||||
|
||||
/*
|
||||
* Hardware has stripped IV/EIV data from 802.11 frame during
|
||||
* decryption. It has provided the data seperately but rt2x00lib
|
||||
* decryption. It has provided the data separately but rt2x00lib
|
||||
* should decide if it should be reinserted.
|
||||
*/
|
||||
rxdesc->flags |= RX_FLAG_IV_STRIPPED;
|
||||
@ -2042,7 +2042,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
|
||||
* During each loop we will compare the freshly read
|
||||
* STA_CSR4 register value with the value read from
|
||||
* the previous loop. If the 2 values are equal then
|
||||
* we should stop processing because the chance it
|
||||
* we should stop processing because the chance is
|
||||
* quite big that the device has been unplugged and
|
||||
* we risk going into an endless loop.
|
||||
*/
|
||||
@ -2300,6 +2300,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF5325) &&
|
||||
@ -2330,7 +2331,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Detect if this device has an hardware controlled radio.
|
||||
* Detect if this device has a hardware controlled radio.
|
||||
*/
|
||||
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
|
||||
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
|
||||
@ -2355,7 +2356,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* When working with a RF2529 chip without double antenna
|
||||
* When working with a RF2529 chip without double antenna,
|
||||
* the antenna settings should be gathered from the NIC
|
||||
* eeprom word.
|
||||
*/
|
||||
@ -2668,7 +2669,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
|
||||
|
||||
/*
|
||||
* We only need to perform additional register initialization
|
||||
* for WMM queues/
|
||||
* for WMM queues.
|
||||
*/
|
||||
if (queue_idx >= 4)
|
||||
return 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -1825,6 +1825,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) ||
|
||||
rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -1431,3 +1431,4 @@ MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
|
||||
MODULE_ALIAS("spi:wl1251");
|
||||
MODULE_FIRMWARE(WL1251_FW_NAME);
|
||||
|
@ -1979,3 +1979,4 @@ module_exit(wl1271_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
|
||||
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
|
||||
MODULE_FIRMWARE(WL1271_FW_NAME);
|
||||
|
@ -112,6 +112,9 @@ exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
MODULE_FIRMWARE("zd1201-ap.fw");
|
||||
MODULE_FIRMWARE("zd1201.fw");
|
||||
|
||||
static void zd1201_usbfree(struct urb *urb)
|
||||
{
|
||||
struct zd1201 *zd = urb->context;
|
||||
|
@ -318,6 +318,13 @@ error:
|
||||
return r;
|
||||
}
|
||||
|
||||
MODULE_FIRMWARE(FW_ZD1211B_PREFIX "ur");
|
||||
MODULE_FIRMWARE(FW_ZD1211_PREFIX "ur");
|
||||
MODULE_FIRMWARE(FW_ZD1211B_PREFIX "ub");
|
||||
MODULE_FIRMWARE(FW_ZD1211_PREFIX "ub");
|
||||
MODULE_FIRMWARE(FW_ZD1211B_PREFIX "uphr");
|
||||
MODULE_FIRMWARE(FW_ZD1211_PREFIX "uphr");
|
||||
|
||||
/* Read data from device address space using "firmware interface" which does
|
||||
* not require firmware to be loaded. */
|
||||
int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len)
|
||||
|
@ -103,8 +103,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/dma.h>
|
||||
|
||||
/* This include could be elsewhere, since it is not wireless specific */
|
||||
#include "wireless/i82593.h"
|
||||
#include <linux/i82593.h>
|
||||
|
||||
static char version[] __initdata = "znet.c:v1.02 9/23/94 becker@scyld.com\n";
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
config ARLAN
|
||||
tristate "Aironet Arlan 655 & IC2200 DS support"
|
||||
depends on ISA && !64BIT
|
||||
depends on ISA && !64BIT && WLAN
|
||||
select WIRELESS_EXT
|
||||
---help---
|
||||
Aironet makes Arlan, a class of wireless LAN adapters. These use the
|
||||
|
@ -1,6 +1,6 @@
|
||||
config PCMCIA_NETWAVE
|
||||
tristate "Xircom Netwave AirSurfer Pcmcia wireless support"
|
||||
depends on PCMCIA
|
||||
depends on PCMCIA && WLAN
|
||||
select WIRELESS_EXT
|
||||
select WEXT_PRIV
|
||||
help
|
||||
|
@ -1,6 +1,6 @@
|
||||
config WAVELAN
|
||||
tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support"
|
||||
depends on ISA
|
||||
depends on ISA && WLAN
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
@ -25,7 +25,7 @@ config WAVELAN
|
||||
|
||||
config PCMCIA_WAVELAN
|
||||
tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support"
|
||||
depends on PCMCIA
|
||||
depends on PCMCIA && WLAN
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
|
@ -446,7 +446,7 @@
|
||||
#include <pcmcia/ds.h>
|
||||
|
||||
/* Wavelan declarations */
|
||||
#include "i82593.h" /* Definitions for the Intel chip */
|
||||
#include <linux/i82593.h> /* Definitions for the Intel chip */
|
||||
|
||||
#include "wavelan_cs.h" /* Others bits of the hardware */
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user