提交 23779897 编写于 作者: D David S. Miller
......@@ -30,10 +30,11 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <linux/if_arp.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <net/iw_handler.h>
#include <net/ieee80211.h>
#include <linux/dma-mapping.h>
#include <net/checksum.h>
......@@ -449,9 +450,9 @@ static size_t gelic_wl_synthesize_ie(u8 *buf,
/* element id */
if (rsn)
*buf++ = MFIE_TYPE_RSN;
*buf++ = WLAN_EID_RSN;
else
*buf++ = MFIE_TYPE_GENERIC;
*buf++ = WLAN_EID_GENERIC;
/* length filed; set later */
buf++;
......@@ -539,7 +540,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
break;
switch (item_id) {
case MFIE_TYPE_GENERIC:
case WLAN_EID_GENERIC:
if ((OUI_LEN + 1 <= item_len) &&
!memcmp(pos, wpa_oui, OUI_LEN) &&
pos[OUI_LEN] == 0x01) {
......@@ -547,7 +548,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
ie_info->wpa.len = item_len + 2;
}
break;
case MFIE_TYPE_RSN:
case WLAN_EID_RSN:
ie_info->rsn.data = pos - 2;
/* length includes the header */
ie_info->rsn.len = item_len + 2;
......@@ -581,7 +582,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev,
char *tmp;
u8 rate;
unsigned int i, j, len;
u8 buf[MAX_WPA_IE_LEN];
u8 buf[64]; /* arbitrary size large enough */
pr_debug("%s: <-\n", __func__);
......@@ -1734,14 +1735,14 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
target->essid_len = strnlen(scan_info->essid,
sizeof(scan_info->essid));
target->rate_len = 0;
for (r = 0; r < MAX_RATES_LENGTH; r++)
for (r = 0; r < 12; r++)
if (scan_info->rate[r])
target->rate_len++;
if (8 < target->rate_len)
pr_info("%s: AP returns %d rates\n", __func__,
target->rate_len);
target->rate_ext_len = 0;
for (r = 0; r < MAX_RATES_EX_LENGTH; r++)
for (r = 0; r < 16; r++)
if (scan_info->ext_rate[r])
target->rate_ext_len++;
list_move_tail(&target->list, &wl->network_list);
......
......@@ -164,8 +164,8 @@ struct gelic_eurus_scan_info {
__be16 security;
u8 bssid[8]; /* last ETH_ALEN are valid. bssid[0],[1] are unused */
u8 essid[32]; /* IW_ESSID_MAX_SIZE */
u8 rate[16]; /* first MAX_RATES_LENGTH(12) are valid */
u8 ext_rate[16]; /* first MAX_RATES_EX_LENGTH(16) are valid */
u8 rate[16]; /* first 12 are valid */
u8 ext_rate[16]; /* first 16 are valid */
__be32 reserved1;
__be32 reserved2;
__be32 reserved3;
......
......@@ -16,14 +16,7 @@ obj-$(CONFIG_WAVELAN) += wavelan.o
obj-$(CONFIG_PCMCIA_NETWAVE) += netwave_cs.o
obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan_cs.o
obj-$(CONFIG_HERMES) += orinoco.o hermes.o hermes_dld.o
obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o
obj-$(CONFIG_APPLE_AIRPORT) += airport.o
obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
obj-$(CONFIG_HERMES) += orinoco/
obj-$(CONFIG_AIRO) += airo.o
obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o
......
......@@ -1297,22 +1297,6 @@ static void adm8211_set_bssid(struct ieee80211_hw *dev, const u8 *bssid)
ADM8211_CSR_WRITE(ABDA1, reg);
}
static int adm8211_set_ssid(struct ieee80211_hw *dev, u8 *ssid, size_t ssid_len)
{
struct adm8211_priv *priv = dev->priv;
u8 buf[36];
if (ssid_len > 32)
return -EINVAL;
memset(buf, 0, sizeof(buf));
buf[0] = ssid_len;
memcpy(buf + 1, ssid, ssid_len);
adm8211_write_sram_bytes(dev, ADM8211_SRAM_SSID, buf, 33);
/* TODO: configure beacon for adhoc? */
return 0;
}
static int adm8211_config(struct ieee80211_hw *dev, u32 changed)
{
struct adm8211_priv *priv = dev->priv;
......@@ -1338,13 +1322,6 @@ static int adm8211_config_interface(struct ieee80211_hw *dev,
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
}
if (conf->ssid_len != priv->ssid_len ||
memcmp(conf->ssid, priv->ssid, conf->ssid_len)) {
adm8211_set_ssid(dev, conf->ssid, conf->ssid_len);
priv->ssid_len = conf->ssid_len;
memcpy(priv->ssid, conf->ssid, conf->ssid_len);
}
return 0;
}
......
......@@ -553,8 +553,6 @@ struct adm8211_priv {
int channel;
u8 bssid[ETH_ALEN];
u8 ssid[32];
size_t ssid_len;
u8 soft_rx_crc;
u8 retry_limit;
......
......@@ -47,10 +47,11 @@
#include <linux/ioport.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <net/ieee80211.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/ieee80211.h>
#include "airo.h"
#define DRV_NAME "airo"
......@@ -7265,56 +7266,53 @@ static inline char *airo_translate_scan(struct net_device *dev,
if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) {
unsigned int num_null_ies = 0;
u16 length = sizeof (bss->extra.iep);
struct ieee80211_info_element *info_element =
(struct ieee80211_info_element *) &bss->extra.iep;
u8 *ie = (void *)&bss->extra.iep;
while ((length >= sizeof(*info_element)) && (num_null_ies < 2)) {
if (sizeof(*info_element) + info_element->len > length) {
while ((length >= 2) && (num_null_ies < 2)) {
if (2 + ie[1] > length) {
/* Invalid element, don't continue parsing IE */
break;
}
switch (info_element->id) {
case MFIE_TYPE_SSID:
switch (ie[0]) {
case WLAN_EID_SSID:
/* Two zero-length SSID elements
* mean we're done parsing elements */
if (!info_element->len)
if (!ie[1])
num_null_ies++;
break;
case MFIE_TYPE_GENERIC:
if (info_element->len >= 4 &&
info_element->data[0] == 0x00 &&
info_element->data[1] == 0x50 &&
info_element->data[2] == 0xf2 &&
info_element->data[3] == 0x01) {
case WLAN_EID_GENERIC:
if (ie[1] >= 4 &&
ie[2] == 0x00 &&
ie[3] == 0x50 &&
ie[4] == 0xf2 &&
ie[5] == 0x01) {
iwe.cmd = IWEVGENIE;
iwe.u.data.length = min(info_element->len + 2,
MAX_WPA_IE_LEN);
/* 64 is an arbitrary cut-off */
iwe.u.data.length = min(ie[1] + 2,
64);
current_ev = iwe_stream_add_point(
info, current_ev,
end_buf, &iwe,
(char *) info_element);
end_buf, &iwe, ie);
}
break;
case MFIE_TYPE_RSN:
case WLAN_EID_RSN:
iwe.cmd = IWEVGENIE;
iwe.u.data.length = min(info_element->len + 2,
MAX_WPA_IE_LEN);
/* 64 is an arbitrary cut-off */
iwe.u.data.length = min(ie[1] + 2, 64);
current_ev = iwe_stream_add_point(
info, current_ev, end_buf,
&iwe, (char *) info_element);
&iwe, ie);
break;
default:
break;
}
length -= sizeof(*info_element) + info_element->len;
info_element =
(struct ieee80211_info_element *)&info_element->
data[info_element->len];
length -= 2 + ie[1];
ie += 2 + ie[1];
}
}
return current_ev;
......
......@@ -1093,10 +1093,11 @@ struct ath5k_hw {
u8 ah_sta_id[ETH_ALEN];
/* Current BSSID we are trying to assoc to / creating.
/* Current BSSID we are trying to assoc to / create.
* This is passed by mac80211 on config_interface() and cached here for
* use in resets */
u8 ah_bssid[ETH_ALEN];
u8 ah_bssid_mask[ETH_ALEN];
u32 ah_gpio[AR5K_MAX_GPIO];
int ah_gpio_npins;
......
......@@ -60,6 +60,9 @@
#include "debug.h"
static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
/******************\
......@@ -2975,12 +2978,13 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ath5k_softc *sc = hw->priv;
int ret = 0;
if (modparam_nohwcrypt)
return -EOPNOTSUPP;
switch (key->alg) {
case ALG_WEP:
/* XXX: fix hardware encryption, its not working. For now
* allow software encryption */
/* break; */
case ALG_TKIP:
break;
case ALG_CCMP:
return -EOPNOTSUPP;
default:
......@@ -2999,6 +3003,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
__set_bit(key->keyidx, sc->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);
......
......@@ -46,34 +46,45 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah)
{
u32 pcu_reg, beacon_reg, low_id, high_id;
pcu_reg = 0;
/* Preserve rest settings */
pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
| AR5K_STA_ID1_KEYSRCH_MODE
| (ah->ah_version == AR5K_AR5210 ?
(AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
beacon_reg = 0;
ATH5K_TRACE(ah->ah_sc);
switch (ah->ah_op_mode) {
case NL80211_IFTYPE_ADHOC:
pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA |
(ah->ah_version == AR5K_AR5210 ?
AR5K_STA_ID1_NO_PSPOLL : 0);
pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
beacon_reg |= AR5K_BCR_ADHOC;
if (ah->ah_version == AR5K_AR5210)
pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
else
AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC);
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA |
(ah->ah_version == AR5K_AR5210 ?
AR5K_STA_ID1_NO_PSPOLL : 0);
pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
beacon_reg |= AR5K_BCR_AP;
if (ah->ah_version == AR5K_AR5210)
pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
else
AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC);
break;
case NL80211_IFTYPE_STATION:
pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
(ah->ah_version == AR5K_AR5210 ?
pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
| (ah->ah_version == AR5K_AR5210 ?
AR5K_STA_ID1_PWR_SV : 0);
case NL80211_IFTYPE_MONITOR:
pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
(ah->ah_version == AR5K_AR5210 ?
pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
| (ah->ah_version == AR5K_AR5210 ?
AR5K_STA_ID1_NO_PSPOLL : 0);
break;
......@@ -130,6 +141,8 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
}
/* TODO: Handle ANI stats */
}
/**
......@@ -254,6 +267,10 @@ void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
* @mac: The card's mac address
*
* Set station id on hw using the provided mac address
*
* NOTE: This is only called during attach, don't call it
* on reset because it overwrites all AR5K_STA_ID1 settings.
* We have set_opmode (above) for reset.
*/
int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
{
......@@ -290,8 +307,10 @@ void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
* Set simple BSSID mask on 5212
*/
if (ah->ah_version == AR5K_AR5212) {
ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0);
ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1);
ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
AR5K_BSS_IDM0);
ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
AR5K_BSS_IDM1);
}
/*
......@@ -415,6 +434,9 @@ int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
u32 low_id, high_id;
ATH5K_TRACE(ah->ah_sc);
/* Cache bssid mask so that we can restore it
* on reset */
memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
if (ah->ah_version == AR5K_AR5212) {
low_id = AR5K_LOW_ID(mask);
high_id = AR5K_HIGH_ID(mask);
......@@ -576,7 +598,7 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
filter |= AR5K_RX_FILTER_PROM;
}
/*Zero length DMA*/
/*Zero length DMA (phy error reporting) */
if (data)
AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
else
......@@ -661,7 +683,12 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
* Set the additional timers by mode
*/
switch (ah->ah_op_mode) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_STATION:
/* In STA mode timer1 is used as next wakeup
* timer and timer2 as next CFP duration start
* timer. Both in 1/8TUs. */
/* TODO: PCF handling */
if (ah->ah_version == AR5K_AR5210) {
timer1 = 0xffffffff;
timer2 = 0xffffffff;
......@@ -669,27 +696,60 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
timer1 = 0x0000ffff;
timer2 = 0x0007ffff;
}
/* Mark associated AP as PCF incapable for now */
AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF);
break;
case NL80211_IFTYPE_ADHOC:
AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM);
default:
/* On non-STA modes timer1 is used as next DMA
* beacon alert (DBA) timer and timer2 as next
* software beacon alert. Both in 1/8TUs. */
timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3;
timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3;
break;
}
/* Timer3 marks the end of our ATIM window
* a zero length window is not allowed because
* we 'll get no beacons */
timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
/*
* Set the beacon register and enable all timers.
* (next beacon, DMA beacon, software beacon, ATIM window time)
*/
ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
/* When in AP mode zero timer0 to start TSF */
if (ah->ah_op_mode == NL80211_IFTYPE_AP)
ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
else
ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
/* Force a TSF reset if requested and enable beacons */
if (interval & AR5K_BEACON_RESET_TSF)
ath5k_hw_reset_tsf(ah);
ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD |
AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE),
AR5K_BEACON);
AR5K_BEACON_ENABLE),
AR5K_BEACON);
/* Flush any pending BMISS interrupts on ISR by
* performing a clear-on-write operation on PISR
* register for the BMISS bit (writing a bit on
* ISR togles a reset for that bit and leaves
* the rest bits intact) */
if (ah->ah_version == AR5K_AR5210)
ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR);
else
ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR);
/* TODO: Set enchanced sleep registers on AR5212
* based on vif->bss_conf params, until then
* disable power save reporting.*/
AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV);
}
#if 0
......@@ -899,14 +959,26 @@ int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
*/
int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
{
unsigned int i;
unsigned int i, type;
u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
ATH5K_TRACE(ah->ah_sc);
AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
/* Reset associated MIC entry if TKIP
* is enabled located at offset (entry + 64) */
if (type == AR5K_KEYTABLE_TYPE_TKIP) {
AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE);
for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
ath5k_hw_reg_write(ah, 0,
AR5K_KEYTABLE_OFF(micentry, i));
}
/*
* Set NULL encryption on AR5212+
*
......@@ -916,10 +988,16 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
* Note2: Windows driver (ndiswrapper) sets this to
* 0x00000714 instead of 0x00000007
*/
if (ah->ah_version > AR5K_AR5211)
if (ah->ah_version > AR5K_AR5211) {
ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
AR5K_KEYTABLE_TYPE(entry));
if (type == AR5K_KEYTABLE_TYPE_TKIP) {
ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
AR5K_KEYTABLE_TYPE(micentry));
}
}
return 0;
}
......@@ -943,17 +1021,29 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
const struct ieee80211_key_conf *key, const u8 *mac)
{
unsigned int i;
int keylen;
__le32 key_v[5] = {};
__le32 key0 = 0, key1 = 0;
__le32 *rxmic, *txmic;
u32 keytype;
u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
bool is_tkip;
ATH5K_TRACE(ah->ah_sc);
/* key->keylen comes in from mac80211 in bytes */
is_tkip = (key->alg == ALG_TKIP);
/*
* key->keylen comes in from mac80211 in bytes.
* TKIP is 128 bit + 128 bit mic
*/
keylen = (is_tkip) ? (128 / 8) : key->keylen;
if (key->keylen > AR5K_KEYTABLE_SIZE / 8)
if (entry > AR5K_KEYTABLE_SIZE ||
(is_tkip && micentry > AR5K_KEYTABLE_SIZE))
return -EOPNOTSUPP;
switch (key->keylen) {
switch (keylen) {
/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */
case 40 / 8:
memcpy(&key_v[0], key->key, 5);
......@@ -967,24 +1057,66 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
memcpy(&key_v[4], &key->key[12], 1);
keytype = AR5K_KEYTABLE_TYPE_104;
break;
/* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */
/* WEP/TKIP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */
case 128 / 8:
memcpy(&key_v[0], &key->key[0], 6);
memcpy(&key_v[2], &key->key[6], 6);
memcpy(&key_v[4], &key->key[12], 4);
keytype = AR5K_KEYTABLE_TYPE_128;
keytype = is_tkip ?
AR5K_KEYTABLE_TYPE_TKIP :
AR5K_KEYTABLE_TYPE_128;
break;
default:
return -EINVAL; /* shouldn't happen */
}
/* intentionally corrupt key until mic is installed */
if (is_tkip) {
key0 = key_v[0] = ~key_v[0];
key1 = key_v[1] = ~key_v[1];
}
for (i = 0; i < ARRAY_SIZE(key_v); i++)
ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
AR5K_KEYTABLE_OFF(entry, i));
ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
if (is_tkip) {
/* Install rx/tx MIC */
rxmic = (__le32 *) &key->key[16];
txmic = (__le32 *) &key->key[24];
#if 0
/* MISC_MODE register & 0x04 - for mac srev >= griffin */
key_v[0] = rxmic[0];
key_v[1] = (txmic[0] >> 16) & 0xffff;
key_v[2] = rxmic[1];
key_v[3] = txmic[0] & 0xffff;
key_v[4] = txmic[1];
#else
key_v[0] = rxmic[0];
key_v[1] = 0;
key_v[2] = rxmic[1];
key_v[3] = 0;
key_v[4] = 0;
#endif
for (i = 0; i < ARRAY_SIZE(key_v); i++)
ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
AR5K_KEYTABLE_OFF(micentry, i));
ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
AR5K_KEYTABLE_TYPE(micentry));
ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry));
ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry));
/* restore first 2 words of key */
ath5k_hw_reg_write(ah, le32_to_cpu(~key0),
AR5K_KEYTABLE_OFF(entry, 0));
ath5k_hw_reg_write(ah, le32_to_cpu(~key1),
AR5K_KEYTABLE_OFF(entry, 1));
}
return ath5k_hw_set_key_lladdr(ah, entry, mac);
}
......
......@@ -1114,14 +1114,16 @@
#define AR5K_PCU_MAX 0x8fff
/*
* First station id register (MAC address in lower 32 bits)
* First station id register (Lower 32 bits of MAC address)
*/
#define AR5K_STA_ID0 0x8000
#define AR5K_STA_ID0 0x8000
#define AR5K_STA_ID0_ARRD_L32 0xffffffff
/*
* Second station id register (MAC address in upper 16 bits)
* Second station id register (Upper 16 bits of MAC address + PCU settings)
*/
#define AR5K_STA_ID1 0x8004 /* Register Address */
#define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC addres */
#define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */
#define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */
#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */
......@@ -1811,6 +1813,10 @@
#define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7)
#define AR5K_KEYTABLE_VALID 0x00008000
/* If key type is TKIP and MIC is enabled
* MIC key goes in offset entry + 64 */
#define AR5K_KEYTABLE_MIC_OFFSET 64
/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit
* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit
* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit
......
ath9k-y += hw.o \
eeprom.o \
mac.o \
calib.o \
ani.o \
phy.o \
regd.o \
beacon.o \
......
此差异已折叠。
......@@ -828,195 +828,251 @@ struct chan_centers {
u16 ext_center;
};
int ath_hal_getcapability(struct ath_hal *ah,
enum ath9k_capability_type type,
u32 capability,
u32 *result);
const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
u32 mode);
void ath9k_hw_detach(struct ath_hal *ah);
struct ath_hal *ath9k_hw_attach(u16 devid,
struct ath_softc *sc,
void __iomem *mem,
int *error);
bool ath9k_regd_init_channels(struct ath_hal *ah,
u32 maxchans, u32 *nchans,
u8 *regclassids,
u32 maxregids, u32 *nregids,
u16 cc,
bool enableOutdoor,
bool enableExtendedChannels);
/* Helpers */
enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
const struct ath9k_channel *chan);
bool ath9k_hw_wait(struct ath_hal *ah, u32 reg, u32 mask, u32 val);
u32 ath9k_hw_reverse_bits(u32 val, u32 n);
bool ath9k_get_channel_edges(struct ath_hal *ah,
u16 flags, u16 *low,
u16 *high);
u16 ath9k_hw_computetxtime(struct ath_hal *ah,
const struct ath9k_rate_table *rates,
u32 frameLen, u16 rateix,
bool shortPreamble);
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah,
enum ath9k_int ints);
bool ath9k_hw_reset(struct ath_hal *ah,
struct ath9k_channel *chan,
void ath9k_hw_get_channel_centers(struct ath_hal *ah,
struct ath9k_channel *chan,
struct chan_centers *centers);
/* Attach, Detach */
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
void ath9k_hw_detach(struct ath_hal *ah);
struct ath_hal *ath9k_hw_attach(u16 devid, struct ath_softc *sc,
void __iomem *mem, int *error);
void ath9k_hw_rfdetach(struct ath_hal *ah);
/* HW Reset */
bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode,
u8 txchainmask, u8 rxchainmask,
enum ath9k_ht_extprotspacing extprotspacing,
bool bChannelChange,
int *status);
bool ath9k_hw_phy_disable(struct ath_hal *ah);
void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
bool *isCalDone);
void ath9k_hw_ani_monitor(struct ath_hal *ah,
const struct ath9k_node_stats *stats,
struct ath9k_channel *chan);
bool ath9k_hw_calibrate(struct ath_hal *ah,
struct ath9k_channel *chan,
u8 rxchainmask,
bool longcal,
bool *isCalDone);
s16 ath9k_hw_getchan_noise(struct ath_hal *ah,
struct ath9k_channel *chan);
void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
u16 assocId);
void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits);
void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
u16 assocId);
bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q);
void ath9k_hw_reset_tsf(struct ath_hal *ah);
bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry);
bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry,
const u8 *mac);
bool ath9k_hw_set_keycache_entry(struct ath_hal *ah,
u16 entry,
const struct ath9k_keyval *k,
const u8 *mac,
int xorKey);
bool ath9k_hw_set_tsfadjust(struct ath_hal *ah,
u32 setting);
void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore);
bool ath9k_hw_intrpend(struct ath_hal *ah);
bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked);
bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah,
bool bIncTrigLevel);
void ath9k_hw_procmibevent(struct ath_hal *ah,
const struct ath9k_node_stats *stats);
bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set);
void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode);
bool ath9k_hw_phycounters(struct ath_hal *ah);
bool bChannelChange, int *status);
/* Key Cache Management */
bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry);
bool ath9k_hw_getcapability(struct ath_hal *ah,
enum ath9k_capability_type type,
u32 capability,
u32 *result);
bool ath9k_hw_setcapability(struct ath_hal *ah,
enum ath9k_capability_type type,
u32 capability,
u32 setting,
int *status);
u32 ath9k_hw_getdefantenna(struct ath_hal *ah);
void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac);
void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask);
bool ath9k_hw_setbssidmask(struct ath_hal *ah,
const u8 *mask);
bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry, const u8 *mac);
bool ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
const struct ath9k_keyval *k,
const u8 *mac, int xorKey);
bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry);
/* Power Management */
bool ath9k_hw_setpower(struct ath_hal *ah,
enum ath9k_power_mode mode);
enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah);
u64 ath9k_hw_gettsf64(struct ath_hal *ah);
void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore);
/* Beacon timers */
void ath9k_hw_beaconinit(struct ath_hal *ah, u32 next_beacon, u32 beacon_period);
void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
const struct ath9k_beacon_state *bs);
/* Rate table */
const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
u32 mode);
/* HW Capabilities */
bool ath9k_hw_fill_cap_info(struct ath_hal *ah);
bool ath9k_hw_getcapability(struct ath_hal *ah, enum ath9k_capability_type type,
u32 capability, u32 *result);
bool ath9k_hw_setcapability(struct ath_hal *ah, enum ath9k_capability_type type,
u32 capability, u32 setting, int *status);
/* GPIO / RFKILL / Antennae */
void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio);
u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
u32 ah_signal_type);
void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val);
#ifdef CONFIG_RFKILL
void ath9k_enable_rfkill(struct ath_hal *ah);
#endif
int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg);
u32 ath9k_hw_getdefantenna(struct ath_hal *ah);
bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us);
void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna);
bool ath9k_hw_setantennaswitch(struct ath_hal *ah,
enum ath9k_ant_setting settings,
struct ath9k_channel *chan,
u8 *tx_chainmask,
u8 *rx_chainmask,
u8 *antenna_cfgd);
void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna);
int ath9k_hw_select_antconfig(struct ath_hal *ah,
u32 cfg);
bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q,
u32 txdp);
/* General Operation */
u32 ath9k_hw_getrxfilter(struct ath_hal *ah);
void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits);
bool ath9k_hw_phy_disable(struct ath_hal *ah);
bool ath9k_hw_disable(struct ath_hal *ah);
bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit);
void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac);
bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac);
void ath9k_hw_setopmode(struct ath_hal *ah);
void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0, u32 filter1);
void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask);
bool ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask);
void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, u16 assocId);
u64 ath9k_hw_gettsf64(struct ath_hal *ah);
void ath9k_hw_reset_tsf(struct ath_hal *ah);
bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting);
bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us);
void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode);
/* Regulatory */
bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah);
struct ath9k_channel* ath9k_regd_check_channel(struct ath_hal *ah,
const struct ath9k_channel *c);
u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan);
u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
struct ath9k_channel *chan);
bool ath9k_regd_init_channels(struct ath_hal *ah,
u32 maxchans, u32 *nchans, u8 *regclassids,
u32 maxregids, u32 *nregids, u16 cc,
bool enableOutdoor, bool enableExtendedChannels);
/* ANI */
void ath9k_ani_reset(struct ath_hal *ah);
void ath9k_hw_ani_monitor(struct ath_hal *ah,
const struct ath9k_node_stats *stats,
struct ath9k_channel *chan);
bool ath9k_hw_phycounters(struct ath_hal *ah);
void ath9k_enable_mib_counters(struct ath_hal *ah);
void ath9k_hw_disable_mib_counters(struct ath_hal *ah);
u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
u32 *rxc_pcnt,
u32 *rxf_pcnt,
u32 *txf_pcnt);
void ath9k_hw_procmibevent(struct ath_hal *ah,
const struct ath9k_node_stats *stats);
void ath9k_hw_ani_setup(struct ath_hal *ah);
void ath9k_hw_ani_attach(struct ath_hal *ah);
void ath9k_hw_ani_detach(struct ath_hal *ah);
/* Calibration */
void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
bool *isCalDone);
void ath9k_hw_start_nfcal(struct ath_hal *ah);
void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan);
int16_t ath9k_hw_getnf(struct ath_hal *ah,
struct ath9k_channel *chan);
void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah);
s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan);
bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
u8 rxchainmask, bool longcal,
bool *isCalDone);
bool ath9k_hw_init_cal(struct ath_hal *ah,
struct ath9k_channel *chan);
/* EEPROM */
int ath9k_hw_set_txpower(struct ath_hal *ah,
struct ath9k_channel *chan,
u16 cfgCtl,
u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower,
u8 powerLimit);
void ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan);
bool ath9k_hw_set_power_per_rate_table(struct ath_hal *ah,
struct ath9k_channel *chan,
int16_t *ratesArray,
u16 cfgCtl,
u8 AntennaReduction,
u8 twiceMaxRegulatoryPower,
u8 powerLimit);
bool ath9k_hw_set_power_cal_table(struct ath_hal *ah,
struct ath9k_channel *chan,
int16_t *pTxPowerIndexOffset);
bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
struct ath9k_channel *chan);
int ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
struct ath9k_channel *chan,
u8 index, u16 *config);
u8 ath9k_hw_get_num_ant_config(struct ath_hal *ah,
enum ieee80211_band freq_band);
u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, u16 i, bool is2GHz);
int ath9k_hw_eeprom_attach(struct ath_hal *ah);
/* Interrupt Handling */
bool ath9k_hw_intrpend(struct ath_hal *ah);
bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked);
enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah);
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints);
/* MAC (PCU/QCU) */
void ath9k_hw_dmaRegDump(struct ath_hal *ah);
u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q);
bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q, u32 txdp);
bool ath9k_hw_txstart(struct ath_hal *ah, u32 q);
u16 ath9k_hw_computetxtime(struct ath_hal *ah,
const struct ath9k_rate_table *rates,
u32 frameLen, u16 rateix,
bool shortPreamble);
u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q);
bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel);
bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q);
bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
u32 segLen, bool firstSeg,
bool lastSeg, const struct ath_desc *ds0);
void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds);
int ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds);
void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
u32 keyIx, enum ath9k_key_type keyType, u32 flags);
void ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
struct ath_desc *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags);
void ath9k_hw_set11n_burstduration(struct ath_hal *ah,
struct ath_desc *ds,
void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
u32 aggrLen);
void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
u32 numDelims);
void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds);
void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds);
void ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
u32 burstDuration);
void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds);
u32 ath9k_hw_reverse_bits(u32 val, u32 n);
bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q);
u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan);
u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
struct ath9k_channel *chan);
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
struct ath9k_tx_queue_info *qinfo);
void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
u32 vmf);
void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs);
bool ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
const struct ath9k_tx_queue_info *qinfo);
struct ath9k_channel *ath9k_regd_check_channel(struct ath_hal *ah,
const struct ath9k_channel *c);
void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
u32 pktLen, enum ath9k_pkt_type type,
u32 txPower, u32 keyIx,
enum ath9k_key_type keyType, u32 flags);
bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
u32 segLen, bool firstSeg,
bool lastSeg,
const struct ath_desc *ds0);
u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
u32 *rxc_pcnt,
u32 *rxf_pcnt,
u32 *txf_pcnt);
void ath9k_hw_dmaRegDump(struct ath_hal *ah);
void ath9k_hw_beaconinit(struct ath_hal *ah,
u32 next_beacon, u32 beacon_period);
void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
const struct ath9k_beacon_state *bs);
bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
struct ath9k_tx_queue_info *qinfo);
int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
const struct ath9k_tx_queue_info *qinfo);
bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q);
bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q);
int ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
u32 pa, struct ath_desc *nds, u64 tsf);
bool ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
u32 size, u32 flags);
bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set);
void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp);
void ath9k_hw_rxena(struct ath_hal *ah);
void ath9k_hw_setopmode(struct ath_hal *ah);
bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac);
void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0,
u32 filter1);
u32 ath9k_hw_getrxfilter(struct ath_hal *ah);
void ath9k_hw_startpcureceive(struct ath_hal *ah);
void ath9k_hw_stoppcurecv(struct ath_hal *ah);
bool ath9k_hw_stopdmarecv(struct ath_hal *ah);
int ath9k_hw_rxprocdesc(struct ath_hal *ah,
struct ath_desc *ds, u32 pa,
struct ath_desc *nds, u64 tsf);
u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q);
int ath9k_hw_txprocdesc(struct ath_hal *ah,
struct ath_desc *ds);
void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
u32 numDelims);
void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
u32 aggrLen);
void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds);
bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q);
void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs);
void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds);
void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah,
struct ath_desc *ds, u32 vmf);
bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit);
bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah);
int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
const struct ath9k_tx_queue_info *qinfo);
u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q);
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
bool ath9k_hw_disable(struct ath_hal *ah);
void ath9k_hw_rfdetach(struct ath_hal *ah);
void ath9k_hw_get_channel_centers(struct ath_hal *ah,
struct ath9k_channel *chan,
struct chan_centers *centers);
bool ath9k_get_channel_edges(struct ath_hal *ah,
u16 flags, u16 *low,
u16 *high);
void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
u32 ah_signal_type);
void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value);
u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio);
#endif
......@@ -114,7 +114,7 @@ static void ath_beacon_setup(struct ath_softc *sc,
ath9k_hw_set11n_txdesc(ah, ds,
skb->len + FCS_LEN, /* frame length */
ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */
avp->av_btxctl.txpower, /* txpower XXX */
MAX_RATE_POWER, /* FIXME */
ATH9K_TXKEYIX_INVALID, /* no encryption */
ATH9K_KEY_TYPE_CLEAR, /* no encryption */
flags /* no ack,
......@@ -152,12 +152,14 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
struct ath_vap *avp;
struct sk_buff *skb;
struct ath_txq *cabq;
struct ieee80211_vif *vif;
struct ieee80211_tx_info *info;
int cabq_depth;
avp = sc->sc_vaps[if_id];
ASSERT(avp);
vif = sc->sc_vaps[if_id];
ASSERT(vif);
avp = (void *)vif->drv_priv;
cabq = sc->sc_cabq;
if (avp->av_bcbuf == NULL) {
......@@ -174,7 +176,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
PCI_DMA_TODEVICE);
}
skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
skb = ieee80211_beacon_get(sc->hw, vif);
bf->bf_mpdu = skb;
if (skb == NULL)
return NULL;
......@@ -196,7 +198,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
skb_end_pointer(skb) - skb->head,
PCI_DMA_TODEVICE);
skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
skb = ieee80211_get_buffered_bc(sc->hw, vif);
/*
* if the CABQ traffic from previous DTIM is pending and the current
......@@ -232,7 +234,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
*/
while (skb) {
ath_tx_cabq(sc, skb);
skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
skb = ieee80211_get_buffered_bc(sc->hw, vif);
}
return bf;
......@@ -244,13 +246,16 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
*/
static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
{
struct ieee80211_vif *vif;
struct ath_hal *ah = sc->sc_ah;
struct ath_buf *bf;
struct ath_vap *avp;
struct sk_buff *skb;
avp = sc->sc_vaps[if_id];
ASSERT(avp);
vif = sc->sc_vaps[if_id];
ASSERT(vif);
avp = (void *)vif->drv_priv;
if (avp->av_bcbuf == NULL) {
DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n",
......@@ -300,14 +305,17 @@ int ath_beaconq_setup(struct ath_hal *ah)
*/
int ath_beacon_alloc(struct ath_softc *sc, int if_id)
{
struct ieee80211_vif *vif;
struct ath_vap *avp;
struct ieee80211_hdr *hdr;
struct ath_buf *bf;
struct sk_buff *skb;
__le64 tstamp;
avp = sc->sc_vaps[if_id];
ASSERT(avp);
vif = sc->sc_vaps[if_id];
ASSERT(vif);
avp = (void *)vif->drv_priv;
/* Allocate a beacon descriptor if we haven't done so. */
if (!avp->av_bcbuf) {
......@@ -363,7 +371,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
* FIXME: Fill avp->av_btxctl.txpower and
* avp->av_btxctl.shortPreamble
*/
skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
skb = ieee80211_beacon_get(sc->hw, vif);
if (skb == NULL) {
DPRINTF(sc, ATH_DBG_BEACON, "%s: cannot get skb\n",
__func__);
......@@ -652,15 +660,21 @@ void ath_bstuck_process(struct ath_softc *sc)
*/
void ath_beacon_config(struct ath_softc *sc, int if_id)
{
struct ieee80211_vif *vif;
struct ath_hal *ah = sc->sc_ah;
struct ath_beacon_config conf;
struct ath_vap *avp;
enum ath9k_opmode av_opmode;
u32 nexttbtt, intval;
if (if_id != ATH_IF_ID_ANY)
av_opmode = sc->sc_vaps[if_id]->av_opmode;
else
if (if_id != ATH_IF_ID_ANY) {
vif = sc->sc_vaps[if_id];
ASSERT(vif);
avp = (void *)vif->drv_priv;
av_opmode = avp->av_opmode;
} else {
av_opmode = sc->sc_ah->ah_opmode;
}
memset(&conf, 0, sizeof(struct ath_beacon_config));
......
此差异已折叠。
......@@ -14,13 +14,9 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Implementation of the main "ATH" layer. */
#include "core.h"
#include "regd.h"
static int ath_outdoor; /* enable outdoor use */
static u32 ath_chainmask_sel_up_rssi_thres =
ATH_CHAINMASK_SEL_UP_RSSI_THRES;
static u32 ath_chainmask_sel_down_rssi_thres =
......@@ -47,6 +43,41 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz)
*csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
}
static u8 parse_mpdudensity(u8 mpdudensity)
{
/*
* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
* 0 for no restriction
* 1 for 1/4 us
* 2 for 1/2 us
* 3 for 1 us
* 4 for 2 us
* 5 for 4 us
* 6 for 8 us
* 7 for 16 us
*/
switch (mpdudensity) {
case 0:
return 0;
case 1:
case 2:
case 3:
/* Our lower layer calculations limit our precision to
1 microsecond */
return 1;
case 4:
return 2;
case 5:
return 4;
case 6:
return 8;
case 7:
return 16;
default:
return 0;
}
}
/*
* Set current operating mode
*
......@@ -155,17 +186,10 @@ static int ath_setup_channels(struct ath_softc *sc)
struct ath9k_channel *c;
/* Fill in ah->ah_channels */
if (!ath9k_regd_init_channels(ah,
ATH_CHAN_MAX,
(u32 *)&nchan,
regclassids,
ATH_REGCLASSIDS_MAX,
&nregclass,
CTRY_DEFAULT,
false,
1)) {
if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan,
regclassids, ATH_REGCLASSIDS_MAX,
&nregclass, CTRY_DEFAULT, false, 1)) {
u32 rd = ah->ah_currentRD;
DPRINTF(sc, ATH_DBG_FATAL,
"%s: unable to collect channel list; "
"regdomain likely %u country code %u\n",
......@@ -186,40 +210,32 @@ static int ath_setup_channels(struct ath_softc *sc)
chan_2ghz[a].max_power = c->maxTxPower;
if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
chan_2ghz[a].flags |=
IEEE80211_CHAN_NO_IBSS;
chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS;
if (c->channelFlags & CHANNEL_PASSIVE)
chan_2ghz[a].flags |=
IEEE80211_CHAN_PASSIVE_SCAN;
chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
band_2ghz->n_channels = ++a;
DPRINTF(sc, ATH_DBG_CONFIG,
"%s: 2MHz channel: %d, "
"channelFlags: 0x%x\n",
__func__,
c->channel,
c->channelFlags);
__func__, c->channel, c->channelFlags);
} else if (IS_CHAN_5GHZ(c)) {
chan_5ghz[b].band = IEEE80211_BAND_5GHZ;
chan_5ghz[b].center_freq = c->channel;
chan_5ghz[b].max_power = c->maxTxPower;
if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
chan_5ghz[b].flags |=
IEEE80211_CHAN_NO_IBSS;
chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS;
if (c->channelFlags & CHANNEL_PASSIVE)
chan_5ghz[b].flags |=
IEEE80211_CHAN_PASSIVE_SCAN;
chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
band_5ghz->n_channels = ++b;
DPRINTF(sc, ATH_DBG_CONFIG,
"%s: 5MHz channel: %d, "
"channelFlags: 0x%x\n",
__func__,
c->channel,
c->channelFlags);
__func__, c->channel, c->channelFlags);
}
}
......@@ -260,44 +276,6 @@ static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan)
return ATH9K_MODE_11B;
}
/*
* Stop the device, grabbing the top-level lock to protect
* against concurrent entry through ath_init (which can happen
* if another thread does a system call and the thread doing the
* stop is preempted).
*/
static int ath_stop(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %ld\n",
__func__, sc->sc_flags & SC_OP_INVALID);
/*
* Shutdown the hardware and driver:
* stop output from above
* turn off timers
* disable interrupts
* clear transmit machinery
* clear receive machinery
* turn off the radio
* reclaim beacon resources
*
* Note that some of this work is not possible if the
* hardware is gone (invalid).
*/
ath_draintxq(sc, false);
if (!(sc->sc_flags & SC_OP_INVALID)) {
ath_stoprecv(sc);
ath9k_hw_phy_disable(ah);
} else
sc->sc_rxlink = NULL;
return 0;
}
/*
* Set the current channel
*
......@@ -606,114 +584,6 @@ static void ath_ani_calibrate(unsigned long data)
mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval));
}
/******************/
/* VAP management */
/******************/
int ath_vap_attach(struct ath_softc *sc,
int if_id,
struct ieee80211_vif *if_data,
enum ath9k_opmode opmode)
{
struct ath_vap *avp;
if (if_id >= ATH_BCBUF || sc->sc_vaps[if_id] != NULL) {
DPRINTF(sc, ATH_DBG_FATAL,
"%s: Invalid interface id = %u\n", __func__, if_id);
return -EINVAL;
}
switch (opmode) {
case ATH9K_M_STA:
case ATH9K_M_IBSS:
case ATH9K_M_MONITOR:
break;
case ATH9K_M_HOSTAP:
/* XXX not right, beacon buffer is allocated on RUN trans */
if (list_empty(&sc->sc_bbuf))
return -ENOMEM;
break;
default:
return -EINVAL;
}
/* create ath_vap */
avp = kmalloc(sizeof(struct ath_vap), GFP_KERNEL);
if (avp == NULL)
return -ENOMEM;
memset(avp, 0, sizeof(struct ath_vap));
avp->av_if_data = if_data;
/* Set the VAP opmode */
avp->av_opmode = opmode;
avp->av_bslot = -1;
if (opmode == ATH9K_M_HOSTAP)
ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
sc->sc_vaps[if_id] = avp;
sc->sc_nvaps++;
/* Set the device opmode */
sc->sc_ah->ah_opmode = opmode;
/* default VAP configuration */
avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE;
avp->av_config.av_fixed_retryset = 0x03030303;
return 0;
}
int ath_vap_detach(struct ath_softc *sc, int if_id)
{
struct ath_hal *ah = sc->sc_ah;
struct ath_vap *avp;
avp = sc->sc_vaps[if_id];
if (avp == NULL) {
DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n",
__func__, if_id);
return -EINVAL;
}
/*
* Quiesce the hardware while we remove the vap. In
* particular we need to reclaim all references to the
* vap state by any frames pending on the tx queues.
*
* XXX can we do this w/o affecting other vap's?
*/
ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */
ath_draintxq(sc, false); /* stop xmit side */
ath_stoprecv(sc); /* stop recv side */
ath_flushrecv(sc); /* flush recv queue */
kfree(avp);
sc->sc_vaps[if_id] = NULL;
sc->sc_nvaps--;
return 0;
}
int ath_vap_config(struct ath_softc *sc,
int if_id, struct ath_vap_config *if_config)
{
struct ath_vap *avp;
if (if_id >= ATH_BCBUF) {
DPRINTF(sc, ATH_DBG_FATAL,
"%s: Invalid interface id = %u\n", __func__, if_id);
return -EINVAL;
}
avp = sc->sc_vaps[if_id];
ASSERT(avp != NULL);
if (avp)
memcpy(&avp->av_config, if_config, sizeof(avp->av_config));
return 0;
}
/********/
/* Core */
/********/
......@@ -727,16 +597,6 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n",
__func__, sc->sc_ah->ah_opmode);
/*
* Stop anything previously setup. This is safe
* whether this is the first time through or not.
*/
ath_stop(sc);
/* Initialize chanmask selection */
sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask;
sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
/* Reset SERDES registers */
ath9k_hw_configpcipowersave(ah, 0);
......@@ -762,6 +622,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
goto done;
}
spin_unlock_bh(&sc->sc_resetlock);
/*
* This is needed only to setup initial state
* but it's best done after a reset.
......@@ -781,6 +642,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
error = -EIO;
goto done;
}
/* Setup our intr mask. */
sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX
| ATH9K_INT_RXEOL | ATH9K_INT_RXORN
......@@ -810,30 +672,60 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
(sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
!sc->sc_config.swBeaconProcess)
sc->sc_imask |= ATH9K_INT_TIM;
/*
* Don't enable interrupts here as we've not yet built our
* vap and node data structures, which will be needed as soon
* as we start receiving.
*/
ath_setcurmode(sc, ath_chan2mode(initial_chan));
/* XXX: we must make sure h/w is ready and clear invalid flag
* before turning on interrupt. */
sc->sc_flags &= ~SC_OP_INVALID;
/* Disable BMISS interrupt when we're not associated */
sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
ath9k_hw_set_interrupts(sc->sc_ah,sc->sc_imask);
ieee80211_wake_queues(sc->hw);
done:
return error;
}
void ath_stop(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Cleaning up\n", __func__);
ieee80211_stop_queues(sc->hw);
/* make sure h/w will not generate any interrupt
* before setting the invalid flag. */
ath9k_hw_set_interrupts(ah, 0);
if (!(sc->sc_flags & SC_OP_INVALID)) {
ath_draintxq(sc, false);
ath_stoprecv(sc);
ath9k_hw_phy_disable(ah);
} else
sc->sc_rxlink = NULL;
#ifdef CONFIG_RFKILL
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
#endif
/* disable HAL and put h/w to sleep */
ath9k_hw_disable(sc->sc_ah);
ath9k_hw_configpcipowersave(sc->sc_ah, 1);
sc->sc_flags |= SC_OP_INVALID;
}
int ath_reset(struct ath_softc *sc, bool retry_tx)
{
struct ath_hal *ah = sc->sc_ah;
int status;
int error = 0;
ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */
ath_draintxq(sc, retry_tx); /* stop xmit */
ath_stoprecv(sc); /* stop recv */
ath_flushrecv(sc); /* flush recv queue */
ath9k_hw_set_interrupts(ah, 0);
ath_draintxq(sc, retry_tx);
ath_stoprecv(sc);
ath_flushrecv(sc);
/* Reset chip */
spin_lock_bh(&sc->sc_resetlock);
......@@ -848,7 +740,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
}
spin_unlock_bh(&sc->sc_resetlock);
if (ath_startrecv(sc) != 0) /* restart recv */
if (ath_startrecv(sc) != 0)
DPRINTF(sc, ATH_DBG_FATAL,
"%s: unable to start recv logic\n", __func__);
......@@ -881,29 +773,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
return error;
}
int ath_suspend(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
/* No I/O if device has been surprise removed */
if (sc->sc_flags & SC_OP_INVALID)
return -EIO;
/* Shut off the interrupt before setting sc->sc_invalid to '1' */
ath9k_hw_set_interrupts(ah, 0);
/* XXX: we must make sure h/w will not generate any interrupt
* before setting the invalid flag. */
sc->sc_flags |= SC_OP_INVALID;
/* disable HAL and put h/w to sleep */
ath9k_hw_disable(sc->sc_ah);
ath9k_hw_configpcipowersave(sc->sc_ah, 1);
return 0;
}
/* Interrupt handler. Most of the actual processing is deferred.
* It's the caller's responsibility to ensure the chip is awake. */
......@@ -1071,11 +940,9 @@ int ath_init(u16 devid, struct ath_softc *sc)
/* XXX: hardware will not be ready until ath_open() being called */
sc->sc_flags |= SC_OP_INVALID;
sc->sc_debug = DBG_DEFAULT;
DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid);
/* Initialize tasklet */
spin_lock_init(&sc->sc_resetlock);
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
(unsigned long)sc);
......@@ -1088,8 +955,6 @@ int ath_init(u16 devid, struct ath_softc *sc)
/* XXX assert csz is non-zero */
sc->sc_cachelsz = csz << 2; /* convert to bytes */
spin_lock_init(&sc->sc_resetlock);
ah = ath9k_hw_attach(devid, sc, sc->mem, &status);
if (ah == NULL) {
DPRINTF(sc, ATH_DBG_FATAL,
......@@ -1100,10 +965,6 @@ int ath_init(u16 devid, struct ath_softc *sc)
}
sc->sc_ah = ah;
/* Initializes the noise floor to a reasonable default value.
* Later on this will be updated during ANI processing. */
sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR;
/* Get the hardware key cache size. */
sc->sc_keymax = ah->ah_caps.keycache_size;
if (sc->sc_keymax > ATH_KEYMAX) {
......@@ -1131,17 +992,14 @@ int ath_init(u16 devid, struct ath_softc *sc)
set_bit(i + 64, sc->sc_keymap);
set_bit(i + 32 + 64, sc->sc_keymap);
}
/*
* Collect the channel list using the default country
* code and including outdoor channels. The 802.11 layer
* is resposible for filtering this list based on settings
* like the phy mode.
*/
/* Collect the channel list using the default country code */
error = ath_setup_channels(sc);
if (error)
goto bad;
/* default to STA mode */
/* default to MONITOR mode */
sc->sc_ah->ah_opmode = ATH9K_M_MONITOR;
/* Setup rate tables */
......@@ -1211,6 +1069,10 @@ int ath_init(u16 devid, struct ath_softc *sc)
goto bad2;
}
/* Initializes the noise floor to a reasonable default value.
* Later on this will be updated during ANI processing. */
sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR;
setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc);
sc->sc_rc = ath_rate_attach(ah);
......@@ -1271,6 +1133,7 @@ int ath_init(u16 devid, struct ath_softc *sc)
ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask);
ath9k_hw_setbssidmask(ah, sc->sc_bssidmask);
}
sc->sc_slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */
/* initialize beacon slots */
......@@ -1285,6 +1148,22 @@ int ath_init(u16 devid, struct ath_softc *sc)
ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127);
#endif
/* setup channels and rates */
sc->sbands[IEEE80211_BAND_2GHZ].channels =
sc->channels[IEEE80211_BAND_2GHZ];
sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
sc->rates[IEEE80211_BAND_2GHZ];
sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
sc->sbands[IEEE80211_BAND_5GHZ].channels =
sc->channels[IEEE80211_BAND_5GHZ];
sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
sc->rates[IEEE80211_BAND_5GHZ];
sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
}
return 0;
bad2:
/* cleanup tx queues */
......@@ -1294,125 +1173,39 @@ int ath_init(u16 devid, struct ath_softc *sc)
bad:
if (ah)
ath9k_hw_detach(ah);
return error;
}
void ath_deinit(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
int i;
DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__);
tasklet_kill(&sc->intr_tq);
tasklet_kill(&sc->bcon_tasklet);
ath_stop(sc);
if (!(sc->sc_flags & SC_OP_INVALID))
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
ath_rate_detach(sc->sc_rc);
/* cleanup tx queues */
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
if (ATH_TXQ_SETUP(sc, i))
ath_tx_cleanupq(sc, &sc->sc_txq[i]);
ath9k_hw_detach(ah);
return error;
}
/*******************/
/* Node Management */
/*******************/
struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id)
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
struct ath_vap *avp;
struct ath_node *an;
avp = sc->sc_vaps[if_id];
ASSERT(avp != NULL);
an = (struct ath_node *)sta->drv_priv;
/* mac80211 sta_notify callback is from an IRQ context, so no sleep */
an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC);
if (an == NULL)
return NULL;
memset(an, 0, sizeof(*an));
if (sc->sc_flags & SC_OP_TXAGGR)
ath_tx_node_init(sc, an);
an->an_sc = sc;
memcpy(an->an_addr, addr, ETH_ALEN);
atomic_set(&an->an_refcnt, 1);
/* set up per-node tx/rx state */
ath_tx_node_init(sc, an);
ath_rx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
ath_chainmask_sel_init(sc, an);
ath_chainmask_sel_timerstart(&an->an_chainmask_sel);
list_add(&an->list, &sc->node_list);
return an;
}
void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag)
void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
unsigned long flags;
struct ath_node *an = (struct ath_node *)sta->drv_priv;
ath_chainmask_sel_timerstop(&an->an_chainmask_sel);
an->an_flags |= ATH_NODE_CLEAN;
ath_tx_node_cleanup(sc, an, bh_flag);
ath_rx_node_cleanup(sc, an);
ath_tx_node_free(sc, an);
ath_rx_node_free(sc, an);
spin_lock_irqsave(&sc->node_lock, flags);
list_del(&an->list);
spin_unlock_irqrestore(&sc->node_lock, flags);
kfree(an);
}
/* Finds a node and increases the refcnt if found */
struct ath_node *ath_node_get(struct ath_softc *sc, u8 *addr)
{
struct ath_node *an = NULL, *an_found = NULL;
if (list_empty(&sc->node_list)) /* FIXME */
goto out;
list_for_each_entry(an, &sc->node_list, list) {
if (!compare_ether_addr(an->an_addr, addr)) {
atomic_inc(&an->an_refcnt);
an_found = an;
break;
}
}
out:
return an_found;
}
/* Decrements the refcnt and if it drops to zero, detach the node */
void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag)
{
if (atomic_dec_and_test(&an->an_refcnt))
ath_node_detach(sc, an, bh_flag);
}
/* Finds a node, doesn't increment refcnt. Caller must hold sc->node_lock */
struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr)
{
struct ath_node *an = NULL, *an_found = NULL;
if (list_empty(&sc->node_list))
return NULL;
list_for_each_entry(an, &sc->node_list, list)
if (!compare_ether_addr(an->an_addr, addr)) {
an_found = an;
break;
}
return an_found;
if (sc->sc_flags & SC_OP_TXAGGR)
ath_tx_node_cleanup(sc, an);
}
/*
......@@ -1433,11 +1226,8 @@ void ath_newassoc(struct ath_softc *sc,
for (tidno = 0; tidno < WME_NUM_TID; tidno++) {
if (sc->sc_flags & SC_OP_TXAGGR)
ath_tx_aggr_teardown(sc, an, tidno);
if (sc->sc_flags & SC_OP_RXAGGR)
ath_rx_aggr_teardown(sc, an, tidno);
}
}
an->an_flags = 0;
}
/**************/
......@@ -1488,27 +1278,6 @@ void ath_update_txpow(struct ath_softc *sc)
}
}
/* Return the current country and domain information */
void ath_get_currentCountry(struct ath_softc *sc,
struct ath9k_country_entry *ctry)
{
ath9k_regd_get_current_country(sc->sc_ah, ctry);
/* If HAL not specific yet, since it is band dependent,
* use the one we passed in. */
if (ctry->countryCode == CTRY_DEFAULT) {
ctry->iso[0] = 0;
ctry->iso[1] = 0;
} else if (ctry->iso[0] && ctry->iso[1]) {
if (!ctry->iso[2]) {
if (ath_outdoor)
ctry->iso[2] = 'O';
else
ctry->iso[2] = 'I';
}
}
}
/**************************/
/* Slow Antenna Diversity */
/**************************/
......
......@@ -84,9 +84,6 @@ struct ath_node;
#define TSF_TO_TU(_h,_l) \
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
#define ATH9K_BH_STATUS_INTACT 0
#define ATH9K_BH_STATUS_CHANGE 1
#define ATH_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<<i))
static inline unsigned long get_timestamp(void)
......@@ -209,6 +206,7 @@ struct ath_buf_state {
struct ath_rc_series bfs_rcs[4]; /* rate series */
u32 bf_type; /* BUF_* (enum buffer_type) */
/* key type use to encrypt this frame */
u32 bfs_keyix;
enum ath9k_key_type bfs_keytype;
};
......@@ -219,6 +217,7 @@ struct ath_buf_state {
#define bf_seqno bf_state.bfs_seqno
#define bf_tidno bf_state.bfs_tidno
#define bf_rcs bf_state.bfs_rcs
#define bf_keyix bf_state.bfs_keyix
#define bf_keytype bf_state.bfs_keytype
#define bf_isdata(bf) (bf->bf_state.bf_type & BUF_DATA)
#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
......@@ -244,7 +243,6 @@ struct ath_buf {
struct ath_buf *bf_next; /* next subframe in the aggregate */
struct ath_buf *bf_rifslast; /* last buf for RIFS burst */
void *bf_mpdu; /* enclosing frame structure */
void *bf_node; /* pointer to the node */
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 */
......@@ -306,15 +304,7 @@ void ath_descdma_cleanup(struct ath_softc *sc,
#define ATH_MAX_ANTENNA 3
#define ATH_RXBUF 512
#define ATH_RX_TIMEOUT 40 /* 40 milliseconds */
#define WME_NUM_TID 16
#define IEEE80211_BAR_CTL_TID_M 0xF000 /* tid mask */
#define IEEE80211_BAR_CTL_TID_S 12 /* tid shift */
enum ATH_RX_TYPE {
ATH_RX_NON_CONSUMED = 0,
ATH_RX_CONSUMED
};
/* per frame rx status block */
struct ath_recv_status {
......@@ -348,48 +338,18 @@ struct ath_rxbuf {
struct ath_recv_status rx_status; /* cached rx status */
};
/* Per-TID aggregate receiver state for a node */
struct ath_arx_tid {
struct ath_node *an;
struct ath_rxbuf *rxbuf; /* re-ordering buffer */
struct timer_list timer;
spinlock_t tidlock;
int baw_head; /* seq_next at head */
int baw_tail; /* tail of block-ack window */
int seq_reset; /* need to reset start sequence */
int addba_exchangecomplete;
u16 seq_next; /* next expected sequence */
u16 baw_size; /* block-ack window size */
};
/* Per-node receiver aggregate state */
struct ath_arx {
struct ath_arx_tid tid[WME_NUM_TID];
};
int ath_startrecv(struct ath_softc *sc);
bool ath_stoprecv(struct ath_softc *sc);
void ath_flushrecv(struct ath_softc *sc);
u32 ath_calcrxfilter(struct ath_softc *sc);
void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an);
void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an);
void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
void ath_handle_rx_intr(struct ath_softc *sc);
int ath_rx_init(struct ath_softc *sc, int nbufs);
void ath_rx_cleanup(struct ath_softc *sc);
int ath_rx_tasklet(struct ath_softc *sc, int flush);
int ath_rx_input(struct ath_softc *sc,
struct ath_node *node,
struct sk_buff *skb,
struct ath_recv_status *rx_status,
enum ATH_RX_TYPE *status);
int _ath_rx_indicate(struct ath_softc *sc,
struct sk_buff *skb,
struct ath_recv_status *status,
u16 keyix);
int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb,
struct ath_recv_status *status);
/******/
/* TX */
/******/
......@@ -418,12 +378,6 @@ int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb,
#define WME_AC_VO 3 /* voice */
#define WME_NUM_AC 4
enum ATH_SM_PWRSAV{
ATH_SM_ENABLE,
ATH_SM_PWRSAV_STATIC,
ATH_SM_PWRSAV_DYNAMIC,
};
/*
* Data transmit queue state. One of these exists for each
* hardware transmit queue. Packets sent to us from above
......@@ -456,6 +410,10 @@ struct ath_txq {
struct list_head axq_acq;
};
#define AGGR_CLEANUP BIT(1)
#define AGGR_ADDBA_COMPLETE BIT(2)
#define AGGR_ADDBA_PROGRESS BIT(3)
/* per TID aggregate tx state for a destination */
struct ath_atx_tid {
struct list_head list; /* round-robin tid entry */
......@@ -471,9 +429,7 @@ struct ath_atx_tid {
int baw_tail; /* next unused tx buffer slot */
int sched;
int paused;
int cleanup_inprogress;
u32 addba_exchangecomplete:1;
int32_t addba_exchangeinprogress;
u8 state;
int addba_exchangeattempts;
};
......@@ -494,24 +450,8 @@ struct ath_atx {
/* per-frame tx control block */
struct ath_tx_control {
struct ath_node *an;
struct ath_txq *txq;
int if_id;
int qnum;
u32 ht:1;
u32 ps:1;
u32 use_minrate:1;
enum ath9k_pkt_type atype;
enum ath9k_key_type keytype;
u32 flags;
u16 seqno;
u16 tidno;
u16 txpower;
u16 frmlen;
u32 keyix;
int min_rate;
int mcast_rate;
struct ath_softc *dev;
dma_addr_t dmacontext;
};
/* per frame tx status block */
......@@ -546,33 +486,29 @@ void ath_draintxq(struct ath_softc *sc, bool retry_tx);
void ath_tx_draintxq(struct ath_softc *sc,
struct ath_txq *txq, bool retry_tx);
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
void ath_tx_node_cleanup(struct ath_softc *sc,
struct ath_node *an, bool bh_flag);
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an);
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_init(struct ath_softc *sc, int nbufs);
int ath_tx_cleanup(struct ath_softc *sc);
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);
int ath_txq_update(struct ath_softc *sc, int qnum,
struct ath9k_tx_queue_info *q);
int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb);
int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
struct ath_tx_control *txctl);
void ath_tx_tasklet(struct ath_softc *sc);
u32 ath_txq_depth(struct ath_softc *sc, int qnum);
u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum);
void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth);
void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
struct ath_xmit_status *tx_status, struct ath_node *an);
struct ath_xmit_status *tx_status);
void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
/**********************/
/* Node / Aggregation */
/**********************/
/* indicates the node is clened up */
#define ATH_NODE_CLEAN 0x1
/* indicates the node is 80211 power save */
#define ATH_NODE_PWRSAVE 0x2
#define ADDBA_EXCHANGE_ATTEMPTS 10
#define ATH_AGGR_DELIM_SZ 4 /* delimiter size */
#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
......@@ -584,6 +520,7 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
#define IEEE80211_SEQ_SEQ_SHIFT 4
#define IEEE80211_SEQ_MAX 4096
#define IEEE80211_MIN_AMPDU_BUF 0x8
#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
/* return whether a bit at index _n in bitmap _bm is set
* _sz is the size of the bitmap */
......@@ -614,14 +551,6 @@ enum ATH_AGGR_STATUS {
ATH_AGGR_8K_LIMITED,
};
enum ATH_AGGR_CHECK {
AGGR_NOT_REQUIRED,
AGGR_REQUIRED,
AGGR_CLEANUP_PROGRESS,
AGGR_EXCHANGE_PROGRESS,
AGGR_EXCHANGE_DONE
};
struct aggr_rifs_param {
int param_max_frames;
int param_max_len;
......@@ -633,54 +562,30 @@ struct aggr_rifs_param {
/* Per-node aggregation state */
struct ath_node_aggr {
struct ath_atx tx; /* node transmit state */
struct ath_arx rx; /* node receive state */
};
/* driver-specific node state */
struct ath_node {
struct list_head list;
struct ath_softc *an_sc;
atomic_t an_refcnt;
struct ath_chainmask_sel an_chainmask_sel;
struct ath_node_aggr an_aggr;
u8 an_smmode; /* SM Power save mode */
u8 an_flags;
u8 an_addr[ETH_ALEN];
u16 maxampdu;
u8 mpdudensity;
};
void ath_tx_resume_tid(struct ath_softc *sc,
struct ath_atx_tid *tid);
enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc,
struct ath_node *an, u8 tidno);
bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
void ath_tx_aggr_teardown(struct ath_softc *sc,
struct ath_node *an, u8 tidno);
void ath_rx_aggr_teardown(struct ath_softc *sc,
struct ath_node *an, u8 tidno);
int ath_rx_aggr_start(struct ath_softc *sc,
const u8 *addr,
u16 tid,
u16 *ssn);
int ath_rx_aggr_stop(struct ath_softc *sc,
const u8 *addr,
u16 tid);
int ath_tx_aggr_start(struct ath_softc *sc,
const u8 *addr,
u16 tid,
u16 *ssn);
int ath_tx_aggr_stop(struct ath_softc *sc,
const u8 *addr,
u16 tid);
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn);
int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_newassoc(struct ath_softc *sc,
struct ath_node *node, int isnew, int isuapsd);
struct ath_node *ath_node_attach(struct ath_softc *sc,
u8 addr[ETH_ALEN], int if_id);
void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag);
struct ath_node *ath_node_get(struct ath_softc *sc, u8 addr[ETH_ALEN]);
void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag);
struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr);
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta);
void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta);
/*******************/
/* Beacon Handling */
......@@ -744,23 +649,14 @@ struct ath_vap_config {
/* driver-specific vap state */
struct ath_vap {
struct ieee80211_vif *av_if_data;
int av_bslot; /* beacon slot index */
enum ath9k_opmode av_opmode; /* VAP operational mode */
struct ath_buf *av_bcbuf; /* beacon buffer */
struct ath_tx_control av_btxctl; /* txctl information for beacon */
int av_bslot; /* beacon slot index */
struct ath_vap_config av_config;/* vap configuration parameters*/
struct ath_rate_node *rc_node;
};
int ath_vap_attach(struct ath_softc *sc,
int if_id,
struct ieee80211_vif *if_data,
enum ath9k_opmode opmode);
int ath_vap_detach(struct ath_softc *sc, int if_id);
int ath_vap_config(struct ath_softc *sc,
int if_id, struct ath_vap_config *if_config);
/*********************/
/* Antenna diversity */
/*********************/
......@@ -968,14 +864,13 @@ struct ath_softc {
u8 sc_nbcnvaps; /* # of vaps sending beacons */
u16 sc_nvaps; /* # of active virtual ap's */
struct ath_vap *sc_vaps[ATH_BCBUF];
struct ieee80211_vif *sc_vaps[ATH_BCBUF];
u8 sc_mcastantenna;
u8 sc_defant; /* current default antenna */
u8 sc_rxotherant; /* rx's on non-default antenna */
struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
struct list_head node_list;
struct ath_ht_info sc_ht_info;
enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
......@@ -1036,7 +931,6 @@ struct ath_softc {
spinlock_t sc_rxbuflock;
spinlock_t sc_txbuflock;
spinlock_t sc_resetlock;
spinlock_t node_lock;
/* LEDs */
struct ath_led radio_led;
......@@ -1052,9 +946,8 @@ struct ath_softc {
};
int ath_init(u16 devid, struct ath_softc *sc);
void ath_deinit(struct ath_softc *sc);
int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan);
int ath_suspend(struct ath_softc *sc);
void ath_stop(struct ath_softc *sc);
irqreturn_t ath_isr(int irq, void *dev);
int ath_reset(struct ath_softc *sc, bool retry_tx);
int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan);
......@@ -1073,8 +966,6 @@ int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
void ath_setslottime(struct ath_softc *sc);
void ath_update_txpow(struct ath_softc *sc);
int ath_cabq_update(struct ath_softc *);
void ath_get_currentCountry(struct ath_softc *sc,
struct ath9k_country_entry *ctry);
u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp);
#endif /* CORE_H */
此差异已折叠。
此差异已折叠。
......@@ -923,7 +923,7 @@ struct ath_hal_5416 {
#define OFDM_PLCP_BITS_QUARTER 22
#define OFDM_SYMBOL_TIME_QUARTER 16
u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp,
u32 ath9k_hw_get_eeprom(struct ath_hal *ah,
enum eeprom_param param);
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -718,7 +718,6 @@ struct b43_wldev {
bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
bool short_slot; /* TRUE, if short slot timing is enabled. */
bool radio_hw_enable; /* saved state of radio hardware enabled state */
bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册