提交 495a1b4e 编写于 作者: D David S. Miller

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6

Conflicts:
	net/mac80211/pm.c
...@@ -12,38 +12,22 @@ following format: ...@@ -12,38 +12,22 @@ following format:
The radiotap format is discussed in The radiotap format is discussed in
./Documentation/networking/radiotap-headers.txt. ./Documentation/networking/radiotap-headers.txt.
Despite 13 radiotap argument types are currently defined, most only make sense Despite many radiotap parameters being currently defined, most only make sense
to appear on received packets. The following information is parsed from the to appear on received packets. The following information is parsed from the
radiotap headers and used to control injection: radiotap headers and used to control injection:
* IEEE80211_RADIOTAP_RATE
rate in 500kbps units, automatic if invalid or not present
* IEEE80211_RADIOTAP_ANTENNA
antenna to use, automatic if not present
* IEEE80211_RADIOTAP_DBM_TX_POWER
transmit power in dBm, automatic if not present
* IEEE80211_RADIOTAP_FLAGS * IEEE80211_RADIOTAP_FLAGS
IEEE80211_RADIOTAP_F_FCS: FCS will be removed and recalculated IEEE80211_RADIOTAP_F_FCS: FCS will be removed and recalculated
IEEE80211_RADIOTAP_F_WEP: frame will be encrypted if key available IEEE80211_RADIOTAP_F_WEP: frame will be encrypted if key available
IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the
current fragmentation threshold. Note that current fragmentation threshold.
this flag is only reliable when software
fragmentation is enabled)
The injection code can also skip all other currently defined radiotap fields The injection code can also skip all other currently defined radiotap fields
facilitating replay of captured radiotap headers directly. facilitating replay of captured radiotap headers directly.
Here is an example valid radiotap header defining these three parameters Here is an example valid radiotap header defining some parameters
0x00, 0x00, // <-- radiotap version 0x00, 0x00, // <-- radiotap version
0x0b, 0x00, // <- radiotap header length 0x0b, 0x00, // <- radiotap header length
...@@ -72,8 +56,8 @@ interface), along the following lines: ...@@ -72,8 +56,8 @@ interface), along the following lines:
... ...
r = pcap_inject(ppcap, u8aSendBuffer, nLength); r = pcap_inject(ppcap, u8aSendBuffer, nLength);
You can also find sources for a complete inject test applet here: You can also find a link to a complete inject application here:
http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer http://wireless.kernel.org/en/users/Documentation/packetspammer
Andy Green <andy@warmcat.com> Andy Green <andy@warmcat.com>
...@@ -521,16 +521,12 @@ status of the system. ...@@ -521,16 +521,12 @@ status of the system.
Input devices may issue events that are related to rfkill. These are the Input devices may issue events that are related to rfkill. These are the
various KEY_* events and SW_* events supported by rfkill-input.c. various KEY_* events and SW_* events supported by rfkill-input.c.
******IMPORTANT****** Userspace may not change the state of an rfkill switch in response to an
When rfkill-input is ACTIVE, userspace is NOT TO CHANGE THE STATE OF AN RFKILL input event, it should refrain from changing states entirely.
SWITCH IN RESPONSE TO AN INPUT EVENT also handled by rfkill-input, unless it
has set to true the user_claim attribute for that particular switch. This rule Userspace cannot assume it is the only source of control for rfkill switches.
is *absolute*; do NOT violate it. Their state can change due to firmware actions, direct user actions, and the
******IMPORTANT****** rfkill-input EPO override for *_RFKILL_ALL.
Userspace must not assume it is the only source of control for rfkill switches.
Their state CAN and WILL change due to firmware actions, direct user actions,
and the rfkill-input EPO override for *_RFKILL_ALL.
When rfkill-input is not active, userspace must initiate a rfkill status When rfkill-input is not active, userspace must initiate a rfkill status
change by writing to the "state" attribute in order for anything to happen. change by writing to the "state" attribute in order for anything to happen.
......
...@@ -888,6 +888,12 @@ P: Luis R. Rodriguez ...@@ -888,6 +888,12 @@ P: Luis R. Rodriguez
M: lrodriguez@atheros.com M: lrodriguez@atheros.com
P: Jouni Malinen P: Jouni Malinen
M: jmalinen@atheros.com M: jmalinen@atheros.com
P: Sujith Manoharan
M: Sujith.Manoharan@atheros.com
P: Vasanthakumar Thiagarajan
M: vasanth@atheros.com
P: Senthil Balasubramanian
M: senthilkumar@atheros.com
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
L: ath9k-devel@lists.ath9k.org L: ath9k-devel@lists.ath9k.org
S: Supported S: Supported
...@@ -4421,8 +4427,8 @@ S: Maintained ...@@ -4421,8 +4427,8 @@ S: Maintained
F: drivers/ata/sata_promise.* F: drivers/ata/sata_promise.*
PS3 NETWORK SUPPORT PS3 NETWORK SUPPORT
P: Masakazu Mokuno P: Geoff Levand
M: mokuno@sm.sony.co.jp M: geoffrey.levand@am.sony.com
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
L: cbe-oss-dev@ozlabs.org L: cbe-oss-dev@ozlabs.org
S: Supported S: Supported
......
...@@ -38,9 +38,9 @@ static void tosa_bt_off(struct tosa_bt_data *data) ...@@ -38,9 +38,9 @@ static void tosa_bt_off(struct tosa_bt_data *data)
static int tosa_bt_toggle_radio(void *data, enum rfkill_state state) static int tosa_bt_toggle_radio(void *data, enum rfkill_state state)
{ {
pr_info("BT_RADIO going: %s\n", pr_info("BT_RADIO going: %s\n",
state == RFKILL_STATE_ON ? "on" : "off"); state == RFKILL_STATE_UNBLOCKED ? "on" : "off");
if (state == RFKILL_STATE_ON) { if (state == RFKILL_STATE_UNBLOCKED) {
pr_info("TOSA_BT: going ON\n"); pr_info("TOSA_BT: going ON\n");
tosa_bt_on(data); tosa_bt_on(data);
} else { } else {
......
...@@ -2484,7 +2484,7 @@ static int add_net_device(struct hso_device *hso_dev) ...@@ -2484,7 +2484,7 @@ static int add_net_device(struct hso_device *hso_dev)
static int hso_radio_toggle(void *data, enum rfkill_state state) static int hso_radio_toggle(void *data, enum rfkill_state state)
{ {
struct hso_device *hso_dev = data; struct hso_device *hso_dev = data;
int enabled = (state == RFKILL_STATE_ON); int enabled = (state == RFKILL_STATE_UNBLOCKED);
int rv; int rv;
mutex_lock(&hso_dev->mutex); mutex_lock(&hso_dev->mutex);
...@@ -2522,7 +2522,7 @@ static void hso_create_rfkill(struct hso_device *hso_dev, ...@@ -2522,7 +2522,7 @@ static void hso_create_rfkill(struct hso_device *hso_dev,
snprintf(rfkn, 20, "hso-%d", snprintf(rfkn, 20, "hso-%d",
interface->altsetting->desc.bInterfaceNumber); interface->altsetting->desc.bInterfaceNumber);
hso_net->rfkill->name = rfkn; hso_net->rfkill->name = rfkn;
hso_net->rfkill->state = RFKILL_STATE_ON; hso_net->rfkill->state = RFKILL_STATE_UNBLOCKED;
hso_net->rfkill->data = hso_dev; hso_net->rfkill->data = hso_dev;
hso_net->rfkill->toggle_radio = hso_radio_toggle; hso_net->rfkill->toggle_radio = hso_radio_toggle;
if (rfkill_register(hso_net->rfkill) < 0) { if (rfkill_register(hso_net->rfkill) < 0) {
......
...@@ -146,10 +146,10 @@ config LIBERTAS_CS ...@@ -146,10 +146,10 @@ config LIBERTAS_CS
A driver for Marvell Libertas 8385 CompactFlash devices. A driver for Marvell Libertas 8385 CompactFlash devices.
config LIBERTAS_SDIO config LIBERTAS_SDIO
tristate "Marvell Libertas 8385 and 8686 SDIO 802.11b/g cards" tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards"
depends on LIBERTAS && MMC depends on LIBERTAS && MMC
---help--- ---help---
A driver for Marvell Libertas 8385 and 8686 SDIO devices. A driver for Marvell Libertas 8385/8686/8688 SDIO devices.
config LIBERTAS_SPI config LIBERTAS_SPI
tristate "Marvell Libertas 8686 SPI 802.11b/g cards" tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
...@@ -337,6 +337,7 @@ config USB_NET_RNDIS_WLAN ...@@ -337,6 +337,7 @@ config USB_NET_RNDIS_WLAN
select USB_NET_CDCETHER select USB_NET_CDCETHER
select USB_NET_RNDIS_HOST select USB_NET_RNDIS_HOST
select WIRELESS_EXT select WIRELESS_EXT
select CFG80211
---help--- ---help---
This is a driver for wireless RNDIS devices. This is a driver for wireless RNDIS devices.
These are USB based adapters found in devices such as: These are USB based adapters found in devices such as:
...@@ -433,6 +434,13 @@ config RTL8187 ...@@ -433,6 +434,13 @@ config RTL8187
Thanks to Realtek for their support! Thanks to Realtek for their support!
# If possible, automatically enable LEDs for RTL8187.
config RTL8187_LEDS
bool
depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187)
default y
config ADM8211 config ADM8211
tristate "ADMtek ADM8211 support" tristate "ADMtek ADM8211 support"
depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL
...@@ -483,9 +491,7 @@ config MWL8K ...@@ -483,9 +491,7 @@ config MWL8K
will be called mwl8k. If unsure, say N. will be called mwl8k. If unsure, say N.
source "drivers/net/wireless/p54/Kconfig" source "drivers/net/wireless/p54/Kconfig"
source "drivers/net/wireless/ath5k/Kconfig" source "drivers/net/wireless/ath/Kconfig"
source "drivers/net/wireless/ath9k/Kconfig"
source "drivers/net/wireless/ar9170/Kconfig"
source "drivers/net/wireless/ipw2x00/Kconfig" source "drivers/net/wireless/ipw2x00/Kconfig"
source "drivers/net/wireless/iwlwifi/Kconfig" source "drivers/net/wireless/iwlwifi/Kconfig"
source "drivers/net/wireless/hostap/Kconfig" source "drivers/net/wireless/hostap/Kconfig"
......
...@@ -55,8 +55,6 @@ obj-$(CONFIG_RT2X00) += rt2x00/ ...@@ -55,8 +55,6 @@ obj-$(CONFIG_RT2X00) += rt2x00/
obj-$(CONFIG_P54_COMMON) += p54/ obj-$(CONFIG_P54_COMMON) += p54/
obj-$(CONFIG_ATH5K) += ath5k/ obj-$(CONFIG_ATH_COMMON) += ath/
obj-$(CONFIG_ATH9K) += ath9k/
obj-$(CONFIG_AR9170_USB) += ar9170/
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
...@@ -2250,6 +2250,7 @@ static int at76_init_new_device(struct at76_priv *priv, ...@@ -2250,6 +2250,7 @@ static int at76_init_new_device(struct at76_priv *priv,
/* mac80211 initialisation */ /* mac80211 initialisation */
priv->hw->wiphy->max_scan_ssids = 1; priv->hw->wiphy->max_scan_ssids = 1;
priv->hw->wiphy->max_scan_ie_len = 0;
priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &at76_supported_band; priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &at76_supported_band;
priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
......
config ATH_COMMON
tristate "Atheros Wireless Cards"
depends on ATH5K || ATH9K || AR9170_USB
source "drivers/net/wireless/ath/ath5k/Kconfig"
source "drivers/net/wireless/ath/ath9k/Kconfig"
source "drivers/net/wireless/ath/ar9170/Kconfig"
obj-$(CONFIG_ATH5K) += ath5k/
obj-$(CONFIG_ATH9K) += ath9k/
obj-$(CONFIG_AR9170_USB) += ar9170/
obj-$(CONFIG_ATH_COMMON) += ath.o
ath-objs := main.o regd.o
...@@ -2,6 +2,7 @@ config AR9170_USB ...@@ -2,6 +2,7 @@ config AR9170_USB
tristate "Atheros AR9170 802.11n USB support" tristate "Atheros AR9170 802.11n USB support"
depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL
select FW_LOADER select FW_LOADER
select ATH_COMMON
help help
This is a driver for the Atheros "otus" 802.11n USB devices. This is a driver for the Atheros "otus" 802.11n USB devices.
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <net/wireless.h> #include <net/cfg80211.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#ifdef CONFIG_AR9170_LEDS #ifdef CONFIG_AR9170_LEDS
#include <linux/leds.h> #include <linux/leds.h>
...@@ -48,6 +48,8 @@ ...@@ -48,6 +48,8 @@
#include "eeprom.h" #include "eeprom.h"
#include "hw.h" #include "hw.h"
#include "../regd.h"
#define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1) #define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1)
enum ar9170_bw { enum ar9170_bw {
...@@ -58,6 +60,21 @@ enum ar9170_bw { ...@@ -58,6 +60,21 @@ enum ar9170_bw {
__AR9170_NUM_BW, __AR9170_NUM_BW,
}; };
static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type)
{
switch (type) {
case NL80211_CHAN_NO_HT:
case NL80211_CHAN_HT20:
return AR9170_BW_20;
case NL80211_CHAN_HT40MINUS:
return AR9170_BW_40_BELOW;
case NL80211_CHAN_HT40PLUS:
return AR9170_BW_40_ABOVE;
default:
BUG();
}
}
enum ar9170_rf_init_mode { enum ar9170_rf_init_mode {
AR9170_RFI_NONE, AR9170_RFI_NONE,
AR9170_RFI_WARM, AR9170_RFI_WARM,
...@@ -87,10 +104,16 @@ enum ar9170_device_state { ...@@ -87,10 +104,16 @@ enum ar9170_device_state {
AR9170_ASSOCIATED, AR9170_ASSOCIATED,
}; };
struct ar9170_rxstream_mpdu_merge {
struct ar9170_rx_head plcp;
bool has_plcp;
};
struct ar9170 { struct ar9170 {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct mutex mutex; struct mutex mutex;
enum ar9170_device_state state; enum ar9170_device_state state;
unsigned long bad_hw_nagger;
int (*open)(struct ar9170 *); int (*open)(struct ar9170 *);
void (*stop)(struct ar9170 *); void (*stop)(struct ar9170 *);
...@@ -118,6 +141,7 @@ struct ar9170 { ...@@ -118,6 +141,7 @@ struct ar9170 {
u64 cur_mc_hash, want_mc_hash; u64 cur_mc_hash, want_mc_hash;
u32 cur_filter, want_filter; u32 cur_filter, want_filter;
unsigned int filter_changed; unsigned int filter_changed;
unsigned int filter_state;
bool sniffer_enabled; bool sniffer_enabled;
/* PHY */ /* PHY */
...@@ -151,11 +175,17 @@ struct ar9170 { ...@@ -151,11 +175,17 @@ struct ar9170 {
/* EEPROM */ /* EEPROM */
struct ar9170_eeprom eeprom; struct ar9170_eeprom eeprom;
struct ath_regulatory regulatory;
/* global tx status for unregistered Stations. */ /* global tx status for unregistered Stations. */
struct sk_buff_head global_tx_status; struct sk_buff_head global_tx_status;
struct sk_buff_head global_tx_status_waste; struct sk_buff_head global_tx_status_waste;
struct delayed_work tx_status_janitor; struct delayed_work tx_status_janitor;
/* rxstream mpdu merge */
struct ar9170_rxstream_mpdu_merge rx_mpdu;
struct sk_buff *rx_failover;
int rx_failover_missing;
}; };
struct ar9170_sta_info { struct ar9170_sta_info {
......
...@@ -312,7 +312,7 @@ struct ar9170_rx_head { ...@@ -312,7 +312,7 @@ struct ar9170_rx_head {
u8 plcp[12]; u8 plcp[12];
} __packed; } __packed;
struct ar9170_rx_tail { struct ar9170_rx_phystatus {
union { union {
struct { struct {
u8 rssi_ant0, rssi_ant1, rssi_ant2, u8 rssi_ant0, rssi_ant1, rssi_ant2,
...@@ -324,6 +324,9 @@ struct ar9170_rx_tail { ...@@ -324,6 +324,9 @@ struct ar9170_rx_tail {
u8 evm_stream0[6], evm_stream1[6]; u8 evm_stream0[6], evm_stream1[6];
u8 phy_err; u8 phy_err;
} __packed;
struct ar9170_rx_macstatus {
u8 SAidx, DAidx; u8 SAidx, DAidx;
u8 error; u8 error;
u8 status; u8 status;
...@@ -339,7 +342,7 @@ struct ar9170_rx_tail { ...@@ -339,7 +342,7 @@ struct ar9170_rx_tail {
#define AR9170_RX_ENC_SOFTWARE 0x8 #define AR9170_RX_ENC_SOFTWARE 0x8
static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t)
{ {
return (t->SAidx & 0xc0) >> 4 | return (t->SAidx & 0xc0) >> 4 |
(t->DAidx & 0xc0) >> 6; (t->DAidx & 0xc0) >> 6;
...@@ -357,10 +360,9 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) ...@@ -357,10 +360,9 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t)
#define AR9170_RX_STATUS_MPDU_MASK 0x30 #define AR9170_RX_STATUS_MPDU_MASK 0x30
#define AR9170_RX_STATUS_MPDU_SINGLE 0x00 #define AR9170_RX_STATUS_MPDU_SINGLE 0x00
#define AR9170_RX_STATUS_MPDU_FIRST 0x10 #define AR9170_RX_STATUS_MPDU_FIRST 0x20
#define AR9170_RX_STATUS_MPDU_MIDDLE 0x20 #define AR9170_RX_STATUS_MPDU_MIDDLE 0x30
#define AR9170_RX_STATUS_MPDU_LAST 0x30 #define AR9170_RX_STATUS_MPDU_LAST 0x10
#define AR9170_RX_ERROR_RXTO 0x01 #define AR9170_RX_ERROR_RXTO 0x01
#define AR9170_RX_ERROR_OVERRUN 0x02 #define AR9170_RX_ERROR_OVERRUN 0x02
...@@ -369,6 +371,7 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) ...@@ -369,6 +371,7 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t)
#define AR9170_RX_ERROR_WRONG_RA 0x10 #define AR9170_RX_ERROR_WRONG_RA 0x10
#define AR9170_RX_ERROR_PLCP 0x20 #define AR9170_RX_ERROR_PLCP 0x20
#define AR9170_RX_ERROR_MMIC 0x40 #define AR9170_RX_ERROR_MMIC 0x40
#define AR9170_RX_ERROR_FATAL 0x80
struct ar9170_cmd_tx_status { struct ar9170_cmd_tx_status {
__le16 unkn; __le16 unkn;
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <net/wireless.h> #include <net/cfg80211.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include "eeprom.h" #include "eeprom.h"
......
config ATH5K config ATH5K
tristate "Atheros 5xxx wireless cards support" tristate "Atheros 5xxx wireless cards support"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
select ATH_COMMON
select MAC80211_LEDS select MAC80211_LEDS
select LEDS_CLASS select LEDS_CLASS
select NEW_LEDS select NEW_LEDS
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include <linux/types.h> #include <linux/types.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#include "../regd.h"
/* RX/TX descriptor hw structs /* RX/TX descriptor hw structs
* TODO: Driver part should only see sw structs */ * TODO: Driver part should only see sw structs */
#include "desc.h" #include "desc.h"
...@@ -1039,8 +1041,6 @@ struct ath5k_hw { ...@@ -1039,8 +1041,6 @@ struct ath5k_hw {
bool ah_5ghz; bool ah_5ghz;
bool ah_2ghz; bool ah_2ghz;
#define ah_regdomain ah_capabilities.cap_regdomain.reg_current
#define ah_regdomain_hw ah_capabilities.cap_regdomain.reg_hw
#define ah_modes ah_capabilities.cap_mode #define ah_modes ah_capabilities.cap_mode
#define ah_ee_version ah_capabilities.cap_eeprom.ee_version #define ah_ee_version ah_capabilities.cap_eeprom.ee_version
...@@ -1065,6 +1065,7 @@ struct ath5k_hw { ...@@ -1065,6 +1065,7 @@ struct ath5k_hw {
u32 ah_gpio[AR5K_MAX_GPIO]; u32 ah_gpio[AR5K_MAX_GPIO];
int ah_gpio_npins; int ah_gpio_npins;
struct ath_regulatory ah_regulatory;
struct ath5k_capabilities ah_capabilities; struct ath5k_capabilities ah_capabilities;
struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES];
......
...@@ -61,9 +61,13 @@ ...@@ -61,9 +61,13 @@
static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
static int modparam_nohwcrypt; static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
static int modparam_all_channels;
module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO);
MODULE_PARM_DESC(all_channels, "Expose all channels the device can use.");
/******************\ /******************\
* Internal defines * * Internal defines *
...@@ -705,6 +709,15 @@ ath5k_pci_resume(struct pci_dev *pdev) ...@@ -705,6 +709,15 @@ ath5k_pci_resume(struct pci_dev *pdev)
* Driver Initialization * * Driver Initialization *
\***********************/ \***********************/
static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct ath5k_softc *sc = hw->priv;
struct ath_regulatory *reg = &sc->ah->ah_regulatory;
return ath_reg_notifier_apply(wiphy, request, reg);
}
static int static int
ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
{ {
...@@ -793,12 +806,23 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) ...@@ -793,12 +806,23 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
memset(sc->bssidmask, 0xff, ETH_ALEN); memset(sc->bssidmask, 0xff, ETH_ALEN);
ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
ah->ah_regulatory.current_rd =
ah->ah_capabilities.cap_eeprom.ee_regdomain;
ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier);
if (ret) {
ATH5K_ERR(sc, "can't initialize regulatory system\n");
goto err_queues;
}
ret = ieee80211_register_hw(hw); ret = ieee80211_register_hw(hw);
if (ret) { if (ret) {
ATH5K_ERR(sc, "can't register ieee80211 hw\n"); ATH5K_ERR(sc, "can't register ieee80211 hw\n");
goto err_queues; goto err_queues;
} }
if (!ath_is_world_regd(&sc->ah->ah_regulatory))
regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2);
ath5k_init_leds(sc); ath5k_init_leds(sc);
return 0; return 0;
...@@ -862,6 +886,20 @@ ath5k_ieee2mhz(short chan) ...@@ -862,6 +886,20 @@ ath5k_ieee2mhz(short chan)
return 2212 + chan * 20; return 2212 + chan * 20;
} }
/*
* Returns true for the channel numbers used without all_channels modparam.
*/
static bool ath5k_is_standard_channel(short chan)
{
return ((chan <= 14) ||
/* UNII 1,2 */
((chan & 3) == 0 && chan >= 36 && chan <= 64) ||
/* midband */
((chan & 3) == 0 && chan >= 100 && chan <= 140) ||
/* UNII-3 */
((chan & 3) == 1 && chan >= 149 && chan <= 165));
}
static unsigned int static unsigned int
ath5k_copy_channels(struct ath5k_hw *ah, ath5k_copy_channels(struct ath5k_hw *ah,
struct ieee80211_channel *channels, struct ieee80211_channel *channels,
...@@ -899,6 +937,9 @@ ath5k_copy_channels(struct ath5k_hw *ah, ...@@ -899,6 +937,9 @@ ath5k_copy_channels(struct ath5k_hw *ah,
if (!ath5k_channel_ok(ah, freq, chfreq)) if (!ath5k_channel_ok(ah, freq, chfreq))
continue; continue;
if (!modparam_all_channels && !ath5k_is_standard_channel(ch))
continue;
/* Write channel info and increment counter */ /* Write channel info and increment counter */
channels[count].center_freq = freq; channels[count].center_freq = freq;
channels[count].band = (chfreq == CHANNEL_2GHZ) ? channels[count].band = (chfreq == CHANNEL_2GHZ) ?
...@@ -1577,9 +1618,8 @@ ath5k_rx_start(struct ath5k_softc *sc) ...@@ -1577,9 +1618,8 @@ ath5k_rx_start(struct ath5k_softc *sc)
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
sc->cachelsz, sc->rxbufsize); sc->cachelsz, sc->rxbufsize);
sc->rxlink = NULL;
spin_lock_bh(&sc->rxbuflock); spin_lock_bh(&sc->rxbuflock);
sc->rxlink = NULL;
list_for_each_entry(bf, &sc->rxbuf, list) { list_for_each_entry(bf, &sc->rxbuf, list) {
ret = ath5k_rxbuf_setup(sc, bf); ret = ath5k_rxbuf_setup(sc, bf);
if (ret != 0) { if (ret != 0) {
...@@ -1588,9 +1628,9 @@ ath5k_rx_start(struct ath5k_softc *sc) ...@@ -1588,9 +1628,9 @@ ath5k_rx_start(struct ath5k_softc *sc)
} }
} }
bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
ath5k_hw_set_rxdp(ah, bf->daddr);
spin_unlock_bh(&sc->rxbuflock); spin_unlock_bh(&sc->rxbuflock);
ath5k_hw_set_rxdp(ah, bf->daddr);
ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */
ath5k_mode_setup(sc); /* set filters, etc. */ ath5k_mode_setup(sc); /* set filters, etc. */
ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
...@@ -1739,7 +1779,7 @@ ath5k_tasklet_rx(unsigned long data) ...@@ -1739,7 +1779,7 @@ ath5k_tasklet_rx(unsigned long data)
struct sk_buff *skb, *next_skb; struct sk_buff *skb, *next_skb;
dma_addr_t next_skb_addr; dma_addr_t next_skb_addr;
struct ath5k_softc *sc = (void *)data; struct ath5k_softc *sc = (void *)data;
struct ath5k_buf *bf, *bf_last; struct ath5k_buf *bf;
struct ath5k_desc *ds; struct ath5k_desc *ds;
int ret; int ret;
int hdrlen; int hdrlen;
...@@ -1750,7 +1790,6 @@ ath5k_tasklet_rx(unsigned long data) ...@@ -1750,7 +1790,6 @@ ath5k_tasklet_rx(unsigned long data)
ATH5K_WARN(sc, "empty rx buf pool\n"); ATH5K_WARN(sc, "empty rx buf pool\n");
goto unlock; goto unlock;
} }
bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list);
do { do {
rxs.flag = 0; rxs.flag = 0;
...@@ -1759,24 +1798,9 @@ ath5k_tasklet_rx(unsigned long data) ...@@ -1759,24 +1798,9 @@ ath5k_tasklet_rx(unsigned long data)
skb = bf->skb; skb = bf->skb;
ds = bf->desc; ds = bf->desc;
/* /* bail if HW is still using self-linked descriptor */
* last buffer must not be freed to ensure proper hardware if (ath5k_hw_get_rxdp(sc->ah) == bf->daddr)
* function. When the hardware finishes also a packet next to break;
* it, we are sure, it doesn't use it anymore and we can go on.
*/
if (bf_last == bf)
bf->flags |= 1;
if (bf->flags) {
struct ath5k_buf *bf_next = list_entry(bf->list.next,
struct ath5k_buf, list);
ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc,
&rs);
if (ret)
break;
bf->flags &= ~1;
/* skip the overwritten one (even status is martian) */
goto next;
}
ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
if (unlikely(ret == -EINPROGRESS)) if (unlikely(ret == -EINPROGRESS))
...@@ -2455,7 +2479,7 @@ ath5k_intr(int irq, void *dev_id) ...@@ -2455,7 +2479,7 @@ ath5k_intr(int irq, void *dev_id)
tasklet_schedule(&sc->restq); tasklet_schedule(&sc->restq);
} else { } else {
if (status & AR5K_INT_SWBA) { if (status & AR5K_INT_SWBA) {
tasklet_schedule(&sc->beacontq); tasklet_hi_schedule(&sc->beacontq);
} }
if (status & AR5K_INT_RXEOL) { if (status & AR5K_INT_RXEOL) {
/* /*
......
...@@ -56,7 +56,6 @@ ...@@ -56,7 +56,6 @@
struct ath5k_buf { struct ath5k_buf {
struct list_head list; struct list_head list;
unsigned int flags; /* rx descriptor flags */
struct ath5k_desc *desc; /* virtual addr of desc */ struct ath5k_desc *desc; /* virtual addr of desc */
dma_addr_t daddr; /* physical addr of desc */ dma_addr_t daddr; /* physical addr of desc */
struct sk_buff *skb; /* skbuff for buf */ struct sk_buff *skb; /* skbuff for buf */
......
...@@ -80,8 +80,6 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) ...@@ -80,8 +80,6 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
* ath5k_hw_get_rxdp - Get RX Descriptor's address * ath5k_hw_get_rxdp - Get RX Descriptor's address
* *
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
*
* XXX: Is RXDP read and clear ?
*/ */
u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
{ {
......
...@@ -537,8 +537,6 @@ static const struct ath5k_ini ar5212_ini_common_start[] = { ...@@ -537,8 +537,6 @@ static const struct ath5k_ini ar5212_ini_common_start[] = {
{ AR5K_DCU_TX_FILTER_1(15), 0x00000000 }, { AR5K_DCU_TX_FILTER_1(15), 0x00000000 },
{ AR5K_DCU_TX_FILTER_CLR, 0x00000000 }, { AR5K_DCU_TX_FILTER_CLR, 0x00000000 },
{ AR5K_DCU_TX_FILTER_SET, 0x00000000 }, { AR5K_DCU_TX_FILTER_SET, 0x00000000 },
{ AR5K_DCU_TX_FILTER_CLR, 0x00000000 },
{ AR5K_DCU_TX_FILTER_SET, 0x00000000 },
{ AR5K_STA_ID1, 0x00000000 }, { AR5K_STA_ID1, 0x00000000 },
{ AR5K_BSS_ID0, 0x00000000 }, { AR5K_BSS_ID0, 0x00000000 },
{ AR5K_BSS_ID1, 0x00000000 }, { AR5K_BSS_ID1, 0x00000000 },
...@@ -669,7 +667,7 @@ static const struct ath5k_ini ar5212_ini_common_start[] = { ...@@ -669,7 +667,7 @@ static const struct ath5k_ini ar5212_ini_common_start[] = {
/*{ AR5K_PHY(650), 0x000001b5 },*/ /*{ AR5K_PHY(650), 0x000001b5 },*/
{ AR5K_PHY(651), 0x00000000 }, { AR5K_PHY(651), 0x00000000 },
{ AR5K_PHY_TXPOWER_RATE3, 0x20202020 }, { AR5K_PHY_TXPOWER_RATE3, 0x20202020 },
{ AR5K_PHY_TXPOWER_RATE2, 0x20202020 }, { AR5K_PHY_TXPOWER_RATE4, 0x20202020 },
/*{ AR5K_PHY(655), 0x13c889af },*/ /*{ AR5K_PHY(655), 0x13c889af },*/
{ AR5K_PHY(656), 0x38490a20 }, { AR5K_PHY(656), 0x38490a20 },
{ AR5K_PHY(657), 0x00007bb6 }, { AR5K_PHY(657), 0x00007bb6 },
...@@ -718,7 +716,7 @@ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { ...@@ -718,7 +716,7 @@ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
{ AR5K_PHY_SETTLING, { AR5K_PHY_SETTLING,
{ 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } }, { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
{ AR5K_PHY_AGCCTL, { AR5K_PHY_AGCCTL,
{ 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } }, { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } },
{ AR5K_PHY_NF, { AR5K_PHY_NF,
{ 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
{ AR5K_PHY_WEAK_OFDM_HIGH_THR, { AR5K_PHY_WEAK_OFDM_HIGH_THR,
...@@ -799,7 +797,7 @@ static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { ...@@ -799,7 +797,7 @@ static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
{ AR5K_PHY_DESIRED_SIZE, { AR5K_PHY_DESIRED_SIZE,
{ 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
{ AR5K_PHY_SIG, { AR5K_PHY_SIG,
{ 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } }, { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } },
{ AR5K_PHY_AGCCOARSE, { AR5K_PHY_AGCCOARSE,
{ 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } }, { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
{ AR5K_PHY_WEAK_OFDM_LOW_THR, { AR5K_PHY_WEAK_OFDM_LOW_THR,
......
...@@ -67,6 +67,8 @@ static const struct pci_device_id ath5k_led_devices[] = { ...@@ -67,6 +67,8 @@ static const struct pci_device_id ath5k_led_devices[] = {
{ ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) },
/* Acer Extensa 5620z (nekoreeve@gmail.com) */ /* Acer Extensa 5620z (nekoreeve@gmail.com) */
{ ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) }, { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) },
/* Fukato Datacask Jupiter 1014a (mrb74@gmx.at) */
{ ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) },
{ } { }
}; };
...@@ -78,7 +80,7 @@ void ath5k_led_enable(struct ath5k_softc *sc) ...@@ -78,7 +80,7 @@ void ath5k_led_enable(struct ath5k_softc *sc)
} }
} }
void ath5k_led_on(struct ath5k_softc *sc) static void ath5k_led_on(struct ath5k_softc *sc)
{ {
if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
return; return;
......
...@@ -1487,28 +1487,35 @@ ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, ...@@ -1487,28 +1487,35 @@ ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
{ {
s8 tmp; s8 tmp;
s16 min_pwrL, min_pwrR; s16 min_pwrL, min_pwrR;
s16 pwr_i = pwrL[0]; s16 pwr_i;
do { if (pwrL[0] == pwrL[1])
pwr_i--; min_pwrL = pwrL[0];
tmp = (s8) ath5k_get_interpolated_value(pwr_i, else {
pwrL[0], pwrL[1], pwr_i = pwrL[0];
stepL[0], stepL[1]); do {
pwr_i--;
} while (tmp > 1); tmp = (s8) ath5k_get_interpolated_value(pwr_i,
pwrL[0], pwrL[1],
min_pwrL = pwr_i; stepL[0], stepL[1]);
} while (tmp > 1);
pwr_i = pwrR[0];
do { min_pwrL = pwr_i;
pwr_i--; }
tmp = (s8) ath5k_get_interpolated_value(pwr_i,
pwrR[0], pwrR[1],
stepR[0], stepR[1]);
} while (tmp > 1);
min_pwrR = pwr_i; if (pwrR[0] == pwrR[1])
min_pwrR = pwrR[0];
else {
pwr_i = pwrR[0];
do {
pwr_i--;
tmp = (s8) ath5k_get_interpolated_value(pwr_i,
pwrR[0], pwrR[1],
stepR[0], stepR[1]);
} while (tmp > 1);
min_pwrR = pwr_i;
}
/* Keep the right boundary so that it works for both curves */ /* Keep the right boundary so that it works for both curves */
return max(min_pwrL, min_pwrR); return max(min_pwrL, min_pwrR);
......
...@@ -358,7 +358,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) ...@@ -358,7 +358,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
mode |= AR5K_PHY_MODE_FREQ_5GHZ; mode |= AR5K_PHY_MODE_FREQ_5GHZ;
if (ah->ah_radio == AR5K_RF5413) if (ah->ah_radio == AR5K_RF5413)
clock |= AR5K_PHY_PLL_40MHZ_5413; clock = AR5K_PHY_PLL_40MHZ_5413;
else else
clock |= AR5K_PHY_PLL_40MHZ; clock |= AR5K_PHY_PLL_40MHZ;
......
...@@ -2,6 +2,7 @@ config ATH9K ...@@ -2,6 +2,7 @@ config ATH9K
tristate "Atheros 802.11n wireless cards support" tristate "Atheros 802.11n wireless cards support"
depends on PCI && MAC80211 && WLAN_80211 depends on PCI && MAC80211 && WLAN_80211
depends on RFKILL || RFKILL=n depends on RFKILL || RFKILL=n
select ATH_COMMON
select MAC80211_LEDS select MAC80211_LEDS
select LEDS_CLASS select LEDS_CLASS
select NEW_LEDS select NEW_LEDS
......
...@@ -4,7 +4,6 @@ ath9k-y += hw.o \ ...@@ -4,7 +4,6 @@ ath9k-y += hw.o \
calib.o \ calib.o \
ani.o \ ani.o \
phy.o \ phy.o \
regd.o \
beacon.o \ beacon.o \
main.o \ main.o \
recv.o \ recv.o \
......
...@@ -569,8 +569,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, ...@@ -569,8 +569,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
DPRINTF(ah->ah_sc, ATH_DBG_ANI, DPRINTF(ah->ah_sc, ATH_DBG_ANI,
"phyCnt1 0x%x, resetting " "phyCnt1 0x%x, resetting "
"counter value to 0x%x\n", "counter value to 0x%x\n",
phyCnt1, phyCnt1, aniState->ofdmPhyErrBase);
aniState->ofdmPhyErrBase);
REG_WRITE(ah, AR_PHY_ERR_1, REG_WRITE(ah, AR_PHY_ERR_1,
aniState->ofdmPhyErrBase); aniState->ofdmPhyErrBase);
REG_WRITE(ah, AR_PHY_ERR_MASK_1, REG_WRITE(ah, AR_PHY_ERR_MASK_1,
...@@ -580,8 +579,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, ...@@ -580,8 +579,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
DPRINTF(ah->ah_sc, ATH_DBG_ANI, DPRINTF(ah->ah_sc, ATH_DBG_ANI,
"phyCnt2 0x%x, resetting " "phyCnt2 0x%x, resetting "
"counter value to 0x%x\n", "counter value to 0x%x\n",
phyCnt2, phyCnt2, aniState->cckPhyErrBase);
aniState->cckPhyErrBase);
REG_WRITE(ah, AR_PHY_ERR_2, REG_WRITE(ah, AR_PHY_ERR_2,
aniState->cckPhyErrBase); aniState->cckPhyErrBase);
REG_WRITE(ah, AR_PHY_ERR_MASK_2, REG_WRITE(ah, AR_PHY_ERR_MASK_2,
...@@ -667,7 +665,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, ...@@ -667,7 +665,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
u32 cc = REG_READ(ah, AR_CCCNT); u32 cc = REG_READ(ah, AR_CCCNT);
if (cycles == 0 || cycles > cc) { if (cycles == 0 || cycles > cc) {
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, DPRINTF(ah->ah_sc, ATH_DBG_ANI,
"cycle counter wrap. ExtBusy = 0\n"); "cycle counter wrap. ExtBusy = 0\n");
good = 0; good = 0;
} else { } else {
......
...@@ -66,7 +66,6 @@ struct ath_config { ...@@ -66,7 +66,6 @@ struct ath_config {
u32 ath_aggr_prot; u32 ath_aggr_prot;
u16 txpowlimit; u16 txpowlimit;
u8 cabqReadytime; u8 cabqReadytime;
u8 swBeaconProcess;
}; };
/*************************/ /*************************/
...@@ -74,13 +73,17 @@ struct ath_config { ...@@ -74,13 +73,17 @@ struct ath_config {
/*************************/ /*************************/
#define ATH_TXBUF_RESET(_bf) do { \ #define ATH_TXBUF_RESET(_bf) do { \
(_bf)->bf_status = 0; \ (_bf)->bf_stale = false; \
(_bf)->bf_lastbf = NULL; \ (_bf)->bf_lastbf = NULL; \
(_bf)->bf_next = NULL; \ (_bf)->bf_next = NULL; \
memset(&((_bf)->bf_state), 0, \ memset(&((_bf)->bf_state), 0, \
sizeof(struct ath_buf_state)); \ sizeof(struct ath_buf_state)); \
} while (0) } while (0)
#define ATH_RXBUF_RESET(_bf) do { \
(_bf)->bf_stale = false; \
} while (0)
/** /**
* enum buffer_type - Buffer type flags * enum buffer_type - Buffer type flags
* *
...@@ -106,7 +109,7 @@ struct ath_buf_state { ...@@ -106,7 +109,7 @@ struct ath_buf_state {
int bfs_seqno; int bfs_seqno;
int bfs_tidno; int bfs_tidno;
int bfs_retries; int bfs_retries;
u32 bf_type; u8 bf_type;
u32 bfs_keyix; u32 bfs_keyix;
enum ath9k_key_type bfs_keytype; enum ath9k_key_type bfs_keytype;
}; };
...@@ -130,26 +133,21 @@ struct ath_buf { ...@@ -130,26 +133,21 @@ struct ath_buf {
struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or
an aggregate) */ an aggregate) */
struct ath_buf *bf_next; /* next subframe in the aggregate */ struct ath_buf *bf_next; /* next subframe in the aggregate */
void *bf_mpdu; /* enclosing frame structure */ struct sk_buff *bf_mpdu; /* enclosing frame structure */
struct ath_desc *bf_desc; /* virtual addr of desc */ struct ath_desc *bf_desc; /* virtual addr of desc */
dma_addr_t bf_daddr; /* physical addr of desc */ dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer */ dma_addr_t bf_buf_addr; /* physical addr of data buffer */
u32 bf_status; bool bf_stale;
u16 bf_flags; u16 bf_flags;
struct ath_buf_state bf_state; struct ath_buf_state bf_state;
dma_addr_t bf_dmacontext; dma_addr_t bf_dmacontext;
}; };
#define ATH_RXBUF_RESET(_bf) ((_bf)->bf_status = 0)
#define ATH_BUFSTATUS_STALE 0x00000002
struct ath_descdma { struct ath_descdma {
const char *dd_name;
struct ath_desc *dd_desc; struct ath_desc *dd_desc;
dma_addr_t dd_desc_paddr; dma_addr_t dd_desc_paddr;
u32 dd_desc_len; u32 dd_desc_len;
struct ath_buf *dd_bufptr; struct ath_buf *dd_bufptr;
dma_addr_t dd_dmacontext;
}; };
int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
...@@ -295,26 +293,6 @@ struct ath_tx_control { ...@@ -295,26 +293,6 @@ struct ath_tx_control {
#define ATH_TX_XRETRY 0x02 #define ATH_TX_XRETRY 0x02
#define ATH_TX_BAR 0x04 #define ATH_TX_BAR 0x04
/* All RSSI values are noise floor adjusted */
struct ath_tx_stat {
int rssi;
int rssictl[ATH_MAX_ANTENNA];
int rssiextn[ATH_MAX_ANTENNA];
int rateieee;
int rateKbps;
int ratecode;
int flags;
u32 airtime; /* time on air per final tx rate */
};
struct aggr_rifs_param {
int param_max_frames;
int param_max_len;
int param_rl;
int param_al;
struct ath_rc_series *param_rcs;
};
struct ath_node { struct ath_node {
struct ath_softc *an_sc; struct ath_softc *an_sc;
struct ath_atx_tid tid[WME_NUM_TID]; struct ath_atx_tid tid[WME_NUM_TID];
...@@ -362,7 +340,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); ...@@ -362,7 +340,7 @@ 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); void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); 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_init(struct ath_softc *sc, int nbufs);
int ath_tx_cleanup(struct ath_softc *sc); void ath_tx_cleanup(struct ath_softc *sc);
struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb); 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, int ath_txq_update(struct ath_softc *sc, int qnum,
struct ath9k_tx_queue_info *q); struct ath9k_tx_queue_info *q);
...@@ -525,19 +503,18 @@ struct ath_rfkill { ...@@ -525,19 +503,18 @@ struct ath_rfkill {
#define SC_OP_BEACONS BIT(1) #define SC_OP_BEACONS BIT(1)
#define SC_OP_RXAGGR BIT(2) #define SC_OP_RXAGGR BIT(2)
#define SC_OP_TXAGGR BIT(3) #define SC_OP_TXAGGR BIT(3)
#define SC_OP_CHAINMASK_UPDATE BIT(4) #define SC_OP_FULL_RESET BIT(4)
#define SC_OP_FULL_RESET BIT(5) #define SC_OP_PREAMBLE_SHORT BIT(5)
#define SC_OP_PREAMBLE_SHORT BIT(6) #define SC_OP_PROTECT_ENABLE BIT(6)
#define SC_OP_PROTECT_ENABLE BIT(7) #define SC_OP_RXFLUSH BIT(7)
#define SC_OP_RXFLUSH BIT(8) #define SC_OP_LED_ASSOCIATED BIT(8)
#define SC_OP_LED_ASSOCIATED BIT(9) #define SC_OP_RFKILL_REGISTERED BIT(9)
#define SC_OP_RFKILL_REGISTERED BIT(10) #define SC_OP_RFKILL_SW_BLOCKED BIT(10)
#define SC_OP_RFKILL_SW_BLOCKED BIT(11) #define SC_OP_RFKILL_HW_BLOCKED BIT(11)
#define SC_OP_RFKILL_HW_BLOCKED BIT(12) #define SC_OP_WAIT_FOR_BEACON BIT(12)
#define SC_OP_WAIT_FOR_BEACON BIT(13) #define SC_OP_LED_ON BIT(13)
#define SC_OP_LED_ON BIT(14) #define SC_OP_SCANNING BIT(14)
#define SC_OP_SCANNING BIT(15) #define SC_OP_TSF_RESET BIT(15)
#define SC_OP_TSF_RESET BIT(16)
struct ath_bus_ops { struct ath_bus_ops {
void (*read_cachesize)(struct ath_softc *sc, int *csz); void (*read_cachesize)(struct ath_softc *sc, int *csz);
......
...@@ -43,7 +43,7 @@ static int ath_beaconq_config(struct ath_softc *sc) ...@@ -43,7 +43,7 @@ static int ath_beaconq_config(struct ath_softc *sc)
if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
DPRINTF(sc, ATH_DBG_FATAL, DPRINTF(sc, ATH_DBG_FATAL,
"unable to update h/w beacon queue parameters\n"); "Unable to update h/w beacon queue parameters\n");
return 0; return 0;
} else { } else {
ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
...@@ -59,7 +59,7 @@ static int ath_beaconq_config(struct ath_softc *sc) ...@@ -59,7 +59,7 @@ static int ath_beaconq_config(struct ath_softc *sc)
static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
struct ath_buf *bf) struct ath_buf *bf)
{ {
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; struct sk_buff *skb = bf->bf_mpdu;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_desc *ds; struct ath_desc *ds;
struct ath9k_11n_rate_series series[4]; struct ath9k_11n_rate_series series[4];
...@@ -132,16 +132,13 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, ...@@ -132,16 +132,13 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
avp = (void *)vif->drv_priv; avp = (void *)vif->drv_priv;
cabq = sc->beacon.cabq; cabq = sc->beacon.cabq;
if (avp->av_bcbuf == NULL) { if (avp->av_bcbuf == NULL)
DPRINTF(sc, ATH_DBG_BEACON, "avp=%p av_bcbuf=%p\n",
avp, avp->av_bcbuf);
return NULL; return NULL;
}
/* Release the old beacon first */ /* Release the old beacon first */
bf = avp->av_bcbuf; bf = avp->av_bcbuf;
skb = (struct sk_buff *)bf->bf_mpdu; skb = bf->bf_mpdu;
if (skb) { if (skb) {
dma_unmap_single(sc->dev, bf->bf_dmacontext, dma_unmap_single(sc->dev, bf->bf_dmacontext,
skb->len, DMA_TO_DEVICE); skb->len, DMA_TO_DEVICE);
...@@ -229,7 +226,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, ...@@ -229,7 +226,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc,
return; return;
bf = avp->av_bcbuf; bf = avp->av_bcbuf;
skb = (struct sk_buff *) bf->bf_mpdu; skb = bf->bf_mpdu;
ath_beacon_setup(sc, avp, bf); ath_beacon_setup(sc, avp, bf);
...@@ -302,7 +299,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) ...@@ -302,7 +299,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
/* release the previous beacon frame, if it already exists. */ /* release the previous beacon frame, if it already exists. */
bf = avp->av_bcbuf; bf = avp->av_bcbuf;
if (bf->bf_mpdu != NULL) { if (bf->bf_mpdu != NULL) {
skb = (struct sk_buff *)bf->bf_mpdu; skb = bf->bf_mpdu;
dma_unmap_single(sc->dev, bf->bf_dmacontext, dma_unmap_single(sc->dev, bf->bf_dmacontext,
skb->len, DMA_TO_DEVICE); skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
...@@ -374,7 +371,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) ...@@ -374,7 +371,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
bf = avp->av_bcbuf; bf = avp->av_bcbuf;
if (bf->bf_mpdu != NULL) { if (bf->bf_mpdu != NULL) {
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; struct sk_buff *skb = bf->bf_mpdu;
dma_unmap_single(sc->dev, bf->bf_dmacontext, dma_unmap_single(sc->dev, bf->bf_dmacontext,
skb->len, DMA_TO_DEVICE); skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
......
...@@ -186,7 +186,7 @@ static bool getNoiseFloorThresh(struct ath_hw *ah, ...@@ -186,7 +186,7 @@ static bool getNoiseFloorThresh(struct ath_hw *ah,
} }
static void ath9k_hw_setup_calibration(struct ath_hw *ah, static void ath9k_hw_setup_calibration(struct ath_hw *ah,
struct hal_cal_list *currCal) struct ath9k_cal_list *currCal)
{ {
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
...@@ -220,7 +220,7 @@ static void ath9k_hw_setup_calibration(struct ath_hw *ah, ...@@ -220,7 +220,7 @@ static void ath9k_hw_setup_calibration(struct ath_hw *ah,
} }
static void ath9k_hw_reset_calibration(struct ath_hw *ah, static void ath9k_hw_reset_calibration(struct ath_hw *ah,
struct hal_cal_list *currCal) struct ath9k_cal_list *currCal)
{ {
int i; int i;
...@@ -238,13 +238,12 @@ static void ath9k_hw_reset_calibration(struct ath_hw *ah, ...@@ -238,13 +238,12 @@ static void ath9k_hw_reset_calibration(struct ath_hw *ah,
ah->cal_samples = 0; ah->cal_samples = 0;
} }
static void ath9k_hw_per_calibration(struct ath_hw *ah, static bool ath9k_hw_per_calibration(struct ath_hw *ah,
struct ath9k_channel *ichan, struct ath9k_channel *ichan,
u8 rxchainmask, u8 rxchainmask,
struct hal_cal_list *currCal, struct ath9k_cal_list *currCal)
bool *isCalDone)
{ {
*isCalDone = false; bool iscaldone = false;
if (currCal->calState == CAL_RUNNING) { if (currCal->calState == CAL_RUNNING) {
if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
...@@ -263,7 +262,7 @@ static void ath9k_hw_per_calibration(struct ath_hw *ah, ...@@ -263,7 +262,7 @@ static void ath9k_hw_per_calibration(struct ath_hw *ah,
currCal->calData->calPostProc(ah, numChains); currCal->calData->calPostProc(ah, numChains);
ichan->CalValid |= currCal->calData->calType; ichan->CalValid |= currCal->calData->calType;
currCal->calState = CAL_DONE; currCal->calState = CAL_DONE;
*isCalDone = true; iscaldone = true;
} else { } else {
ath9k_hw_setup_calibration(ah, currCal); ath9k_hw_setup_calibration(ah, currCal);
} }
...@@ -271,11 +270,13 @@ static void ath9k_hw_per_calibration(struct ath_hw *ah, ...@@ -271,11 +270,13 @@ static void ath9k_hw_per_calibration(struct ath_hw *ah,
} else if (!(ichan->CalValid & currCal->calData->calType)) { } else if (!(ichan->CalValid & currCal->calData->calType)) {
ath9k_hw_reset_calibration(ah, currCal); ath9k_hw_reset_calibration(ah, currCal);
} }
return iscaldone;
} }
/* Assumes you are talking about the currently configured channel */ /* Assumes you are talking about the currently configured channel */
static bool ath9k_hw_iscal_supported(struct ath_hw *ah, static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
enum hal_cal_types calType) enum ath9k_cal_types calType)
{ {
struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
...@@ -284,8 +285,8 @@ static bool ath9k_hw_iscal_supported(struct ath_hw *ah, ...@@ -284,8 +285,8 @@ static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
return true; return true;
case ADC_GAIN_CAL: case ADC_GAIN_CAL:
case ADC_DC_CAL: case ADC_DC_CAL:
if (conf->channel->band == IEEE80211_BAND_5GHZ && if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
conf_is_ht20(conf)) conf_is_ht20(conf)))
return true; return true;
break; break;
} }
...@@ -498,7 +499,7 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) ...@@ -498,7 +499,7 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
{ {
u32 iOddMeasOffset, iEvenMeasOffset, val, i; u32 iOddMeasOffset, iEvenMeasOffset, val, i;
int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
const struct hal_percal_data *calData = const struct ath9k_percal_data *calData =
ah->cal_list_curr->calData; ah->cal_list_curr->calData;
u32 numSamples = u32 numSamples =
(1 << (calData->calCountMax + 5)) * calData->calNumSamples; (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
...@@ -555,7 +556,7 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) ...@@ -555,7 +556,7 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
bool ath9k_hw_reset_calvalid(struct ath_hw *ah) bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
{ {
struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
struct hal_cal_list *currCal = ah->cal_list_curr; struct ath9k_cal_list *currCal = ah->cal_list_curr;
if (!ah->curchan) if (!ah->curchan)
return true; return true;
...@@ -841,23 +842,21 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) ...@@ -841,23 +842,21 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
} }
bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
u8 rxchainmask, bool longcal, u8 rxchainmask, bool longcal)
bool *isCalDone)
{ {
struct hal_cal_list *currCal = ah->cal_list_curr; bool iscaldone = true;
struct ath9k_cal_list *currCal = ah->cal_list_curr;
*isCalDone = true;
if (currCal && if (currCal &&
(currCal->calState == CAL_RUNNING || (currCal->calState == CAL_RUNNING ||
currCal->calState == CAL_WAITING)) { currCal->calState == CAL_WAITING)) {
ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal, iscaldone = ath9k_hw_per_calibration(ah, chan,
isCalDone); rxchainmask, currCal);
if (*isCalDone) { if (iscaldone) {
ah->cal_list_curr = currCal = currCal->calNext; ah->cal_list_curr = currCal = currCal->calNext;
if (currCal->calState == CAL_WAITING) { if (currCal->calState == CAL_WAITING) {
*isCalDone = false; iscaldone = false;
ath9k_hw_reset_calibration(ah, currCal); ath9k_hw_reset_calibration(ah, currCal);
} }
} }
...@@ -872,18 +871,15 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -872,18 +871,15 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_getnf(ah, chan); ath9k_hw_getnf(ah, chan);
ath9k_hw_loadnf(ah, ah->curchan); ath9k_hw_loadnf(ah, ah->curchan);
ath9k_hw_start_nfcal(ah); ath9k_hw_start_nfcal(ah);
if (chan->channelFlags & CHANNEL_CW_INT)
chan->channelFlags &= ~CHANNEL_CW_INT;
} }
return true; return iscaldone;
} }
static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
{ {
REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
if (chan->channelFlags & CHANNEL_HT20) { if (IS_CHAN_HT20(chan)) {
REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
...@@ -919,83 +915,66 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) ...@@ -919,83 +915,66 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
return true; return true;
} }
bool ath9k_hw_init_cal(struct ath_hw *ah, bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
struct ath9k_channel *chan)
{ {
if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
if (!ar9285_clc(ah, chan)) if (!ar9285_clc(ah, chan))
return false; return false;
} else if (AR_SREV_9280_10_OR_LATER(ah)) { } else {
REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); if (AR_SREV_9280_10_OR_LATER(ah)) {
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
}
/* Kick off the cal */ /* Calibrate the AGC */
REG_WRITE(ah, AR_PHY_AGC_CONTROL, REG_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) | REG_READ(ah, AR_PHY_AGC_CONTROL) |
AR_PHY_AGC_CONTROL_CAL); AR_PHY_AGC_CONTROL_CAL);
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, /* Poll for offset calibration complete */
AR_PHY_AGC_CONTROL_CAL, 0, if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
AH_WAIT_TIMEOUT)) { 0, AH_WAIT_TIMEOUT)) {
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
"offset calibration failed to complete in 1ms; " "offset calibration failed to complete in 1ms; "
"noisy environment?\n"); "noisy environment?\n");
return false; return false;
} }
REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); if (AR_SREV_9280_10_OR_LATER(ah)) {
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
} }
/* Calibrate the AGC */
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) |
AR_PHY_AGC_CONTROL_CAL);
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
0, AH_WAIT_TIMEOUT)) {
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
"offset calibration failed to complete in 1ms; "
"noisy environment?\n");
return false;
}
if (AR_SREV_9280_10_OR_LATER(ah)) {
REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
} }
/* Do PA Calibration */ /* Do PA Calibration */
if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
ath9k_hw_9285_pa_cal(ah); ath9k_hw_9285_pa_cal(ah);
/* Do NF Calibration */ /* Do NF Calibration after DC offset and other calibrations */
REG_WRITE(ah, AR_PHY_AGC_CONTROL, REG_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) | REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
AR_PHY_AGC_CONTROL_NF);
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
/* Enable IQ, ADC Gain and ADC DC offset CALs */
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
INIT_CAL(&ah->adcgain_caldata); INIT_CAL(&ah->adcgain_caldata);
INSERT_CAL(ah, &ah->adcgain_caldata); INSERT_CAL(ah, &ah->adcgain_caldata);
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
"enabling ADC Gain Calibration.\n"); "enabling ADC Gain Calibration.\n");
} }
if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
INIT_CAL(&ah->adcdc_caldata); INIT_CAL(&ah->adcdc_caldata);
INSERT_CAL(ah, &ah->adcdc_caldata); INSERT_CAL(ah, &ah->adcdc_caldata);
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
"enabling ADC DC Calibration.\n"); "enabling ADC DC Calibration.\n");
} }
if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
INIT_CAL(&ah->iq_caldata); INIT_CAL(&ah->iq_caldata);
INSERT_CAL(ah, &ah->iq_caldata); INSERT_CAL(ah, &ah->iq_caldata);
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
"enabling IQ Calibration.\n"); "enabling IQ Calibration.\n");
} }
ah->cal_list_curr = ah->cal_list; ah->cal_list_curr = ah->cal_list;
...@@ -1009,49 +988,49 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, ...@@ -1009,49 +988,49 @@ bool ath9k_hw_init_cal(struct ath_hw *ah,
return true; return true;
} }
const struct hal_percal_data iq_cal_multi_sample = { const struct ath9k_percal_data iq_cal_multi_sample = {
IQ_MISMATCH_CAL, IQ_MISMATCH_CAL,
MAX_CAL_SAMPLES, MAX_CAL_SAMPLES,
PER_MIN_LOG_COUNT, PER_MIN_LOG_COUNT,
ath9k_hw_iqcal_collect, ath9k_hw_iqcal_collect,
ath9k_hw_iqcalibrate ath9k_hw_iqcalibrate
}; };
const struct hal_percal_data iq_cal_single_sample = { const struct ath9k_percal_data iq_cal_single_sample = {
IQ_MISMATCH_CAL, IQ_MISMATCH_CAL,
MIN_CAL_SAMPLES, MIN_CAL_SAMPLES,
PER_MAX_LOG_COUNT, PER_MAX_LOG_COUNT,
ath9k_hw_iqcal_collect, ath9k_hw_iqcal_collect,
ath9k_hw_iqcalibrate ath9k_hw_iqcalibrate
}; };
const struct hal_percal_data adc_gain_cal_multi_sample = { const struct ath9k_percal_data adc_gain_cal_multi_sample = {
ADC_GAIN_CAL, ADC_GAIN_CAL,
MAX_CAL_SAMPLES, MAX_CAL_SAMPLES,
PER_MIN_LOG_COUNT, PER_MIN_LOG_COUNT,
ath9k_hw_adc_gaincal_collect, ath9k_hw_adc_gaincal_collect,
ath9k_hw_adc_gaincal_calibrate ath9k_hw_adc_gaincal_calibrate
}; };
const struct hal_percal_data adc_gain_cal_single_sample = { const struct ath9k_percal_data adc_gain_cal_single_sample = {
ADC_GAIN_CAL, ADC_GAIN_CAL,
MIN_CAL_SAMPLES, MIN_CAL_SAMPLES,
PER_MAX_LOG_COUNT, PER_MAX_LOG_COUNT,
ath9k_hw_adc_gaincal_collect, ath9k_hw_adc_gaincal_collect,
ath9k_hw_adc_gaincal_calibrate ath9k_hw_adc_gaincal_calibrate
}; };
const struct hal_percal_data adc_dc_cal_multi_sample = { const struct ath9k_percal_data adc_dc_cal_multi_sample = {
ADC_DC_CAL, ADC_DC_CAL,
MAX_CAL_SAMPLES, MAX_CAL_SAMPLES,
PER_MIN_LOG_COUNT, PER_MIN_LOG_COUNT,
ath9k_hw_adc_dccal_collect, ath9k_hw_adc_dccal_collect,
ath9k_hw_adc_dccal_calibrate ath9k_hw_adc_dccal_calibrate
}; };
const struct hal_percal_data adc_dc_cal_single_sample = { const struct ath9k_percal_data adc_dc_cal_single_sample = {
ADC_DC_CAL, ADC_DC_CAL,
MIN_CAL_SAMPLES, MIN_CAL_SAMPLES,
PER_MAX_LOG_COUNT, PER_MAX_LOG_COUNT,
ath9k_hw_adc_dccal_collect, ath9k_hw_adc_dccal_collect,
ath9k_hw_adc_dccal_calibrate ath9k_hw_adc_dccal_calibrate
}; };
const struct hal_percal_data adc_init_dc_cal = { const struct ath9k_percal_data adc_init_dc_cal = {
ADC_DC_INIT_CAL, ADC_DC_INIT_CAL,
MIN_CAL_SAMPLES, MIN_CAL_SAMPLES,
INIT_LOG_COUNT, INIT_LOG_COUNT,
......
...@@ -17,13 +17,13 @@ ...@@ -17,13 +17,13 @@
#ifndef CALIB_H #ifndef CALIB_H
#define CALIB_H #define CALIB_H
extern const struct hal_percal_data iq_cal_multi_sample; extern const struct ath9k_percal_data iq_cal_multi_sample;
extern const struct hal_percal_data iq_cal_single_sample; extern const struct ath9k_percal_data iq_cal_single_sample;
extern const struct hal_percal_data adc_gain_cal_multi_sample; extern const struct ath9k_percal_data adc_gain_cal_multi_sample;
extern const struct hal_percal_data adc_gain_cal_single_sample; extern const struct ath9k_percal_data adc_gain_cal_single_sample;
extern const struct hal_percal_data adc_dc_cal_multi_sample; extern const struct ath9k_percal_data adc_dc_cal_multi_sample;
extern const struct hal_percal_data adc_dc_cal_single_sample; extern const struct ath9k_percal_data adc_dc_cal_single_sample;
extern const struct hal_percal_data adc_init_dc_cal; extern const struct ath9k_percal_data adc_init_dc_cal;
#define AR_PHY_CCA_MAX_GOOD_VALUE -85 #define AR_PHY_CCA_MAX_GOOD_VALUE -85
#define AR_PHY_CCA_MAX_HIGH_VALUE -62 #define AR_PHY_CCA_MAX_HIGH_VALUE -62
...@@ -67,14 +67,14 @@ struct ar5416IniArray { ...@@ -67,14 +67,14 @@ struct ar5416IniArray {
} \ } \
} while (0) } while (0)
enum hal_cal_types { enum ath9k_cal_types {
ADC_DC_INIT_CAL = 0x1, ADC_DC_INIT_CAL = 0x1,
ADC_GAIN_CAL = 0x2, ADC_GAIN_CAL = 0x2,
ADC_DC_CAL = 0x4, ADC_DC_CAL = 0x4,
IQ_MISMATCH_CAL = 0x8 IQ_MISMATCH_CAL = 0x8
}; };
enum hal_cal_state { enum ath9k_cal_state {
CAL_INACTIVE, CAL_INACTIVE,
CAL_WAITING, CAL_WAITING,
CAL_RUNNING, CAL_RUNNING,
...@@ -87,18 +87,18 @@ enum hal_cal_state { ...@@ -87,18 +87,18 @@ enum hal_cal_state {
#define PER_MIN_LOG_COUNT 2 #define PER_MIN_LOG_COUNT 2
#define PER_MAX_LOG_COUNT 10 #define PER_MAX_LOG_COUNT 10
struct hal_percal_data { struct ath9k_percal_data {
enum hal_cal_types calType; enum ath9k_cal_types calType;
u32 calNumSamples; u32 calNumSamples;
u32 calCountMax; u32 calCountMax;
void (*calCollect) (struct ath_hw *); void (*calCollect) (struct ath_hw *);
void (*calPostProc) (struct ath_hw *, u8); void (*calPostProc) (struct ath_hw *, u8);
}; };
struct hal_cal_list { struct ath9k_cal_list {
const struct hal_percal_data *calData; const struct ath9k_percal_data *calData;
enum hal_cal_state calState; enum ath9k_cal_state calState;
struct hal_cal_list *calNext; struct ath9k_cal_list *calNext;
}; };
struct ath9k_nfcal_hist { struct ath9k_nfcal_hist {
...@@ -116,8 +116,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, ...@@ -116,8 +116,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah);
s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
u8 rxchainmask, bool longcal, u8 rxchainmask, bool longcal);
bool *isCalDone);
bool ath9k_hw_init_cal(struct ath_hw *ah, bool ath9k_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan); struct ath9k_channel *chan);
......
...@@ -498,6 +498,9 @@ int ath9k_init_debug(struct ath_softc *sc) ...@@ -498,6 +498,9 @@ int ath9k_init_debug(struct ath_softc *sc)
{ {
sc->debug.debug_mask = ath9k_debug; sc->debug.debug_mask = ath9k_debug;
if (!ath9k_debugfs_root)
return -ENOENT;
sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
ath9k_debugfs_root); ath9k_debugfs_root);
if (!sc->debug.debugfs_phy) if (!sc->debug.debugfs_phy)
......
...@@ -19,20 +19,16 @@ ...@@ -19,20 +19,16 @@
enum ATH_DEBUG { enum ATH_DEBUG {
ATH_DBG_RESET = 0x00000001, ATH_DBG_RESET = 0x00000001,
ATH_DBG_REG_IO = 0x00000002, ATH_DBG_QUEUE = 0x00000002,
ATH_DBG_QUEUE = 0x00000004, ATH_DBG_EEPROM = 0x00000004,
ATH_DBG_EEPROM = 0x00000008, ATH_DBG_CALIBRATE = 0x00000008,
ATH_DBG_CALIBRATE = 0x00000010, ATH_DBG_INTERRUPT = 0x00000010,
ATH_DBG_CHANNEL = 0x00000020, ATH_DBG_REGULATORY = 0x00000020,
ATH_DBG_INTERRUPT = 0x00000040, ATH_DBG_ANI = 0x00000040,
ATH_DBG_REGULATORY = 0x00000080, ATH_DBG_XMIT = 0x00000080,
ATH_DBG_ANI = 0x00000100, ATH_DBG_BEACON = 0x00000100,
ATH_DBG_POWER_MGMT = 0x00000200, ATH_DBG_CONFIG = 0x00000200,
ATH_DBG_XMIT = 0x00000400, ATH_DBG_FATAL = 0x00000400,
ATH_DBG_BEACON = 0x00001000,
ATH_DBG_CONFIG = 0x00002000,
ATH_DBG_KEYCACHE = 0x00004000,
ATH_DBG_FATAL = 0x00008000,
ATH_DBG_ANY = 0xffffffff ATH_DBG_ANY = 0xffffffff
}; };
......
...@@ -783,11 +783,11 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, ...@@ -783,11 +783,11 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
((pdadcValues[4 * j + 3] & 0xFF) << 24); ((pdadcValues[4 * j + 3] & 0xFF) << 24);
REG_WRITE(ah, regOffset, reg32); REG_WRITE(ah, regOffset, reg32);
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"PDADC (%d,%4x): %4.4x %8.8x\n", "PDADC (%d,%4x): %4.4x %8.8x\n",
i, regChainOffset, regOffset, i, regChainOffset, regOffset,
reg32); reg32);
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"PDADC: Chain %d | " "PDADC: Chain %d | "
"PDADC %3d Value %3d | " "PDADC %3d Value %3d | "
"PDADC %3d Value %3d | " "PDADC %3d Value %3d | "
...@@ -910,7 +910,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ...@@ -910,7 +910,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
ah->eep_ops->get_eeprom_rev(ah) <= 2) ah->eep_ops->get_eeprom_rev(ah) <= 2)
twiceMaxEdgePower = AR5416_MAX_RATE_POWER; twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
"EXT_ADDITIVE %d\n", "EXT_ADDITIVE %d\n",
ctlMode, numCtlModes, isHt40CtlMode, ctlMode, numCtlModes, isHt40CtlMode,
...@@ -918,7 +918,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ...@@ -918,7 +918,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
for (i = 0; (i < AR5416_NUM_CTLS) && for (i = 0; (i < AR5416_NUM_CTLS) &&
pEepData->ctlIndex[i]; i++) { pEepData->ctlIndex[i]; i++) {
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
" LOOP-Ctlidx %d: cfgCtl 0x%2.2x " " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
"pCtlMode 0x%2.2x ctlIndex 0x%2.2x " "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
"chan %d\n", "chan %d\n",
...@@ -941,7 +941,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ...@@ -941,7 +941,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
IS_CHAN_2GHZ(chan), IS_CHAN_2GHZ(chan),
AR5416_EEP4K_NUM_BAND_EDGES); AR5416_EEP4K_NUM_BAND_EDGES);
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
" MATCH-EE_IDX %d: ch %d is2 %d " " MATCH-EE_IDX %d: ch %d is2 %d "
"2xMinEdge %d chainmask %d chains %d\n", "2xMinEdge %d chainmask %d chains %d\n",
i, freq, IS_CHAN_2GHZ(chan), i, freq, IS_CHAN_2GHZ(chan),
...@@ -961,7 +961,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ...@@ -961,7 +961,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
" SEL-Min ctlMode %d pCtlMode %d " " SEL-Min ctlMode %d pCtlMode %d "
"2xMaxEdge %d sP %d minCtlPwr %d\n", "2xMaxEdge %d sP %d minCtlPwr %d\n",
ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
...@@ -2234,11 +2234,11 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, ...@@ -2234,11 +2234,11 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
((pdadcValues[4 * j + 3] & 0xFF) << 24); ((pdadcValues[4 * j + 3] & 0xFF) << 24);
REG_WRITE(ah, regOffset, reg32); REG_WRITE(ah, regOffset, reg32);
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"PDADC (%d,%4x): %4.4x %8.8x\n", "PDADC (%d,%4x): %4.4x %8.8x\n",
i, regChainOffset, regOffset, i, regChainOffset, regOffset,
reg32); reg32);
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"PDADC: Chain %d | PDADC %3d " "PDADC: Chain %d | PDADC %3d "
"Value %3d | PDADC %3d Value %3d | " "Value %3d | PDADC %3d Value %3d | "
"PDADC %3d Value %3d | PDADC %3d " "PDADC %3d Value %3d | PDADC %3d "
...@@ -2415,14 +2415,14 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, ...@@ -2415,14 +2415,14 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
ah->eep_ops->get_eeprom_rev(ah) <= 2) ah->eep_ops->get_eeprom_rev(ah) <= 2)
twiceMaxEdgePower = AR5416_MAX_RATE_POWER; twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
"EXT_ADDITIVE %d\n", "EXT_ADDITIVE %d\n",
ctlMode, numCtlModes, isHt40CtlMode, ctlMode, numCtlModes, isHt40CtlMode,
(pCtlMode[ctlMode] & EXT_ADDITIVE)); (pCtlMode[ctlMode] & EXT_ADDITIVE));
for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
" LOOP-Ctlidx %d: cfgCtl 0x%2.2x " " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
"pCtlMode 0x%2.2x ctlIndex 0x%2.2x " "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
"chan %d\n", "chan %d\n",
...@@ -2441,7 +2441,7 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, ...@@ -2441,7 +2441,7 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1], rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
" MATCH-EE_IDX %d: ch %d is2 %d " " MATCH-EE_IDX %d: ch %d is2 %d "
"2xMinEdge %d chainmask %d chains %d\n", "2xMinEdge %d chainmask %d chains %d\n",
i, freq, IS_CHAN_2GHZ(chan), i, freq, IS_CHAN_2GHZ(chan),
...@@ -2460,7 +2460,7 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, ...@@ -2460,7 +2460,7 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
minCtlPower = min(twiceMaxEdgePower, scaledPower); minCtlPower = min(twiceMaxEdgePower, scaledPower);
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
" SEL-Min ctlMode %d pCtlMode %d " " SEL-Min ctlMode %d pCtlMode %d "
"2xMaxEdge %d sP %d minCtlPwr %d\n", "2xMaxEdge %d sP %d minCtlPwr %d\n",
ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#ifndef EEPROM_H #ifndef EEPROM_H
#define EEPROM_H #define EEPROM_H
#include <net/cfg80211.h>
#define AH_USE_EEPROM 0x1 #define AH_USE_EEPROM 0x1
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
......
...@@ -97,7 +97,7 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) ...@@ -97,7 +97,7 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
udelay(AH_TIME_QUANTUM); udelay(AH_TIME_QUANTUM);
} }
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, DPRINTF(ah->ah_sc, ATH_DBG_ANY,
"timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
timeout, reg, REG_READ(ah, reg), mask, val); timeout, reg, REG_READ(ah, reg), mask, val);
...@@ -181,7 +181,7 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah, ...@@ -181,7 +181,7 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah,
} }
break; break;
default: default:
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"Unknown phy %u (rate ix %u)\n", "Unknown phy %u (rate ix %u)\n",
rates->info[rateix].phy, rateix); rates->info[rateix].phy, rateix);
txTime = 0; txTime = 0;
...@@ -306,7 +306,7 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) ...@@ -306,7 +306,7 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah)
REG_WRITE(ah, addr, wrData); REG_WRITE(ah, addr, wrData);
rdData = REG_READ(ah, addr); rdData = REG_READ(ah, addr);
if (rdData != wrData) { if (rdData != wrData) {
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"address test failed " "address test failed "
"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
addr, wrData, rdData); addr, wrData, rdData);
...@@ -318,7 +318,7 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) ...@@ -318,7 +318,7 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah)
REG_WRITE(ah, addr, wrData); REG_WRITE(ah, addr, wrData);
rdData = REG_READ(ah, addr); rdData = REG_READ(ah, addr);
if (wrData != rdData) { if (wrData != rdData) {
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"address test failed " "address test failed "
"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
addr, wrData, rdData); addr, wrData, rdData);
...@@ -363,10 +363,7 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah) ...@@ -363,10 +363,7 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah)
ah->config.ack_6mb = 0x0; ah->config.ack_6mb = 0x0;
ah->config.cwm_ignore_extcca = 0; ah->config.cwm_ignore_extcca = 0;
ah->config.pcie_powersave_enable = 0; ah->config.pcie_powersave_enable = 0;
ah->config.pcie_l1skp_enable = 0;
ah->config.pcie_clock_req = 0; ah->config.pcie_clock_req = 0;
ah->config.pcie_power_reset = 0x100;
ah->config.pcie_restore = 0;
ah->config.pcie_waen = 0; ah->config.pcie_waen = 0;
ah->config.analog_shiftreg = 1; ah->config.analog_shiftreg = 1;
ah->config.ht_enable = 1; ah->config.ht_enable = 1;
...@@ -375,13 +372,6 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah) ...@@ -375,13 +372,6 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah)
ah->config.cck_trig_high = 200; ah->config.cck_trig_high = 200;
ah->config.cck_trig_low = 100; ah->config.cck_trig_low = 100;
ah->config.enable_ani = 1; ah->config.enable_ani = 1;
ah->config.noise_immunity_level = 4;
ah->config.ofdm_weaksignal_det = 1;
ah->config.cck_weaksignal_thr = 0;
ah->config.spur_immunity_level = 2;
ah->config.firstep_level = 0;
ah->config.rssi_thr_high = 40;
ah->config.rssi_thr_low = 7;
ah->config.diversity_control = 0; ah->config.diversity_control = 0;
ah->config.antenna_switch_swap = 0; ah->config.antenna_switch_swap = 0;
...@@ -390,7 +380,7 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah) ...@@ -390,7 +380,7 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah)
ah->config.spurchans[i][1] = AR_NO_SPUR; ah->config.spurchans[i][1] = AR_NO_SPUR;
} }
ah->config.intr_mitigation = 1; ah->config.intr_mitigation = true;
/* /*
* We need this for PCI devices only (Cardbus, PCI, miniPCI) * We need this for PCI devices only (Cardbus, PCI, miniPCI)
...@@ -463,8 +453,8 @@ static int ath9k_hw_rfattach(struct ath_hw *ah) ...@@ -463,8 +453,8 @@ static int ath9k_hw_rfattach(struct ath_hw *ah)
rfStatus = ath9k_hw_init_rf(ah, &ecode); rfStatus = ath9k_hw_init_rf(ah, &ecode);
if (!rfStatus) { if (!rfStatus) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"RF setup failed, status %u\n", ecode); "RF setup failed, status: %u\n", ecode);
return ecode; return ecode;
} }
...@@ -488,10 +478,9 @@ static int ath9k_hw_rf_claim(struct ath_hw *ah) ...@@ -488,10 +478,9 @@ static int ath9k_hw_rf_claim(struct ath_hw *ah)
case AR_RAD2122_SREV_MAJOR: case AR_RAD2122_SREV_MAJOR:
break; break;
default: default:
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"5G Radio Chip Rev 0x%02X is not " "Radio Chip Rev 0x%02X not supported\n",
"supported by this driver\n", val & AR_RADIO_SREV_MAJOR);
ah->hw_version.analog5GhzRev);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -513,12 +502,8 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) ...@@ -513,12 +502,8 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah)
ah->macaddr[2 * i] = eeval >> 8; ah->macaddr[2 * i] = eeval >> 8;
ah->macaddr[2 * i + 1] = eeval & 0xff; ah->macaddr[2 * i + 1] = eeval & 0xff;
} }
if (sum == 0 || sum == 0xffff * 3) { if (sum == 0 || sum == 0xffff * 3)
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"mac address read failed: %pM\n",
ah->macaddr);
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
}
return 0; return 0;
} }
...@@ -575,11 +560,8 @@ static int ath9k_hw_post_attach(struct ath_hw *ah) ...@@ -575,11 +560,8 @@ static int ath9k_hw_post_attach(struct ath_hw *ah)
{ {
int ecode; int ecode;
if (!ath9k_hw_chip_test(ah)) { if (!ath9k_hw_chip_test(ah))
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
"hardware self-test failed\n");
return -ENODEV; return -ENODEV;
}
ecode = ath9k_hw_rf_claim(ah); ecode = ath9k_hw_rf_claim(ah);
if (ecode != 0) if (ecode != 0)
...@@ -617,17 +599,14 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ...@@ -617,17 +599,14 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
ath9k_hw_set_defaults(ah); ath9k_hw_set_defaults(ah);
if (ah->config.intr_mitigation != 0)
ah->intr_mitigation = true;
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
DPRINTF(sc, ATH_DBG_RESET, "Couldn't reset chip\n"); DPRINTF(sc, ATH_DBG_FATAL, "Couldn't reset chip\n");
ecode = -EIO; ecode = -EIO;
goto bad; goto bad;
} }
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
DPRINTF(sc, ATH_DBG_RESET, "Couldn't wakeup chip\n"); DPRINTF(sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n");
ecode = -EIO; ecode = -EIO;
goto bad; goto bad;
} }
...@@ -650,7 +629,7 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ...@@ -650,7 +629,7 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
(ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) && (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) &&
(ah->hw_version.macVersion != AR_SREV_VERSION_9160) && (ah->hw_version.macVersion != AR_SREV_VERSION_9160) &&
(!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) { (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) {
DPRINTF(sc, ATH_DBG_RESET, DPRINTF(sc, ATH_DBG_FATAL,
"Mac Chip Rev 0x%02x.%x is not supported by " "Mac Chip Rev 0x%02x.%x is not supported by "
"this driver\n", ah->hw_version.macVersion, "this driver\n", ah->hw_version.macVersion,
ah->hw_version.macRev); ah->hw_version.macRev);
...@@ -690,10 +669,6 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ...@@ -690,10 +669,6 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
if (AR_SREV_9280_10_OR_LATER(ah)) if (AR_SREV_9280_10_OR_LATER(ah))
ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
DPRINTF(sc, ATH_DBG_RESET,
"This Mac Chip Rev 0x%02x.%x is \n",
ah->hw_version.macVersion, ah->hw_version.macRev);
if (AR_SREV_9285_12_OR_LATER(ah)) { if (AR_SREV_9285_12_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
...@@ -859,11 +834,7 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ...@@ -859,11 +834,7 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
if (AR_SREV_9280_20(ah)) if (AR_SREV_9280_20(ah))
ath9k_hw_init_txgain_ini(ah); ath9k_hw_init_txgain_ini(ah);
if (!ath9k_hw_fill_cap_info(ah)) { ath9k_hw_fill_cap_info(ah);
DPRINTF(sc, ATH_DBG_RESET, "failed ath9k_hw_fill_cap_info\n");
ecode = -EINVAL;
goto bad;
}
if ((ah->hw_version.devid == AR9280_DEVID_PCI) && if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) { test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
...@@ -885,8 +856,8 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ...@@ -885,8 +856,8 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
ecode = ath9k_hw_init_macaddr(ah); ecode = ath9k_hw_init_macaddr(ah);
if (ecode != 0) { if (ecode != 0) {
DPRINTF(sc, ATH_DBG_RESET, DPRINTF(sc, ATH_DBG_FATAL,
"failed initializing mac address\n"); "Failed to initialize MAC address\n");
goto bad; goto bad;
} }
...@@ -1054,7 +1025,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, ...@@ -1054,7 +1025,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
AR_IMR_RXORN | AR_IMR_RXORN |
AR_IMR_BCNMISC; AR_IMR_BCNMISC;
if (ah->intr_mitigation) if (ah->config.intr_mitigation)
ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
else else
ah->mask_reg |= AR_IMR_RXOK; ah->mask_reg |= AR_IMR_RXOK;
...@@ -1203,23 +1174,23 @@ static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, ...@@ -1203,23 +1174,23 @@ static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah,
switch (ah->hw_version.devid) { switch (ah->hw_version.devid) {
case AR9280_DEVID_PCI: case AR9280_DEVID_PCI:
if (reg == 0x7894) { if (reg == 0x7894) {
DPRINTF(ah->ah_sc, ATH_DBG_ANY, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"ini VAL: %x EEPROM: %x\n", value, "ini VAL: %x EEPROM: %x\n", value,
(pBase->version & 0xff)); (pBase->version & 0xff));
if ((pBase->version & 0xff) > 0x0a) { if ((pBase->version & 0xff) > 0x0a) {
DPRINTF(ah->ah_sc, ATH_DBG_ANY, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"PWDCLKIND: %d\n", "PWDCLKIND: %d\n",
pBase->pwdclkind); pBase->pwdclkind);
value &= ~AR_AN_TOP2_PWDCLKIND; value &= ~AR_AN_TOP2_PWDCLKIND;
value |= AR_AN_TOP2_PWDCLKIND & value |= AR_AN_TOP2_PWDCLKIND &
(pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
} else { } else {
DPRINTF(ah->ah_sc, ATH_DBG_ANY, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"PWDCLKIND Earlier Rev\n"); "PWDCLKIND Earlier Rev\n");
} }
DPRINTF(ah->ah_sc, ATH_DBG_ANY, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"final ini VAL: %x\n", value); "final ini VAL: %x\n", value);
} }
break; break;
...@@ -1249,6 +1220,21 @@ static void ath9k_olc_init(struct ath_hw *ah) ...@@ -1249,6 +1220,21 @@ static void ath9k_olc_init(struct ath_hw *ah)
ah->PDADCdelta = 0; ah->PDADCdelta = 0;
} }
static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg,
struct ath9k_channel *chan)
{
u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band);
if (IS_CHAN_B(chan))
ctl |= CTL_11B;
else if (IS_CHAN_G(chan))
ctl |= CTL_11G;
else
ctl |= CTL_11A;
return ctl;
}
static int ath9k_hw_process_ini(struct ath_hw *ah, static int ath9k_hw_process_ini(struct ath_hw *ah,
struct ath9k_channel *chan, struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode) enum ath9k_ht_macmode macmode)
...@@ -1360,19 +1346,19 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, ...@@ -1360,19 +1346,19 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
ath9k_olc_init(ah); ath9k_olc_init(ah);
status = ah->eep_ops->set_txpower(ah, chan, status = ah->eep_ops->set_txpower(ah, chan,
ath9k_regd_get_ctl(ah, chan), ath9k_regd_get_ctl(&ah->regulatory, chan),
channel->max_antenna_gain * 2, channel->max_antenna_gain * 2,
channel->max_power * 2, channel->max_power * 2,
min((u32) MAX_RATE_POWER, min((u32) MAX_RATE_POWER,
(u32) ah->regulatory.power_limit)); (u32) ah->regulatory.power_limit));
if (status != 0) { if (status != 0) {
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"error init'ing transmit power\n"); "Error initializing transmit power\n");
return -EIO; return -EIO;
} }
if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"ar5416SetRfRegs failed\n"); "ar5416SetRfRegs failed\n");
return -EIO; return -EIO;
} }
...@@ -1678,7 +1664,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, ...@@ -1678,7 +1664,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) {
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"Could not kill baseband RX\n"); "Could not kill baseband RX\n");
return false; return false;
} }
...@@ -1687,26 +1673,26 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, ...@@ -1687,26 +1673,26 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
if (AR_SREV_9280_10_OR_LATER(ah)) { if (AR_SREV_9280_10_OR_LATER(ah)) {
if (!(ath9k_hw_ar9280_set_channel(ah, chan))) { if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"failed to set channel\n"); "Failed to set channel\n");
return false; return false;
} }
} else { } else {
if (!(ath9k_hw_set_channel(ah, chan))) { if (!(ath9k_hw_set_channel(ah, chan))) {
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"failed to set channel\n"); "Failed to set channel\n");
return false; return false;
} }
} }
if (ah->eep_ops->set_txpower(ah, chan, if (ah->eep_ops->set_txpower(ah, chan,
ath9k_regd_get_ctl(ah, chan), ath9k_regd_get_ctl(&ah->regulatory, chan),
channel->max_antenna_gain * 2, channel->max_antenna_gain * 2,
channel->max_power * 2, channel->max_power * 2,
min((u32) MAX_RATE_POWER, min((u32) MAX_RATE_POWER,
(u32) ah->regulatory.power_limit)) != 0) { (u32) ah->regulatory.power_limit)) != 0) {
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"error init'ing transmit power\n"); "Error initializing transmit power\n");
return false; return false;
} }
...@@ -2199,14 +2185,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -2199,14 +2185,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ah->txchainmask = sc->tx_chainmask; ah->txchainmask = sc->tx_chainmask;
ah->rxchainmask = sc->rx_chainmask; ah->rxchainmask = sc->rx_chainmask;
if (AR_SREV_9285(ah)) {
ah->txchainmask &= 0x1;
ah->rxchainmask &= 0x1;
} else if (AR_SREV_9280(ah)) {
ah->txchainmask &= 0x3;
ah->rxchainmask &= 0x3;
}
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
return -EIO; return -EIO;
...@@ -2242,7 +2220,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -2242,7 +2220,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_mark_phy_inactive(ah); ath9k_hw_mark_phy_inactive(ah);
if (!ath9k_hw_chip_reset(ah, chan)) { if (!ath9k_hw_chip_reset(ah, chan)) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET, "chip reset failed\n"); DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n");
return -EINVAL; return -EINVAL;
} }
...@@ -2335,8 +2313,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -2335,8 +2313,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_OBS, 8); REG_WRITE(ah, AR_OBS, 8);
if (ah->intr_mitigation) { if (ah->config.intr_mitigation) {
REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
} }
...@@ -2385,8 +2362,8 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) ...@@ -2385,8 +2362,8 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
u32 keyType; u32 keyType;
if (entry >= ah->caps.keycache_size) { if (entry >= ah->caps.keycache_size) {
DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"entry %u out of range\n", entry); "keychache entry %u out of range\n", entry);
return false; return false;
} }
...@@ -2422,8 +2399,8 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) ...@@ -2422,8 +2399,8 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
u32 macHi, macLo; u32 macHi, macLo;
if (entry >= ah->caps.keycache_size) { if (entry >= ah->caps.keycache_size) {
DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"entry %u out of range\n", entry); "keychache entry %u out of range\n", entry);
return false; return false;
} }
...@@ -2454,8 +2431,8 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, ...@@ -2454,8 +2431,8 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
u32 keyType; u32 keyType;
if (entry >= pCap->keycache_size) { if (entry >= pCap->keycache_size) {
DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"entry %u out of range\n", entry); "keycache entry %u out of range\n", entry);
return false; return false;
} }
...@@ -2465,7 +2442,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, ...@@ -2465,7 +2442,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
break; break;
case ATH9K_CIPHER_AES_CCM: case ATH9K_CIPHER_AES_CCM:
if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, DPRINTF(ah->ah_sc, ATH_DBG_ANY,
"AES-CCM not supported by mac rev 0x%x\n", "AES-CCM not supported by mac rev 0x%x\n",
ah->hw_version.macRev); ah->hw_version.macRev);
return false; return false;
...@@ -2476,14 +2453,14 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, ...@@ -2476,14 +2453,14 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
keyType = AR_KEYTABLE_TYPE_TKIP; keyType = AR_KEYTABLE_TYPE_TKIP;
if (ATH9K_IS_MIC_ENABLED(ah) if (ATH9K_IS_MIC_ENABLED(ah)
&& entry + 64 >= pCap->keycache_size) { && entry + 64 >= pCap->keycache_size) {
DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, DPRINTF(ah->ah_sc, ATH_DBG_ANY,
"entry %u inappropriate for TKIP\n", entry); "entry %u inappropriate for TKIP\n", entry);
return false; return false;
} }
break; break;
case ATH9K_CIPHER_WEP: case ATH9K_CIPHER_WEP:
if (k->kv_len < LEN_WEP40) { if (k->kv_len < LEN_WEP40) {
DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, DPRINTF(ah->ah_sc, ATH_DBG_ANY,
"WEP key length %u too small\n", k->kv_len); "WEP key length %u too small\n", k->kv_len);
return false; return false;
} }
...@@ -2498,7 +2475,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, ...@@ -2498,7 +2475,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
keyType = AR_KEYTABLE_TYPE_CLR; keyType = AR_KEYTABLE_TYPE_CLR;
break; break;
default: default:
DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"cipher %u not supported\n", k->kv_type); "cipher %u not supported\n", k->kv_type);
return false; return false;
} }
...@@ -2716,7 +2693,7 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) ...@@ -2716,7 +2693,7 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
AR_RTC_FORCE_WAKE_EN); AR_RTC_FORCE_WAKE_EN);
} }
if (i == 0) { if (i == 0) {
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"Failed to wakeup in %uus\n", POWER_UP_TIME / 20); "Failed to wakeup in %uus\n", POWER_UP_TIME / 20);
return false; return false;
} }
...@@ -2737,9 +2714,8 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) ...@@ -2737,9 +2714,8 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
"UNDEFINED" "UNDEFINED"
}; };
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s -> %s (%s)\n", DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n",
modes[ah->power_mode], modes[mode], modes[ah->power_mode], modes[mode]);
setChip ? "set chip " : "");
switch (mode) { switch (mode) {
case ATH9K_PM_AWAKE: case ATH9K_PM_AWAKE:
...@@ -2753,7 +2729,7 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) ...@@ -2753,7 +2729,7 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
ath9k_set_power_network_sleep(ah, setChip); ath9k_set_power_network_sleep(ah, setChip);
break; break;
default: default:
DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"Unknown power mode %u\n", mode); "Unknown power mode %u\n", mode);
return false; return false;
} }
...@@ -2943,7 +2919,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) ...@@ -2943,7 +2919,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
*masked = isr & ATH9K_INT_COMMON; *masked = isr & ATH9K_INT_COMMON;
if (ah->intr_mitigation) { if (ah->config.intr_mitigation) {
if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
*masked |= ATH9K_INT_RX; *masked |= ATH9K_INT_RX;
} }
...@@ -3000,6 +2976,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) ...@@ -3000,6 +2976,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
DPRINTF(ah->ah_sc, ATH_DBG_ANY, DPRINTF(ah->ah_sc, ATH_DBG_ANY,
"received PCI PERR interrupt\n"); "received PCI PERR interrupt\n");
} }
*masked |= ATH9K_INT_FATAL;
} }
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
...@@ -3061,7 +3038,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) ...@@ -3061,7 +3038,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
} }
if (ints & ATH9K_INT_RX) { if (ints & ATH9K_INT_RX) {
mask |= AR_IMR_RXERR; mask |= AR_IMR_RXERR;
if (ah->intr_mitigation) if (ah->config.intr_mitigation)
mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
else else
mask |= AR_IMR_RXOK | AR_IMR_RXDESC; mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
...@@ -3259,7 +3236,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, ...@@ -3259,7 +3236,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
/* HW Capabilities */ /* HW Capabilities */
/*******************/ /*******************/
bool ath9k_hw_fill_cap_info(struct ath_hw *ah) void ath9k_hw_fill_cap_info(struct ath_hw *ah)
{ {
struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath9k_hw_capabilities *pCap = &ah->caps;
u16 capField = 0, eeval; u16 capField = 0, eeval;
...@@ -3343,8 +3320,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) ...@@ -3343,8 +3320,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP; pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM; pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD;
if (ah->config.ht_enable) if (ah->config.ht_enable)
pCap->hw_caps |= ATH9K_HW_CAP_HT; pCap->hw_caps |= ATH9K_HW_CAP_HT;
else else
...@@ -3368,7 +3343,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) ...@@ -3368,7 +3343,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->keycache_size = AR_KEYTABLE_SIZE; pCap->keycache_size = AR_KEYTABLE_SIZE;
pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
pCap->num_mr_retries = 4;
pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
if (AR_SREV_9285_10_OR_LATER(ah)) if (AR_SREV_9285_10_OR_LATER(ah))
...@@ -3378,14 +3352,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) ...@@ -3378,14 +3352,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
else else
pCap->num_gpio_pins = AR_NUM_GPIO; pCap->num_gpio_pins = AR_NUM_GPIO;
if (AR_SREV_9280_10_OR_LATER(ah)) {
pCap->hw_caps |= ATH9K_HW_CAP_WOW;
pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
} else {
pCap->hw_caps &= ~ATH9K_HW_CAP_WOW;
pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
}
if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) { if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
pCap->hw_caps |= ATH9K_HW_CAP_CST; pCap->hw_caps |= ATH9K_HW_CAP_CST;
pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
...@@ -3411,7 +3377,8 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) ...@@ -3411,7 +3377,8 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
(ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) || (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) ||
(ah->hw_version.macVersion == AR_SREV_VERSION_9160) || (ah->hw_version.macVersion == AR_SREV_VERSION_9160) ||
(ah->hw_version.macVersion == AR_SREV_VERSION_9100) || (ah->hw_version.macVersion == AR_SREV_VERSION_9100) ||
(ah->hw_version.macVersion == AR_SREV_VERSION_9280)) (ah->hw_version.macVersion == AR_SREV_VERSION_9280) ||
(ah->hw_version.macVersion == AR_SREV_VERSION_9285))
pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
else else
pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
...@@ -3445,8 +3412,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) ...@@ -3445,8 +3412,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
ah->btactive_gpio = 6; ah->btactive_gpio = 6;
ah->wlanactive_gpio = 5; ah->wlanactive_gpio = 5;
} }
return true;
} }
bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
...@@ -3762,7 +3727,7 @@ bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) ...@@ -3762,7 +3727,7 @@ bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER); ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER);
if (ah->eep_ops->set_txpower(ah, chan, if (ah->eep_ops->set_txpower(ah, chan,
ath9k_regd_get_ctl(ah, chan), ath9k_regd_get_ctl(&ah->regulatory, chan),
channel->max_antenna_gain * 2, channel->max_antenna_gain * 2,
channel->max_power * 2, channel->max_power * 2,
min((u32) MAX_RATE_POWER, min((u32) MAX_RATE_POWER,
......
...@@ -25,10 +25,11 @@ ...@@ -25,10 +25,11 @@
#include "ani.h" #include "ani.h"
#include "eeprom.h" #include "eeprom.h"
#include "calib.h" #include "calib.h"
#include "regd.h"
#include "reg.h" #include "reg.h"
#include "phy.h" #include "phy.h"
#include "../regd.h"
#define ATHEROS_VENDOR_ID 0x168c #define ATHEROS_VENDOR_ID 0x168c
#define AR5416_DEVID_PCI 0x0023 #define AR5416_DEVID_PCI 0x0023
#define AR5416_DEVID_PCIE 0x0024 #define AR5416_DEVID_PCIE 0x0024
...@@ -124,29 +125,24 @@ enum wireless_mode { ...@@ -124,29 +125,24 @@ enum wireless_mode {
}; };
enum ath9k_hw_caps { enum ath9k_hw_caps {
ATH9K_HW_CAP_CHAN_SPREAD = BIT(0), ATH9K_HW_CAP_MIC_AESCCM = BIT(0),
ATH9K_HW_CAP_MIC_AESCCM = BIT(1), ATH9K_HW_CAP_MIC_CKIP = BIT(1),
ATH9K_HW_CAP_MIC_CKIP = BIT(2), ATH9K_HW_CAP_MIC_TKIP = BIT(2),
ATH9K_HW_CAP_MIC_TKIP = BIT(3), ATH9K_HW_CAP_CIPHER_AESCCM = BIT(3),
ATH9K_HW_CAP_CIPHER_AESCCM = BIT(4), ATH9K_HW_CAP_CIPHER_CKIP = BIT(4),
ATH9K_HW_CAP_CIPHER_CKIP = BIT(5), ATH9K_HW_CAP_CIPHER_TKIP = BIT(5),
ATH9K_HW_CAP_CIPHER_TKIP = BIT(6), ATH9K_HW_CAP_VEOL = BIT(6),
ATH9K_HW_CAP_VEOL = BIT(7), ATH9K_HW_CAP_BSSIDMASK = BIT(7),
ATH9K_HW_CAP_BSSIDMASK = BIT(8), ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(8),
ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(9), ATH9K_HW_CAP_HT = BIT(9),
ATH9K_HW_CAP_CHAN_HALFRATE = BIT(10), ATH9K_HW_CAP_GTT = BIT(10),
ATH9K_HW_CAP_CHAN_QUARTERRATE = BIT(11), ATH9K_HW_CAP_FASTCC = BIT(11),
ATH9K_HW_CAP_HT = BIT(12), ATH9K_HW_CAP_RFSILENT = BIT(12),
ATH9K_HW_CAP_GTT = BIT(13), ATH9K_HW_CAP_CST = BIT(13),
ATH9K_HW_CAP_FASTCC = BIT(14), ATH9K_HW_CAP_ENHANCEDPM = BIT(14),
ATH9K_HW_CAP_RFSILENT = BIT(15), ATH9K_HW_CAP_AUTOSLEEP = BIT(15),
ATH9K_HW_CAP_WOW = BIT(16), ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16),
ATH9K_HW_CAP_CST = BIT(17), ATH9K_HW_CAP_BT_COEX = BIT(17)
ATH9K_HW_CAP_ENHANCEDPM = BIT(18),
ATH9K_HW_CAP_AUTOSLEEP = BIT(19),
ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(20),
ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT = BIT(21),
ATH9K_HW_CAP_BT_COEX = BIT(22)
}; };
enum ath9k_capability_type { enum ath9k_capability_type {
...@@ -166,7 +162,6 @@ struct ath9k_hw_capabilities { ...@@ -166,7 +162,6 @@ struct ath9k_hw_capabilities {
u16 keycache_size; u16 keycache_size;
u16 low_5ghz_chan, high_5ghz_chan; u16 low_5ghz_chan, high_5ghz_chan;
u16 low_2ghz_chan, high_2ghz_chan; u16 low_2ghz_chan, high_2ghz_chan;
u16 num_mr_retries;
u16 rts_aggr_limit; u16 rts_aggr_limit;
u8 tx_chainmask; u8 tx_chainmask;
u8 rx_chainmask; u8 rx_chainmask;
...@@ -184,11 +179,8 @@ struct ath9k_ops_config { ...@@ -184,11 +179,8 @@ struct ath9k_ops_config {
int ack_6mb; int ack_6mb;
int cwm_ignore_extcca; int cwm_ignore_extcca;
u8 pcie_powersave_enable; u8 pcie_powersave_enable;
u8 pcie_l1skp_enable;
u8 pcie_clock_req; u8 pcie_clock_req;
u32 pcie_waen; u32 pcie_waen;
int pcie_power_reset;
u8 pcie_restore;
u8 analog_shiftreg; u8 analog_shiftreg;
u8 ht_enable; u8 ht_enable;
u32 ofdm_trig_low; u32 ofdm_trig_low;
...@@ -196,17 +188,10 @@ struct ath9k_ops_config { ...@@ -196,17 +188,10 @@ struct ath9k_ops_config {
u32 cck_trig_high; u32 cck_trig_high;
u32 cck_trig_low; u32 cck_trig_low;
u32 enable_ani; u32 enable_ani;
u8 noise_immunity_level;
u32 ofdm_weaksignal_det;
u32 cck_weaksignal_thr;
u8 spur_immunity_level;
u8 firstep_level;
int8_t rssi_thr_high;
int8_t rssi_thr_low;
u16 diversity_control; u16 diversity_control;
u16 antenna_switch_swap; u16 antenna_switch_swap;
int serialize_regmode; int serialize_regmode;
int intr_mitigation; bool intr_mitigation;
#define SPUR_DISABLE 0 #define SPUR_DISABLE 0
#define SPUR_ENABLE_IOCTL 1 #define SPUR_ENABLE_IOCTL 1
#define SPUR_ENABLE_EEPROM 2 #define SPUR_ENABLE_EEPROM 2
...@@ -281,13 +266,6 @@ enum ath9k_int { ...@@ -281,13 +266,6 @@ enum ath9k_int {
#define CHANNEL_HT40PLUS 0x20000 #define CHANNEL_HT40PLUS 0x20000
#define CHANNEL_HT40MINUS 0x40000 #define CHANNEL_HT40MINUS 0x40000
#define CHANNEL_INTERFERENCE 0x01
#define CHANNEL_DFS 0x02
#define CHANNEL_4MS_LIMIT 0x04
#define CHANNEL_DFS_CLEAR 0x08
#define CHANNEL_DISALLOW_ADHOC 0x10
#define CHANNEL_PER_11D_ADHOC 0x20
#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
...@@ -318,10 +296,6 @@ struct ath9k_channel { ...@@ -318,10 +296,6 @@ struct ath9k_channel {
int16_t rawNoiseFloor; int16_t rawNoiseFloor;
}; };
#define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \
(((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \
(((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \
(((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS))
#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
(((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \
(((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \
...@@ -329,7 +303,6 @@ struct ath9k_channel { ...@@ -329,7 +303,6 @@ struct ath9k_channel {
#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) #define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0)
#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) #define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
#define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0)
#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
#define IS_CHAN_A_5MHZ_SPACED(_c) \ #define IS_CHAN_A_5MHZ_SPACED(_c) \
...@@ -420,7 +393,7 @@ struct ath_hw { ...@@ -420,7 +393,7 @@ struct ath_hw {
struct ath9k_hw_version hw_version; struct ath9k_hw_version hw_version;
struct ath9k_ops_config config; struct ath9k_ops_config config;
struct ath9k_hw_capabilities caps; struct ath9k_hw_capabilities caps;
struct ath9k_regulatory regulatory; struct ath_regulatory regulatory;
struct ath9k_channel channels[38]; struct ath9k_channel channels[38];
struct ath9k_channel *curchan; struct ath9k_channel *curchan;
...@@ -463,14 +436,14 @@ struct ath_hw { ...@@ -463,14 +436,14 @@ struct ath_hw {
enum ath9k_ant_setting diversity_control; enum ath9k_ant_setting diversity_control;
/* Calibration */ /* Calibration */
enum hal_cal_types supp_cals; enum ath9k_cal_types supp_cals;
struct hal_cal_list iq_caldata; struct ath9k_cal_list iq_caldata;
struct hal_cal_list adcgain_caldata; struct ath9k_cal_list adcgain_caldata;
struct hal_cal_list adcdc_calinitdata; struct ath9k_cal_list adcdc_calinitdata;
struct hal_cal_list adcdc_caldata; struct ath9k_cal_list adcdc_caldata;
struct hal_cal_list *cal_list; struct ath9k_cal_list *cal_list;
struct hal_cal_list *cal_list_last; struct ath9k_cal_list *cal_list_last;
struct hal_cal_list *cal_list_curr; struct ath9k_cal_list *cal_list_curr;
#define totalPowerMeasI meas0.unsign #define totalPowerMeasI meas0.unsign
#define totalPowerMeasQ meas1.unsign #define totalPowerMeasQ meas1.unsign
#define totalIqCorrMeas meas2.sign #define totalIqCorrMeas meas2.sign
...@@ -540,7 +513,6 @@ struct ath_hw { ...@@ -540,7 +513,6 @@ struct ath_hw {
enum ath9k_ani_cmd ani_function; enum ath9k_ani_cmd ani_function;
u32 intr_txqs; u32 intr_txqs;
bool intr_mitigation;
enum ath9k_ht_extprotspacing extprotspacing; enum ath9k_ht_extprotspacing extprotspacing;
u8 txchainmask; u8 txchainmask;
u8 rxchainmask; u8 rxchainmask;
...@@ -573,7 +545,7 @@ struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error); ...@@ -573,7 +545,7 @@ struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error);
void ath9k_hw_rfdetach(struct ath_hw *ah); void ath9k_hw_rfdetach(struct ath_hw *ah);
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
bool bChannelChange); bool bChannelChange);
bool ath9k_hw_fill_cap_info(struct ath_hw *ah); void ath9k_hw_fill_cap_info(struct ath_hw *ah);
bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
u32 capability, u32 *result); u32 capability, u32 *result);
bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
......
...@@ -49,7 +49,7 @@ bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) ...@@ -49,7 +49,7 @@ bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
bool ath9k_hw_txstart(struct ath_hw *ah, u32 q) bool ath9k_hw_txstart(struct ath_hw *ah, u32 q)
{ {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q);
REG_WRITE(ah, AR_Q_TXE, 1 << q); REG_WRITE(ah, AR_Q_TXE, 1 << q);
...@@ -110,13 +110,15 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) ...@@ -110,13 +110,15 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
if (q >= pCap->total_queues) { if (q >= pCap->total_queues) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
"invalid queue: %u\n", q);
return false; return false;
} }
qi = &ah->txq[q]; qi = &ah->txq[q];
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
"inactive queue: %u\n", q);
return false; return false;
} }
...@@ -146,7 +148,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) ...@@ -146,7 +148,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
break; break;
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
"TSF have moved while trying to set " "TSF has moved while trying to set "
"quiet time TSF: 0x%08x\n", tsfLow); "quiet time TSF: 0x%08x\n", tsfLow);
} }
...@@ -158,8 +160,8 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) ...@@ -158,8 +160,8 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
wait = wait_time; wait = wait_time;
while (ath9k_hw_numtxpending(ah, q)) { while (ath9k_hw_numtxpending(ah, q)) {
if ((--wait) == 0) { if ((--wait) == 0) {
DPRINTF(ah->ah_sc, ATH_DBG_XMIT, DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
"Failed to stop Tx DMA in 100 " "Failed to stop TX DMA in 100 "
"msec after killing last frame\n"); "msec after killing last frame\n");
break; break;
} }
...@@ -454,17 +456,19 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, ...@@ -454,17 +456,19 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
struct ath9k_tx_queue_info *qi; struct ath9k_tx_queue_info *qi;
if (q >= pCap->total_queues) { if (q >= pCap->total_queues) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
"invalid queue: %u\n", q);
return false; return false;
} }
qi = &ah->txq[q]; qi = &ah->txq[q];
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
"inactive queue: %u\n", q);
return false; return false;
} }
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %p\n", qi); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q);
qi->tqi_ver = qinfo->tqi_ver; qi->tqi_ver = qinfo->tqi_ver;
qi->tqi_subtype = qinfo->tqi_subtype; qi->tqi_subtype = qinfo->tqi_subtype;
...@@ -521,13 +525,15 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, ...@@ -521,13 +525,15 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
struct ath9k_tx_queue_info *qi; struct ath9k_tx_queue_info *qi;
if (q >= pCap->total_queues) { if (q >= pCap->total_queues) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
"invalid queue: %u\n", q);
return false; return false;
} }
qi = &ah->txq[q]; qi = &ah->txq[q];
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
"inactive queue: %u\n", q);
return false; return false;
} }
...@@ -575,22 +581,23 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, ...@@ -575,22 +581,23 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
ATH9K_TX_QUEUE_INACTIVE) ATH9K_TX_QUEUE_INACTIVE)
break; break;
if (q == pCap->total_queues) { if (q == pCap->total_queues) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"no available tx queue\n"); "No available TX queue\n");
return -1; return -1;
} }
break; break;
default: default:
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "bad tx queue type %u\n", type); DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n",
type);
return -1; return -1;
} }
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q);
qi = &ah->txq[q]; qi = &ah->txq[q];
if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"tx queue %u already active\n", q); "TX queue: %u already active\n", q);
return -1; return -1;
} }
memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
...@@ -620,16 +627,18 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) ...@@ -620,16 +627,18 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
struct ath9k_tx_queue_info *qi; struct ath9k_tx_queue_info *qi;
if (q >= pCap->total_queues) { if (q >= pCap->total_queues) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
"invalid queue: %u\n", q);
return false; return false;
} }
qi = &ah->txq[q]; qi = &ah->txq[q];
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
"inactive queue: %u\n", q);
return false; return false;
} }
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "release queue %u\n", q); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q);
qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
ah->txok_interrupt_mask &= ~(1 << q); ah->txok_interrupt_mask &= ~(1 << q);
...@@ -650,17 +659,19 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) ...@@ -650,17 +659,19 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
u32 cwMin, chanCwMin, value; u32 cwMin, chanCwMin, value;
if (q >= pCap->total_queues) { if (q >= pCap->total_queues) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
"invalid queue: %u\n", q);
return false; return false;
} }
qi = &ah->txq[q]; qi = &ah->txq[q];
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
"inactive queue: %u\n", q);
return true; return true;
} }
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "reset queue %u\n", q); DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q);
if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
if (chan && IS_CHAN_B(chan)) if (chan && IS_CHAN_B(chan))
...@@ -894,7 +905,7 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) ...@@ -894,7 +905,7 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
reg = REG_READ(ah, AR_OBS_BUS_1); reg = REG_READ(ah, AR_OBS_BUS_1);
DPRINTF(ah->ah_sc, ATH_DBG_FATAL, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"rx failed to go idle in 10 ms RXSM=0x%x\n", reg); "RX failed to go idle in 10 ms RXSM=0x%x\n", reg);
return false; return false;
} }
...@@ -949,8 +960,8 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah) ...@@ -949,8 +960,8 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
} }
if (i == 0) { if (i == 0) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"dma failed to stop in %d ms " "DMA failed to stop in %d ms "
"AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
AH_RX_STOP_DMA_TIMEOUT / 1000, AH_RX_STOP_DMA_TIMEOUT / 1000,
REG_READ(ah, AR_CR), REG_READ(ah, AR_CR),
......
...@@ -287,7 +287,6 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, ...@@ -287,7 +287,6 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
} }
spin_unlock_bh(&sc->sc_resetlock); spin_unlock_bh(&sc->sc_resetlock);
sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
sc->sc_flags &= ~SC_OP_FULL_RESET; sc->sc_flags &= ~SC_OP_FULL_RESET;
if (ath_startrecv(sc) != 0) { if (ath_startrecv(sc) != 0) {
...@@ -368,28 +367,16 @@ static void ath_ani_calibrate(unsigned long data) ...@@ -368,28 +367,16 @@ static void ath_ani_calibrate(unsigned long data)
/* Perform calibration if necessary */ /* Perform calibration if necessary */
if (longcal || shortcal) { if (longcal || shortcal) {
bool iscaldone = false; sc->ani.caldone = ath9k_hw_calibrate(ah, ah->curchan,
sc->rx_chainmask, longcal);
if (ath9k_hw_calibrate(ah, ah->curchan,
sc->rx_chainmask, longcal, if (longcal)
&iscaldone)) { sc->ani.noise_floor = ath9k_hw_getchan_noise(ah,
if (longcal) ah->curchan);
sc->ani.noise_floor =
ath9k_hw_getchan_noise(ah, DPRINTF(sc, ATH_DBG_ANI," calibrate chan %u/%x nf: %d\n",
ah->curchan); ah->curchan->channel, ah->curchan->channelFlags,
sc->ani.noise_floor);
DPRINTF(sc, ATH_DBG_ANI,
"calibrate chan %u/%x nf: %d\n",
ah->curchan->channel,
ah->curchan->channelFlags,
sc->ani.noise_floor);
} else {
DPRINTF(sc, ATH_DBG_ANY,
"calibrate chan %u/%x failed\n",
ah->curchan->channel,
ah->curchan->channelFlags);
}
sc->ani.caldone = iscaldone;
} }
} }
...@@ -408,6 +395,18 @@ static void ath_ani_calibrate(unsigned long data) ...@@ -408,6 +395,18 @@ static void ath_ani_calibrate(unsigned long data)
mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
} }
static void ath_start_ani(struct ath_softc *sc)
{
unsigned long timestamp = jiffies_to_msecs(jiffies);
sc->ani.longcal_timer = timestamp;
sc->ani.shortcal_timer = timestamp;
sc->ani.checkani_timer = timestamp;
mod_timer(&sc->ani.timer,
jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
}
/* /*
* Update tx/rx chainmask. For legacy association, * Update tx/rx chainmask. For legacy association,
* hard code chainmask to 1x1, for 11n association, use * hard code chainmask to 1x1, for 11n association, use
...@@ -416,7 +415,6 @@ static void ath_ani_calibrate(unsigned long data) ...@@ -416,7 +415,6 @@ static void ath_ani_calibrate(unsigned long data)
*/ */
void ath_update_chainmask(struct ath_softc *sc, int is_ht) void ath_update_chainmask(struct ath_softc *sc, int is_ht)
{ {
sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
if (is_ht || if (is_ht ||
(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) { (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) {
sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask; sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
...@@ -436,12 +434,12 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) ...@@ -436,12 +434,12 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
an = (struct ath_node *)sta->drv_priv; an = (struct ath_node *)sta->drv_priv;
if (sc->sc_flags & SC_OP_TXAGGR) if (sc->sc_flags & SC_OP_TXAGGR) {
ath_tx_node_init(sc, an); ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + sta->ht_cap.ampdu_factor);
sta->ht_cap.ampdu_factor); an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); }
} }
static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
...@@ -458,133 +456,124 @@ static void ath9k_tasklet(unsigned long data) ...@@ -458,133 +456,124 @@ static void ath9k_tasklet(unsigned long data)
u32 status = sc->intrstatus; u32 status = sc->intrstatus;
if (status & ATH9K_INT_FATAL) { if (status & ATH9K_INT_FATAL) {
/* need a chip reset */
ath_reset(sc, false); ath_reset(sc, false);
return; return;
} else { }
if (status & if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
(ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { spin_lock_bh(&sc->rx.rxflushlock);
spin_lock_bh(&sc->rx.rxflushlock); ath_rx_tasklet(sc, 0);
ath_rx_tasklet(sc, 0); spin_unlock_bh(&sc->rx.rxflushlock);
spin_unlock_bh(&sc->rx.rxflushlock);
}
/* XXX: optimize this */
if (status & ATH9K_INT_TX)
ath_tx_tasklet(sc);
} }
if (status & ATH9K_INT_TX)
ath_tx_tasklet(sc);
/* re-enable hardware interrupt */ /* re-enable hardware interrupt */
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
} }
irqreturn_t ath_isr(int irq, void *dev) irqreturn_t ath_isr(int irq, void *dev)
{ {
#define SCHED_INTR ( \
ATH9K_INT_FATAL | \
ATH9K_INT_RXORN | \
ATH9K_INT_RXEOL | \
ATH9K_INT_RX | \
ATH9K_INT_TX | \
ATH9K_INT_BMISS | \
ATH9K_INT_CST | \
ATH9K_INT_TSFOOR)
struct ath_softc *sc = dev; struct ath_softc *sc = dev;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
enum ath9k_int status; enum ath9k_int status;
bool sched = false; bool sched = false;
do { /*
if (sc->sc_flags & SC_OP_INVALID) { * The hardware is not ready/present, don't
/* * touch anything. Note this can happen early
* The hardware is not ready/present, don't * on if the IRQ is shared.
* touch anything. Note this can happen early */
* on if the IRQ is shared. if (sc->sc_flags & SC_OP_INVALID)
*/ return IRQ_NONE;
return IRQ_NONE;
}
if (!ath9k_hw_intrpend(ah)) { /* shared irq, not for us */
return IRQ_NONE;
}
/* ath9k_ps_wakeup(sc);
* Figure out the reason(s) for the interrupt. Note
* that the hal returns a pseudo-ISR that may include /* shared irq, not for us */
* bits we haven't explicitly enabled so we mask the
* value to insure we only process bits we requested. if (!ath9k_hw_intrpend(ah)) {
*/ ath9k_ps_restore(sc);
ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ return IRQ_NONE;
}
/*
* Figure out the reason(s) for the interrupt. Note
* that the hal returns a pseudo-ISR that may include
* bits we haven't explicitly enabled so we mask the
* value to insure we only process bits we requested.
*/
ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
status &= sc->imask; /* discard unasked-for bits */
/*
* If there are no status bits set, then this interrupt was not
* for me (should have been caught above).
*/
if (!status) {
ath9k_ps_restore(sc);
return IRQ_NONE;
}
/* Cache the status */
sc->intrstatus = status;
status &= sc->imask; /* discard unasked-for bits */ if (status & SCHED_INTR)
sched = true;
/*
* If a FATAL or RXORN interrupt is received, we have to reset the
* chip immediately.
*/
if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN))
goto chip_reset;
if (status & ATH9K_INT_SWBA)
tasklet_schedule(&sc->bcon_tasklet);
if (status & ATH9K_INT_TXURN)
ath9k_hw_updatetxtriglevel(ah, true);
if (status & ATH9K_INT_MIB) {
/* /*
* If there are no status bits set, then this interrupt was not * Disable interrupts until we service the MIB
* for me (should have been caught above). * interrupt; otherwise it will continue to
* fire.
*/ */
if (!status) ath9k_hw_set_interrupts(ah, 0);
return IRQ_NONE; /*
* Let the hal handle the event. We assume
sc->intrstatus = status; * it will clear whatever condition caused
ath9k_ps_wakeup(sc); * the interrupt.
*/
ath9k_hw_procmibevent(ah, &sc->nodestats);
ath9k_hw_set_interrupts(ah, sc->imask);
}
if (status & ATH9K_INT_FATAL) { if (status & ATH9K_INT_TIM_TIMER) {
/* need a chip reset */ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
/* Clear RxAbort bit so that we can
* receive frames */
ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
ath9k_hw_setrxabort(ah, 0);
sched = true; sched = true;
} else if (status & ATH9K_INT_RXORN) { sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
/* need a chip reset */
sched = true;
} else {
if (status & ATH9K_INT_SWBA) {
/* schedule a tasklet for beacon handling */
tasklet_schedule(&sc->bcon_tasklet);
}
if (status & ATH9K_INT_RXEOL) {
/*
* NB: the hardware should re-read the link when
* RXE bit is written, but it doesn't work
* at least on older hardware revs.
*/
sched = true;
}
if (status & ATH9K_INT_TXURN)
/* bump tx trigger level */
ath9k_hw_updatetxtriglevel(ah, true);
/* XXX: optimize this */
if (status & ATH9K_INT_RX)
sched = true;
if (status & ATH9K_INT_TX)
sched = true;
if (status & ATH9K_INT_BMISS)
sched = true;
/* carrier sense timeout */
if (status & ATH9K_INT_CST)
sched = true;
if (status & ATH9K_INT_MIB) {
/*
* Disable interrupts until we service the MIB
* interrupt; otherwise it will continue to
* fire.
*/
ath9k_hw_set_interrupts(ah, 0);
/*
* Let the hal handle the event. We assume
* it will clear whatever condition caused
* the interrupt.
*/
ath9k_hw_procmibevent(ah, &sc->nodestats);
ath9k_hw_set_interrupts(ah, sc->imask);
}
if (status & ATH9K_INT_TIM_TIMER) {
if (!(ah->caps.hw_caps &
ATH9K_HW_CAP_AUTOSLEEP)) {
/* Clear RxAbort bit so that we can
* receive frames */
ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
ath9k_hw_setrxabort(ah, 0);
sched = true;
sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
}
}
if (status & ATH9K_INT_TSFOOR) {
/* FIXME: Handle this interrupt for power save */
sched = true;
}
} }
ath9k_ps_restore(sc); }
} while (0);
chip_reset:
ath9k_ps_restore(sc);
ath_debug_stat_interrupt(sc, status); ath_debug_stat_interrupt(sc, status);
if (sched) { if (sched) {
...@@ -594,6 +583,8 @@ irqreturn_t ath_isr(int irq, void *dev) ...@@ -594,6 +583,8 @@ irqreturn_t ath_isr(int irq, void *dev)
} }
return IRQ_HANDLED; return IRQ_HANDLED;
#undef SCHED_INTR
} }
static u32 ath_get_extchanmode(struct ath_softc *sc, static u32 ath_get_extchanmode(struct ath_softc *sc,
...@@ -676,7 +667,7 @@ static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key, ...@@ -676,7 +667,7 @@ static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key,
memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); 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(sc->sc_ah, keyix, hk, NULL)) {
/* TX MIC entry failed. No need to proceed further */ /* TX MIC entry failed. No need to proceed further */
DPRINTF(sc, ATH_DBG_KEYCACHE, DPRINTF(sc, ATH_DBG_FATAL,
"Setting TX MIC Key Failed\n"); "Setting TX MIC Key Failed\n");
return 0; return 0;
} }
...@@ -920,11 +911,9 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, ...@@ -920,11 +911,9 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
/* Start ANI */ ath_start_ani(sc);
mod_timer(&sc->ani.timer,
jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
} else { } else {
DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISSOC\n"); DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
sc->curaid = 0; sc->curaid = 0;
} }
} }
...@@ -1098,10 +1087,10 @@ void ath_radio_enable(struct ath_softc *sc) ...@@ -1098,10 +1087,10 @@ void ath_radio_enable(struct ath_softc *sc)
int r; int r;
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->sc_resetlock); ath9k_hw_configpcipowersave(ah, 0);
spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, ah->curchan, false); r = ath9k_hw_reset(ah, ah->curchan, false);
if (r) { if (r) {
DPRINTF(sc, ATH_DBG_FATAL, DPRINTF(sc, ATH_DBG_FATAL,
"Unable to reset channel %u (%uMhz) ", "Unable to reset channel %u (%uMhz) ",
...@@ -1163,6 +1152,7 @@ void ath_radio_disable(struct ath_softc *sc) ...@@ -1163,6 +1152,7 @@ void ath_radio_disable(struct ath_softc *sc)
spin_unlock_bh(&sc->sc_resetlock); spin_unlock_bh(&sc->sc_resetlock);
ath9k_hw_phy_disable(ah); ath9k_hw_phy_disable(ah);
ath9k_hw_configpcipowersave(ah, 1);
ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
} }
...@@ -1267,7 +1257,6 @@ static int ath_init_sw_rfkill(struct ath_softc *sc) ...@@ -1267,7 +1257,6 @@ static int ath_init_sw_rfkill(struct ath_softc *sc)
sc->rf_kill.rfkill->data = sc; sc->rf_kill.rfkill->data = sc;
sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio; sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio;
sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED; sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED;
sc->rf_kill.rfkill->user_claim_unsupported = 1;
return 0; return 0;
} }
...@@ -1362,6 +1351,17 @@ void ath_detach(struct ath_softc *sc) ...@@ -1362,6 +1351,17 @@ void ath_detach(struct ath_softc *sc)
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
} }
static int ath9k_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_regulatory *reg = &sc->sc_ah->regulatory;
return ath_reg_notifier_apply(wiphy, request, reg);
}
static int ath_init(u16 devid, struct ath_softc *sc) static int ath_init(u16 devid, struct ath_softc *sc)
{ {
struct ath_hw *ah = NULL; struct ath_hw *ah = NULL;
...@@ -1403,7 +1403,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) ...@@ -1403,7 +1403,7 @@ static int ath_init(u16 devid, struct ath_softc *sc)
/* Get the hardware key cache size. */ /* Get the hardware key cache size. */
sc->keymax = ah->caps.keycache_size; sc->keymax = ah->caps.keycache_size;
if (sc->keymax > ATH_KEYMAX) { if (sc->keymax > ATH_KEYMAX) {
DPRINTF(sc, ATH_DBG_KEYCACHE, DPRINTF(sc, ATH_DBG_ANY,
"Warning, using only %u entries in %u key cache\n", "Warning, using only %u entries in %u key cache\n",
ATH_KEYMAX, sc->keymax); ATH_KEYMAX, sc->keymax);
sc->keymax = ATH_KEYMAX; sc->keymax = ATH_KEYMAX;
...@@ -1416,7 +1416,9 @@ static int ath_init(u16 devid, struct ath_softc *sc) ...@@ -1416,7 +1416,9 @@ static int ath_init(u16 devid, struct ath_softc *sc)
for (i = 0; i < sc->keymax; i++) for (i = 0; i < sc->keymax; i++)
ath9k_hw_keyreset(ah, (u16) i); ath9k_hw_keyreset(ah, (u16) i);
if (ath9k_regd_init(sc->sc_ah)) error = ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy,
ath9k_reg_notifier);
if (error)
goto bad; goto bad;
/* default to MONITOR mode */ /* default to MONITOR mode */
...@@ -1545,9 +1547,6 @@ static int ath_init(u16 devid, struct ath_softc *sc) ...@@ -1545,9 +1547,6 @@ static int ath_init(u16 devid, struct ath_softc *sc)
sc->beacon.bslot_aphy[i] = NULL; sc->beacon.bslot_aphy[i] = NULL;
} }
/* save MISC configurations */
sc->config.swBeaconProcess = 1;
/* setup channels and rates */ /* setup channels and rates */
sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
...@@ -1602,9 +1601,6 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -1602,9 +1601,6 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT); BIT(NL80211_IFTYPE_MESH_POINT);
hw->wiphy->reg_notifier = ath9k_reg_notifier;
hw->wiphy->strict_regulatory = true;
hw->queues = 4; hw->queues = 4;
hw->max_rates = 4; hw->max_rates = 4;
hw->channel_change_time = 5000; hw->channel_change_time = 5000;
...@@ -1625,8 +1621,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -1625,8 +1621,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
int ath_attach(u16 devid, struct ath_softc *sc) int ath_attach(u16 devid, struct ath_softc *sc)
{ {
struct ieee80211_hw *hw = sc->hw; struct ieee80211_hw *hw = sc->hw;
const struct ieee80211_regdomain *regd;
int error = 0, i; int error = 0, i;
struct ath_regulatory *reg;
DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
...@@ -1634,6 +1630,8 @@ int ath_attach(u16 devid, struct ath_softc *sc) ...@@ -1634,6 +1630,8 @@ int ath_attach(u16 devid, struct ath_softc *sc)
if (error != 0) if (error != 0)
return error; return error;
reg = &sc->sc_ah->regulatory;
/* get mac address from hardware and set in mac80211 */ /* get mac address from hardware and set in mac80211 */
SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr); SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr);
...@@ -1666,31 +1664,14 @@ int ath_attach(u16 devid, struct ath_softc *sc) ...@@ -1666,31 +1664,14 @@ int ath_attach(u16 devid, struct ath_softc *sc)
goto error_attach; goto error_attach;
#endif #endif
if (ath9k_is_world_regd(sc->sc_ah)) {
/* Anything applied here (prior to wiphy registration) gets
* saved on the wiphy orig_* parameters */
regd = ath9k_world_regdomain(sc->sc_ah);
hw->wiphy->custom_regulatory = true;
hw->wiphy->strict_regulatory = false;
} else {
/* This gets applied in the case of the absense of CRDA,
* it's our own custom world regulatory domain, similar to
* cfg80211's but we enable passive scanning */
regd = ath9k_default_world_regdomain();
}
wiphy_apply_custom_regulatory(hw->wiphy, regd);
ath9k_reg_apply_radar_flags(hw->wiphy);
ath9k_reg_apply_world_flags(hw->wiphy, NL80211_REGDOM_SET_BY_DRIVER);
INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
sc->wiphy_scheduler_int = msecs_to_jiffies(500); sc->wiphy_scheduler_int = msecs_to_jiffies(500);
error = ieee80211_register_hw(hw); error = ieee80211_register_hw(hw);
if (!ath9k_is_world_regd(sc->sc_ah)) { if (!ath_is_world_regd(reg)) {
error = regulatory_hint(hw->wiphy, error = regulatory_hint(hw->wiphy, reg->alpha2);
sc->sc_ah->regulatory.alpha2);
if (error) if (error)
goto error_attach; goto error_attach;
} }
...@@ -1792,7 +1773,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, ...@@ -1792,7 +1773,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
goto fail; goto fail;
} }
dd->dd_name = name;
dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
/* /*
...@@ -1822,7 +1802,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, ...@@ -1822,7 +1802,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
} }
ds = dd->dd_desc; ds = dd->dd_desc;
DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
dd->dd_name, ds, (u32) dd->dd_desc_len, name, ds, (u32) dd->dd_desc_len,
ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
/* allocate buffers */ /* allocate buffers */
...@@ -2043,8 +2023,7 @@ static int ath9k_start(struct ieee80211_hw *hw) ...@@ -2043,8 +2023,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
* here except setup the interrupt mask. * here except setup the interrupt mask.
*/ */
if (ath_startrecv(sc) != 0) { if (ath_startrecv(sc) != 0) {
DPRINTF(sc, ATH_DBG_FATAL, DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n");
"Unable to start recv logic\n");
r = -EIO; r = -EIO;
goto mutex_unlock; goto mutex_unlock;
} }
...@@ -2257,25 +2236,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ...@@ -2257,25 +2236,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
sc->imask |= ATH9K_INT_TSFOOR; sc->imask |= ATH9K_INT_TSFOOR;
} }
/*
* Some hardware processes the TIM IE and fires an
* interrupt when the TIM bit is set. For hardware
* that does, if not overridden by configuration,
* enable the TIM interrupt when operating as station.
*/
if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) &&
(conf->type == NL80211_IFTYPE_STATION) &&
!sc->config.swBeaconProcess)
sc->imask |= ATH9K_INT_TIM;
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
if (conf->type == NL80211_IFTYPE_AP) { if (conf->type == NL80211_IFTYPE_AP)
/* TODO: is this a suitable place to start ANI for AP mode? */ ath_start_ani(sc);
/* Start ANI */
mod_timer(&sc->ani.timer,
jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
}
out: out:
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
...@@ -2326,26 +2290,33 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ...@@ -2326,26 +2290,33 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
struct ath_wiphy *aphy = hw->priv; struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc; struct ath_softc *sc = aphy->sc;
struct ieee80211_conf *conf = &hw->conf; struct ieee80211_conf *conf = &hw->conf;
struct ath_hw *ah = sc->sc_ah;
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
if (changed & IEEE80211_CONF_CHANGE_PS) { if (changed & IEEE80211_CONF_CHANGE_PS) {
if (conf->flags & IEEE80211_CONF_PS) { if (conf->flags & IEEE80211_CONF_PS) {
if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { if (!(ah->caps.hw_caps &
sc->imask |= ATH9K_INT_TIM_TIMER; ATH9K_HW_CAP_AUTOSLEEP)) {
ath9k_hw_set_interrupts(sc->sc_ah, if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
sc->imask); sc->imask |= ATH9K_INT_TIM_TIMER;
ath9k_hw_set_interrupts(sc->sc_ah,
sc->imask);
}
ath9k_hw_setrxabort(sc->sc_ah, 1);
} }
ath9k_hw_setrxabort(sc->sc_ah, 1);
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
} else { } else {
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
ath9k_hw_setrxabort(sc->sc_ah, 0); if (!(ah->caps.hw_caps &
sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; ATH9K_HW_CAP_AUTOSLEEP)) {
if (sc->imask & ATH9K_INT_TIM_TIMER) { ath9k_hw_setrxabort(sc->sc_ah, 0);
sc->imask &= ~ATH9K_INT_TIM_TIMER; sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
ath9k_hw_set_interrupts(sc->sc_ah, if (sc->imask & ATH9K_INT_TIM_TIMER) {
sc->imask); sc->imask &= ~ATH9K_INT_TIM_TIMER;
ath9k_hw_set_interrupts(sc->sc_ah,
sc->imask);
}
} }
} }
} }
...@@ -2562,6 +2533,8 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, ...@@ -2562,6 +2533,8 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
qi.tqi_aifs = params->aifs; qi.tqi_aifs = params->aifs;
qi.tqi_cwmin = params->cw_min; qi.tqi_cwmin = params->cw_min;
qi.tqi_cwmax = params->cw_max; qi.tqi_cwmax = params->cw_max;
...@@ -2598,7 +2571,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, ...@@ -2598,7 +2571,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
DPRINTF(sc, ATH_DBG_KEYCACHE, "Set HW Key\n"); DPRINTF(sc, ATH_DBG_CONFIG, "Set HW Key\n");
switch (cmd) { switch (cmd) {
case SET_KEY: case SET_KEY:
...@@ -2771,6 +2744,7 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) ...@@ -2771,6 +2744,7 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
aphy->state = ATH_WIPHY_ACTIVE; aphy->state = ATH_WIPHY_ACTIVE;
sc->sc_flags &= ~SC_OP_SCANNING; sc->sc_flags &= ~SC_OP_SCANNING;
sc->sc_flags |= SC_OP_FULL_RESET;
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
} }
......
...@@ -46,7 +46,7 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) ...@@ -46,7 +46,7 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
channelSel = ((freq - 704) * 2 - 3040) / 10; channelSel = ((freq - 704) * 2 - 3040) / 10;
bModeSynth = 1; bModeSynth = 1;
} else { } else {
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"Invalid channel %u MHz\n", freq); "Invalid channel %u MHz\n", freq);
return false; return false;
} }
...@@ -79,7 +79,7 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) ...@@ -79,7 +79,7 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
aModeRefSel = ath9k_hw_reverse_bits(1, 2); aModeRefSel = ath9k_hw_reverse_bits(1, 2);
} else { } else {
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"Invalid channel %u MHz\n", freq); "Invalid channel %u MHz\n", freq);
return false; return false;
} }
......
...@@ -556,9 +556,6 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, ...@@ -556,9 +556,6 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
int r; \ int r; \
for (r = 0; r < ((iniarray)->ia_rows); r++) { \ for (r = 0; r < ((iniarray)->ia_rows); r++) { \
REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, \
"RF 0x%x V 0x%x\n", \
INI_RA((iniarray), r, 0), (regData)[r]); \
DO_DELAY(regWr); \ DO_DELAY(regWr); \
} \ } \
} while (0) } while (0)
......
...@@ -524,7 +524,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, ...@@ -524,7 +524,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
u32 valid; u32 valid;
for (i = 0; i < rate_table->rate_cnt; i++) { for (i = 0; i < rate_table->rate_cnt; i++) {
valid = (ath_rc_priv->single_stream ? valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
rate_table->info[i].valid_single_stream : rate_table->info[i].valid_single_stream :
rate_table->info[i].valid); rate_table->info[i].valid);
if (valid == 1) { if (valid == 1) {
...@@ -557,9 +557,9 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, ...@@ -557,9 +557,9 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
for (i = 0; i < rateset->rs_nrates; i++) { for (i = 0; i < rateset->rs_nrates; i++) {
for (j = 0; j < rate_table->rate_cnt; j++) { for (j = 0; j < rate_table->rate_cnt; j++) {
u32 phy = rate_table->info[j].phy; u32 phy = rate_table->info[j].phy;
u32 valid = (ath_rc_priv->single_stream ? u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
rate_table->info[j].valid_single_stream : rate_table->info[j].valid_single_stream :
rate_table->info[j].valid); rate_table->info[j].valid);
u8 rate = rateset->rs_rates[i]; u8 rate = rateset->rs_rates[i];
u8 dot11rate = rate_table->info[j].dot11rate; u8 dot11rate = rate_table->info[j].dot11rate;
...@@ -603,7 +603,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, ...@@ -603,7 +603,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
for (i = 0; i < rateset->rs_nrates; i++) { for (i = 0; i < rateset->rs_nrates; i++) {
for (j = 0; j < rate_table->rate_cnt; j++) { for (j = 0; j < rate_table->rate_cnt; j++) {
u32 phy = rate_table->info[j].phy; u32 phy = rate_table->info[j].phy;
u32 valid = (ath_rc_priv->single_stream ? u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
rate_table->info[j].valid_single_stream : rate_table->info[j].valid_single_stream :
rate_table->info[j].valid); rate_table->info[j].valid);
u8 rate = rateset->rs_rates[i]; u8 rate = rateset->rs_rates[i];
...@@ -740,9 +740,10 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, ...@@ -740,9 +740,10 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
if (rate > (ath_rc_priv->rate_table_size - 1)) if (rate > (ath_rc_priv->rate_table_size - 1))
rate = ath_rc_priv->rate_table_size - 1; rate = ath_rc_priv->rate_table_size - 1;
ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) || ASSERT((rate_table->info[rate].valid &&
(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) ||
(rate_table->info[rate].valid_single_stream && (rate_table->info[rate].valid_single_stream &&
ath_rc_priv->single_stream)); !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)));
return rate; return rate;
} }
...@@ -811,7 +812,7 @@ static u8 ath_rc_rate_getidx(struct ath_softc *sc, ...@@ -811,7 +812,7 @@ static u8 ath_rc_rate_getidx(struct ath_softc *sc,
u16 min_rate) u16 min_rate)
{ {
u32 j; u32 j;
u8 nextindex; u8 nextindex = 0;
if (min_rate) { if (min_rate) {
for (j = RATE_TABLE_SIZE; j > 0; j--) { for (j = RATE_TABLE_SIZE; j > 0; j--) {
...@@ -1320,7 +1321,7 @@ static void ath_rc_tx_status(struct ath_softc *sc, ...@@ -1320,7 +1321,7 @@ static void ath_rc_tx_status(struct ath_softc *sc,
* 40 to 20 => don't update */ * 40 to 20 => don't update */
if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
(ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
return; return;
rix = ath_rc_get_rateindex(rate_table, &rates[i]); rix = ath_rc_get_rateindex(rate_table, &rates[i]);
...@@ -1345,9 +1346,8 @@ static void ath_rc_tx_status(struct ath_softc *sc, ...@@ -1345,9 +1346,8 @@ static void ath_rc_tx_status(struct ath_softc *sc,
/* If HT40 and we have switched mode from 40 to 20 => don't update */ /* If HT40 and we have switched mode from 40 to 20 => don't update */
if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
(ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) { !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
return; return;
}
rix = ath_rc_get_rateindex(rate_table, &rates[i]); rix = ath_rc_get_rateindex(rate_table, &rates[i]);
ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix, ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix,
...@@ -1420,10 +1420,6 @@ static void ath_rc_init(struct ath_softc *sc, ...@@ -1420,10 +1420,6 @@ static void ath_rc_init(struct ath_softc *sc,
ath_rc_priv->valid_phy_rateidx[i][j] = 0; ath_rc_priv->valid_phy_rateidx[i][j] = 0;
ath_rc_priv->valid_phy_ratecnt[i] = 0; ath_rc_priv->valid_phy_ratecnt[i] = 0;
} }
ath_rc_priv->rc_phy_mode = ath_rc_priv->ht_cap & WLAN_RC_40_FLAG;
/* Set stream capability */
ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1;
if (!rateset->rs_nrates) { if (!rateset->rs_nrates) {
/* No working rate, just initialize valid rates */ /* No working rate, just initialize valid rates */
......
...@@ -24,7 +24,6 @@ struct ath_softc; ...@@ -24,7 +24,6 @@ struct ath_softc;
#define ATH_RATE_MAX 30 #define ATH_RATE_MAX 30
#define RATE_TABLE_SIZE 64 #define RATE_TABLE_SIZE 64
#define MAX_TX_RATE_PHY 48 #define MAX_TX_RATE_PHY 48
#define WLAN_CTRL_FRAME_SIZE (2+2+6+4)
/* VALID_ALL - valid for 20/40/Legacy, /* VALID_ALL - valid for 20/40/Legacy,
* VALID - Legacy only, * VALID - Legacy only,
...@@ -158,7 +157,6 @@ struct ath_rateset { ...@@ -158,7 +157,6 @@ struct ath_rateset {
* @probe_interval: interval for ratectrl to probe for other rates * @probe_interval: interval for ratectrl to probe for other rates
* @prev_data_rix: rate idx of last data frame * @prev_data_rix: rate idx of last data frame
* @ht_cap: HT capabilities * @ht_cap: HT capabilities
* @single_stream: When TRUE, only single TX stream possible
* @neg_rates: Negotatied rates * @neg_rates: Negotatied rates
* @neg_ht_rates: Negotiated HT rates * @neg_ht_rates: Negotiated HT rates
*/ */
...@@ -176,10 +174,8 @@ struct ath_rate_priv { ...@@ -176,10 +174,8 @@ struct ath_rate_priv {
u8 max_valid_rate; u8 max_valid_rate;
u8 valid_rate_index[RATE_TABLE_SIZE]; u8 valid_rate_index[RATE_TABLE_SIZE];
u8 ht_cap; u8 ht_cap;
u8 single_stream;
u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
u8 rc_phy_mode;
u8 rate_max_phy; u8 rate_max_phy;
u32 rssi_time; u32 rssi_time;
u32 rssi_down_time; u32 rssi_down_time;
......
...@@ -283,54 +283,51 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) ...@@ -283,54 +283,51 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
struct ath_buf *bf; struct ath_buf *bf;
int error = 0; int error = 0;
do { spin_lock_init(&sc->rx.rxflushlock);
spin_lock_init(&sc->rx.rxflushlock); sc->sc_flags &= ~SC_OP_RXFLUSH;
sc->sc_flags &= ~SC_OP_RXFLUSH; spin_lock_init(&sc->rx.rxbuflock);
spin_lock_init(&sc->rx.rxbuflock);
sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
min(sc->cachelsz,
(u16)64));
DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
sc->cachelsz, sc->rx.bufsize); min(sc->cachelsz, (u16)64));
/* Initialize rx descriptors */ DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
sc->cachelsz, sc->rx.bufsize);
error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, /* Initialize rx descriptors */
"rx", nbufs, 1);
if (error != 0) {
DPRINTF(sc, ATH_DBG_FATAL,
"failed to allocate rx descriptors: %d\n", error);
break;
}
list_for_each_entry(bf, &sc->rx.rxbuf, list) { error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); "rx", nbufs, 1);
if (skb == NULL) { if (error != 0) {
error = -ENOMEM; DPRINTF(sc, ATH_DBG_FATAL,
break; "failed to allocate rx descriptors: %d\n", error);
} goto err;
}
bf->bf_mpdu = skb; list_for_each_entry(bf, &sc->rx.rxbuf, list) {
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL);
sc->rx.bufsize, if (skb == NULL) {
DMA_FROM_DEVICE); error = -ENOMEM;
if (unlikely(dma_mapping_error(sc->dev, goto err;
bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
DPRINTF(sc, ATH_DBG_CONFIG,
"dma_mapping_error() on RX init\n");
error = -ENOMEM;
break;
}
bf->bf_dmacontext = bf->bf_buf_addr;
} }
sc->rx.rxlink = NULL;
} while (0); bf->bf_mpdu = skb;
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
sc->rx.bufsize,
DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(sc->dev,
bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
DPRINTF(sc, ATH_DBG_FATAL,
"dma_mapping_error() on RX init\n");
error = -ENOMEM;
goto err;
}
bf->bf_dmacontext = bf->bf_buf_addr;
}
sc->rx.rxlink = NULL;
err:
if (error) if (error)
ath_rx_cleanup(sc); ath_rx_cleanup(sc);
...@@ -345,10 +342,8 @@ void ath_rx_cleanup(struct ath_softc *sc) ...@@ -345,10 +342,8 @@ void ath_rx_cleanup(struct ath_softc *sc)
list_for_each_entry(bf, &sc->rx.rxbuf, list) { list_for_each_entry(bf, &sc->rx.rxbuf, list) {
skb = bf->bf_mpdu; skb = bf->bf_mpdu;
if (skb) { if (skb) {
dma_unmap_single(sc->dev, dma_unmap_single(sc->dev, bf->bf_buf_addr,
bf->bf_buf_addr, sc->rx.bufsize, DMA_FROM_DEVICE);
sc->rx.bufsize,
DMA_FROM_DEVICE);
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
} }
...@@ -675,7 +670,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) ...@@ -675,7 +670,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
bf->bf_buf_addr))) { bf->bf_buf_addr))) {
dev_kfree_skb_any(requeue_skb); dev_kfree_skb_any(requeue_skb);
bf->bf_mpdu = NULL; bf->bf_mpdu = NULL;
DPRINTF(sc, ATH_DBG_CONFIG, DPRINTF(sc, ATH_DBG_FATAL,
"dma_mapping_error() on RX\n"); "dma_mapping_error() on RX\n");
break; break;
} }
......
...@@ -283,7 +283,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ...@@ -283,7 +283,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
bool rc_update = true; bool rc_update = true;
skb = (struct sk_buff *)bf->bf_mpdu; skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
rcu_read_lock(); rcu_read_lock();
...@@ -380,8 +380,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ...@@ -380,8 +380,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar);
} else { } else {
/* retry the un-acked ones */ /* retry the un-acked ones */
if (bf->bf_next == NULL && if (bf->bf_next == NULL && bf_last->bf_stale) {
bf_last->bf_status & ATH_BUFSTATUS_STALE) {
struct ath_buf *tbf; struct ath_buf *tbf;
tbf = ath_clone_txbuf(sc, bf_last); tbf = ath_clone_txbuf(sc, bf_last);
...@@ -444,7 +443,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, ...@@ -444,7 +443,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
u16 aggr_limit, legacy = 0, maxampdu; u16 aggr_limit, legacy = 0, maxampdu;
int i; int i;
skb = (struct sk_buff *)bf->bf_mpdu; skb = bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb); tx_info = IEEE80211_SKB_CB(skb);
rates = tx_info->control.rates; rates = tx_info->control.rates;
tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
...@@ -1004,7 +1003,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) ...@@ -1004,7 +1003,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
bf = list_first_entry(&txq->axq_q, struct ath_buf, list); bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
if (bf->bf_status & ATH_BUFSTATUS_STALE) { if (bf->bf_stale) {
list_del(&bf->list); list_del(&bf->list);
spin_unlock_bh(&txq->axq_lock); spin_unlock_bh(&txq->axq_lock);
...@@ -1452,7 +1451,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) ...@@ -1452,7 +1451,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
skb = (struct sk_buff *)bf->bf_mpdu; skb = bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb); tx_info = IEEE80211_SKB_CB(skb);
rates = tx_info->control.rates; rates = tx_info->control.rates;
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
...@@ -1573,8 +1572,9 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, ...@@ -1573,8 +1572,9 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
skb->len, DMA_TO_DEVICE); skb->len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) { if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) {
bf->bf_mpdu = NULL; bf->bf_mpdu = NULL;
DPRINTF(sc, ATH_DBG_CONFIG, kfree(tx_info_priv);
"dma_mapping_error() on TX\n"); tx_info->rate_driver_data[0] = NULL;
DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error() on TX\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -1586,7 +1586,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, ...@@ -1586,7 +1586,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_control *txctl) struct ath_tx_control *txctl)
{ {
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_node *an = NULL; struct ath_node *an = NULL;
...@@ -1860,7 +1860,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, ...@@ -1860,7 +1860,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
int nbad, int txok, bool update_rc) int nbad, int txok, bool update_rc)
{ {
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
...@@ -1941,7 +1941,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) ...@@ -1941,7 +1941,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
* it with the STALE flag. * it with the STALE flag.
*/ */
bf_held = NULL; bf_held = NULL;
if (bf->bf_status & ATH_BUFSTATUS_STALE) { if (bf->bf_stale) {
bf_held = bf; bf_held = bf;
if (list_is_last(&bf_held->list, &txq->axq_q)) { if (list_is_last(&bf_held->list, &txq->axq_q)) {
txq->axq_link = NULL; txq->axq_link = NULL;
...@@ -1982,7 +1982,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) ...@@ -1982,7 +1982,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
* however leave the last descriptor back as the holding * however leave the last descriptor back as the holding
* descriptor for hw. * descriptor for hw.
*/ */
lastbf->bf_status |= ATH_BUFSTATUS_STALE; lastbf->bf_stale = true;
INIT_LIST_HEAD(&bf_head); INIT_LIST_HEAD(&bf_head);
if (!list_is_singular(&lastbf->list)) if (!list_is_singular(&lastbf->list))
list_cut_position(&bf_head, list_cut_position(&bf_head,
...@@ -2048,44 +2048,38 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) ...@@ -2048,44 +2048,38 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
{ {
int error = 0; int error = 0;
do { spin_lock_init(&sc->tx.txbuflock);
spin_lock_init(&sc->tx.txbuflock);
error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
"tx", nbufs, 1); "tx", nbufs, 1);
if (error != 0) { if (error != 0) {
DPRINTF(sc, ATH_DBG_FATAL, DPRINTF(sc, ATH_DBG_FATAL,
"Failed to allocate tx descriptors: %d\n", "Failed to allocate tx descriptors: %d\n", error);
error); goto err;
break; }
}
error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
"beacon", ATH_BCBUF, 1);
if (error != 0) {
DPRINTF(sc, ATH_DBG_FATAL,
"Failed to allocate beacon descriptors: %d\n",
error);
break;
}
} while (0); error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
"beacon", ATH_BCBUF, 1);
if (error != 0) {
DPRINTF(sc, ATH_DBG_FATAL,
"Failed to allocate beacon descriptors: %d\n", error);
goto err;
}
err:
if (error != 0) if (error != 0)
ath_tx_cleanup(sc); ath_tx_cleanup(sc);
return error; return error;
} }
int ath_tx_cleanup(struct ath_softc *sc) void ath_tx_cleanup(struct ath_softc *sc)
{ {
if (sc->beacon.bdma.dd_desc_len != 0) if (sc->beacon.bdma.dd_desc_len != 0)
ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf); ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
if (sc->tx.txdma.dd_desc_len != 0) if (sc->tx.txdma.dd_desc_len != 0)
ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf); ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
return 0;
} }
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
......
/*
* 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 <linux/kernel.h>
#include <linux/module.h>
MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards.");
MODULE_LICENSE("Dual BSD/GPL");
...@@ -16,7 +16,9 @@ ...@@ -16,7 +16,9 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "ath9k.h" #include <net/cfg80211.h>
#include <net/mac80211.h>
#include "regd.h"
#include "regd_common.h" #include "regd_common.h"
/* /*
...@@ -55,7 +57,7 @@ ...@@ -55,7 +57,7 @@
/* Can be used for: /* Can be used for:
* 0x60, 0x61, 0x62 */ * 0x60, 0x61, 0x62 */
static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = { static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
.n_reg_rules = 5, .n_reg_rules = 5,
.alpha2 = "99", .alpha2 = "99",
.reg_rules = { .reg_rules = {
...@@ -65,7 +67,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = { ...@@ -65,7 +67,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = {
}; };
/* Can be used by 0x63 and 0x65 */ /* Can be used by 0x63 and 0x65 */
static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = { static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
.n_reg_rules = 4, .n_reg_rules = 4,
.alpha2 = "99", .alpha2 = "99",
.reg_rules = { .reg_rules = {
...@@ -76,7 +78,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = { ...@@ -76,7 +78,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = {
}; };
/* Can be used by 0x64 only */ /* Can be used by 0x64 only */
static const struct ieee80211_regdomain ath9k_world_regdom_64 = { static const struct ieee80211_regdomain ath_world_regdom_64 = {
.n_reg_rules = 3, .n_reg_rules = 3,
.alpha2 = "99", .alpha2 = "99",
.reg_rules = { .reg_rules = {
...@@ -86,7 +88,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_64 = { ...@@ -86,7 +88,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_64 = {
}; };
/* Can be used by 0x66 and 0x69 */ /* Can be used by 0x66 and 0x69 */
static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = { static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
.n_reg_rules = 3, .n_reg_rules = 3,
.alpha2 = "99", .alpha2 = "99",
.reg_rules = { .reg_rules = {
...@@ -96,7 +98,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = { ...@@ -96,7 +98,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = {
}; };
/* Can be used by 0x67, 0x6A and 0x68 */ /* Can be used by 0x67, 0x6A and 0x68 */
static const struct ieee80211_regdomain ath9k_world_regdom_67_68_6A = { static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = {
.n_reg_rules = 4, .n_reg_rules = 4,
.alpha2 = "99", .alpha2 = "99",
.reg_rules = { .reg_rules = {
...@@ -112,49 +114,51 @@ static inline bool is_wwr_sku(u16 regd) ...@@ -112,49 +114,51 @@ static inline bool is_wwr_sku(u16 regd)
(regd == WORLD); (regd == WORLD);
} }
static u16 ath9k_regd_get_eepromRD(struct ath_hw *ah) static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
{ {
return ah->regulatory.current_rd & ~WORLDWIDE_ROAMING_FLAG; return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
} }
bool ath9k_is_world_regd(struct ath_hw *ah) bool ath_is_world_regd(struct ath_regulatory *reg)
{ {
return is_wwr_sku(ath9k_regd_get_eepromRD(ah)); return is_wwr_sku(ath_regd_get_eepromRD(reg));
} }
EXPORT_SYMBOL(ath_is_world_regd);
const struct ieee80211_regdomain *ath9k_default_world_regdomain(void) static const struct ieee80211_regdomain *ath_default_world_regdomain(void)
{ {
/* this is the most restrictive */ /* this is the most restrictive */
return &ath9k_world_regdom_64; return &ath_world_regdom_64;
} }
const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah) static const struct
ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
{ {
switch (ah->regulatory.regpair->regDmnEnum) { switch (reg->regpair->regDmnEnum) {
case 0x60: case 0x60:
case 0x61: case 0x61:
case 0x62: case 0x62:
return &ath9k_world_regdom_60_61_62; return &ath_world_regdom_60_61_62;
case 0x63: case 0x63:
case 0x65: case 0x65:
return &ath9k_world_regdom_63_65; return &ath_world_regdom_63_65;
case 0x64: case 0x64:
return &ath9k_world_regdom_64; return &ath_world_regdom_64;
case 0x66: case 0x66:
case 0x69: case 0x69:
return &ath9k_world_regdom_66_69; return &ath_world_regdom_66_69;
case 0x67: case 0x67:
case 0x68: case 0x68:
case 0x6A: case 0x6A:
return &ath9k_world_regdom_67_68_6A; return &ath_world_regdom_67_68_6A;
default: default:
WARN_ON(1); WARN_ON(1);
return ath9k_default_world_regdomain(); return ath_default_world_regdomain();
} }
} }
/* Frequency is one where radar detection is required */ /* Frequency is one where radar detection is required */
static bool ath9k_is_radar_freq(u16 center_freq) static bool ath_is_radar_freq(u16 center_freq)
{ {
return (center_freq >= 5260 && center_freq <= 5700); return (center_freq >= 5260 && center_freq <= 5700);
} }
...@@ -168,9 +172,9 @@ static bool ath9k_is_radar_freq(u16 center_freq) ...@@ -168,9 +172,9 @@ static bool ath9k_is_radar_freq(u16 center_freq)
* received a beacon on a channel we can enable active scan and * received a beacon on a channel we can enable active scan and
* adhoc (or beaconing). * adhoc (or beaconing).
*/ */
static void ath9k_reg_apply_beaconing_flags( static void
struct wiphy *wiphy, ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator) enum nl80211_reg_initiator initiator)
{ {
enum ieee80211_band band; enum ieee80211_band band;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
...@@ -191,7 +195,7 @@ static void ath9k_reg_apply_beaconing_flags( ...@@ -191,7 +195,7 @@ static void ath9k_reg_apply_beaconing_flags(
ch = &sband->channels[i]; ch = &sband->channels[i];
if (ath9k_is_radar_freq(ch->center_freq) || if (ath_is_radar_freq(ch->center_freq) ||
(ch->flags & IEEE80211_CHAN_RADAR)) (ch->flags & IEEE80211_CHAN_RADAR))
continue; continue;
...@@ -227,9 +231,9 @@ static void ath9k_reg_apply_beaconing_flags( ...@@ -227,9 +231,9 @@ static void ath9k_reg_apply_beaconing_flags(
} }
/* Allows active scan scan on Ch 12 and 13 */ /* Allows active scan scan on Ch 12 and 13 */
static void ath9k_reg_apply_active_scan_flags( static void
struct wiphy *wiphy, ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator) enum nl80211_reg_initiator initiator)
{ {
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
struct ieee80211_channel *ch; struct ieee80211_channel *ch;
...@@ -278,7 +282,7 @@ static void ath9k_reg_apply_active_scan_flags( ...@@ -278,7 +282,7 @@ static void ath9k_reg_apply_active_scan_flags(
} }
/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */ /* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) static void ath_reg_apply_radar_flags(struct wiphy *wiphy)
{ {
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
struct ieee80211_channel *ch; struct ieee80211_channel *ch;
...@@ -291,7 +295,7 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) ...@@ -291,7 +295,7 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy)
for (i = 0; i < sband->n_channels; i++) { for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i]; ch = &sband->channels[i];
if (!ath9k_is_radar_freq(ch->center_freq)) if (!ath_is_radar_freq(ch->center_freq))
continue; continue;
/* We always enable radar detection/DFS on this /* We always enable radar detection/DFS on this
* frequency range. Additionally we also apply on * frequency range. Additionally we also apply on
...@@ -310,37 +314,31 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) ...@@ -310,37 +314,31 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy)
} }
} }
void ath9k_reg_apply_world_flags(struct wiphy *wiphy, static void ath_reg_apply_world_flags(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator) enum nl80211_reg_initiator initiator,
struct ath_regulatory *reg)
{ {
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); switch (reg->regpair->regDmnEnum) {
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_hw *ah = sc->sc_ah;
switch (ah->regulatory.regpair->regDmnEnum) {
case 0x60: case 0x60:
case 0x63: case 0x63:
case 0x66: case 0x66:
case 0x67: case 0x67:
ath9k_reg_apply_beaconing_flags(wiphy, initiator); ath_reg_apply_beaconing_flags(wiphy, initiator);
break; break;
case 0x68: case 0x68:
ath9k_reg_apply_beaconing_flags(wiphy, initiator); ath_reg_apply_beaconing_flags(wiphy, initiator);
ath9k_reg_apply_active_scan_flags(wiphy, initiator); ath_reg_apply_active_scan_flags(wiphy, initiator);
break; break;
} }
return; return;
} }
int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) int ath_reg_notifier_apply(struct wiphy *wiphy,
struct regulatory_request *request,
struct ath_regulatory *reg)
{ {
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
/* We always apply this */ /* We always apply this */
ath9k_reg_apply_radar_flags(wiphy); ath_reg_apply_radar_flags(wiphy);
switch (request->initiator) { switch (request->initiator) {
case NL80211_REGDOM_SET_BY_DRIVER: case NL80211_REGDOM_SET_BY_DRIVER:
...@@ -348,17 +346,19 @@ int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) ...@@ -348,17 +346,19 @@ int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
case NL80211_REGDOM_SET_BY_USER: case NL80211_REGDOM_SET_BY_USER:
break; break;
case NL80211_REGDOM_SET_BY_COUNTRY_IE: case NL80211_REGDOM_SET_BY_COUNTRY_IE:
if (ath9k_is_world_regd(sc->sc_ah)) if (ath_is_world_regd(reg))
ath9k_reg_apply_world_flags(wiphy, request->initiator); ath_reg_apply_world_flags(wiphy, request->initiator,
reg);
break; break;
} }
return 0; return 0;
} }
EXPORT_SYMBOL(ath_reg_notifier_apply);
bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah) static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
{ {
u16 rd = ath9k_regd_get_eepromRD(ah); u16 rd = ath_regd_get_eepromRD(reg);
int i; int i;
if (rd & COUNTRY_ERD_FLAG) { if (rd & COUNTRY_ERD_FLAG) {
...@@ -373,14 +373,14 @@ bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah) ...@@ -373,14 +373,14 @@ bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah)
if (regDomainPairs[i].regDmnEnum == rd) if (regDomainPairs[i].regDmnEnum == rd)
return true; return true;
} }
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, printk(KERN_DEBUG
"invalid regulatory domain/country code 0x%x\n", rd); "ath: invalid regulatory domain/country code 0x%x\n", rd);
return false; return false;
} }
/* EEPROM country code to regpair mapping */ /* EEPROM country code to regpair mapping */
static struct country_code_to_enum_rd* static struct country_code_to_enum_rd*
ath9k_regd_find_country(u16 countryCode) ath_regd_find_country(u16 countryCode)
{ {
int i; int i;
...@@ -393,7 +393,7 @@ ath9k_regd_find_country(u16 countryCode) ...@@ -393,7 +393,7 @@ ath9k_regd_find_country(u16 countryCode)
/* EEPROM rd code to regpair mapping */ /* EEPROM rd code to regpair mapping */
static struct country_code_to_enum_rd* static struct country_code_to_enum_rd*
ath9k_regd_find_country_by_rd(int regdmn) ath_regd_find_country_by_rd(int regdmn)
{ {
int i; int i;
...@@ -405,13 +405,13 @@ ath9k_regd_find_country_by_rd(int regdmn) ...@@ -405,13 +405,13 @@ ath9k_regd_find_country_by_rd(int regdmn)
} }
/* Returns the map of the EEPROM set RD to a country code */ /* Returns the map of the EEPROM set RD to a country code */
static u16 ath9k_regd_get_default_country(u16 rd) static u16 ath_regd_get_default_country(u16 rd)
{ {
if (rd & COUNTRY_ERD_FLAG) { if (rd & COUNTRY_ERD_FLAG) {
struct country_code_to_enum_rd *country = NULL; struct country_code_to_enum_rd *country = NULL;
u16 cc = rd & ~COUNTRY_ERD_FLAG; u16 cc = rd & ~COUNTRY_ERD_FLAG;
country = ath9k_regd_find_country(cc); country = ath_regd_find_country(cc);
if (country != NULL) if (country != NULL)
return cc; return cc;
} }
...@@ -420,7 +420,7 @@ static u16 ath9k_regd_get_default_country(u16 rd) ...@@ -420,7 +420,7 @@ static u16 ath9k_regd_get_default_country(u16 rd)
} }
static struct reg_dmn_pair_mapping* static struct reg_dmn_pair_mapping*
ath9k_get_regpair(int regdmn) ath_get_regpair(int regdmn)
{ {
int i; int i;
...@@ -433,87 +433,120 @@ ath9k_get_regpair(int regdmn) ...@@ -433,87 +433,120 @@ ath9k_get_regpair(int regdmn)
return NULL; return NULL;
} }
int ath9k_regd_init(struct ath_hw *ah) static int
ath_regd_init_wiphy(struct ath_regulatory *reg,
struct wiphy *wiphy,
int (*reg_notifier)(struct wiphy *wiphy,
struct regulatory_request *request))
{
const struct ieee80211_regdomain *regd;
wiphy->reg_notifier = reg_notifier;
wiphy->strict_regulatory = true;
if (ath_is_world_regd(reg)) {
/*
* Anything applied here (prior to wiphy registration) gets
* saved on the wiphy orig_* parameters
*/
regd = ath_world_regdomain(reg);
wiphy->custom_regulatory = true;
wiphy->strict_regulatory = false;
} else {
/*
* This gets applied in the case of the absense of CRDA,
* it's our own custom world regulatory domain, similar to
* cfg80211's but we enable passive scanning.
*/
regd = ath_default_world_regdomain();
}
wiphy_apply_custom_regulatory(wiphy, regd);
ath_reg_apply_radar_flags(wiphy);
ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
return 0;
}
int
ath_regd_init(struct ath_regulatory *reg,
struct wiphy *wiphy,
int (*reg_notifier)(struct wiphy *wiphy,
struct regulatory_request *request))
{ {
struct country_code_to_enum_rd *country = NULL; struct country_code_to_enum_rd *country = NULL;
u16 regdmn; u16 regdmn;
if (!ath9k_regd_is_eeprom_valid(ah)) { if (!ath_regd_is_eeprom_valid(reg)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, printk(KERN_ERR "ath: Invalid EEPROM contents\n");
"Invalid EEPROM contents\n");
return -EINVAL; return -EINVAL;
} }
regdmn = ath9k_regd_get_eepromRD(ah); regdmn = ath_regd_get_eepromRD(reg);
ah->regulatory.country_code = ath9k_regd_get_default_country(regdmn); reg->country_code = ath_regd_get_default_country(regdmn);
if (ah->regulatory.country_code == CTRY_DEFAULT && if (reg->country_code == CTRY_DEFAULT &&
regdmn == CTRY_DEFAULT) regdmn == CTRY_DEFAULT)
ah->regulatory.country_code = CTRY_UNITED_STATES; reg->country_code = CTRY_UNITED_STATES;
if (ah->regulatory.country_code == CTRY_DEFAULT) { if (reg->country_code == CTRY_DEFAULT) {
country = NULL; country = NULL;
} else { } else {
country = ath9k_regd_find_country(ah->regulatory.country_code); country = ath_regd_find_country(reg->country_code);
if (country == NULL) { if (country == NULL) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, printk(KERN_DEBUG
"Country is NULL!!!!, cc= %d\n", "ath: Country is NULL!!!!, cc= %d\n",
ah->regulatory.country_code); reg->country_code);
return -EINVAL; return -EINVAL;
} else } else
regdmn = country->regDmnEnum; regdmn = country->regDmnEnum;
} }
ah->regulatory.regpair = ath9k_get_regpair(regdmn); reg->regpair = ath_get_regpair(regdmn);
if (!ah->regulatory.regpair) { if (!reg->regpair) {
DPRINTF(ah->ah_sc, ATH_DBG_FATAL, printk(KERN_DEBUG "ath: "
"No regulatory domain pair found, cannot continue\n"); "No regulatory domain pair found, cannot continue\n");
return -EINVAL; return -EINVAL;
} }
if (!country) if (!country)
country = ath9k_regd_find_country_by_rd(regdmn); country = ath_regd_find_country_by_rd(regdmn);
if (country) { if (country) {
ah->regulatory.alpha2[0] = country->isoName[0]; reg->alpha2[0] = country->isoName[0];
ah->regulatory.alpha2[1] = country->isoName[1]; reg->alpha2[1] = country->isoName[1];
} else { } else {
ah->regulatory.alpha2[0] = '0'; reg->alpha2[0] = '0';
ah->regulatory.alpha2[1] = '0'; reg->alpha2[1] = '0';
} }
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n",
"Country alpha2 being used: %c%c\n" reg->alpha2[0], reg->alpha2[1]);
"Regulatory.Regpair detected: 0x%0x\n", printk(KERN_DEBUG "ath: Regpair detected: 0x%0x\n",
ah->regulatory.alpha2[0], ah->regulatory.alpha2[1], reg->regpair->regDmnEnum);
ah->regulatory.regpair->regDmnEnum);
ath_regd_init_wiphy(reg, wiphy, reg_notifier);
return 0; return 0;
} }
EXPORT_SYMBOL(ath_regd_init);
u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan) u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
enum ieee80211_band band)
{ {
u32 ctl = NO_CTL; if (!reg->regpair ||
(reg->country_code == CTRY_DEFAULT &&
if (!ah->regulatory.regpair || is_wwr_sku(ath_regd_get_eepromRD(reg)))) {
(ah->regulatory.country_code == CTRY_DEFAULT && return SD_NO_CTL;
is_wwr_sku(ath9k_regd_get_eepromRD(ah)))) {
if (IS_CHAN_B(chan))
ctl = SD_NO_CTL | CTL_11B;
else if (IS_CHAN_G(chan))
ctl = SD_NO_CTL | CTL_11G;
else
ctl = SD_NO_CTL | CTL_11A;
return ctl;
} }
if (IS_CHAN_B(chan)) switch (band) {
ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11B; case IEEE80211_BAND_2GHZ:
else if (IS_CHAN_G(chan)) return reg->regpair->reg_2ghz_ctl;
ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11G; case IEEE80211_BAND_5GHZ:
else return reg->regpair->reg_5ghz_ctl;
ctl = ah->regulatory.regpair->reg_5ghz_ctl | CTL_11A; default:
return NO_CTL;
}
return ctl; return NO_CTL;
} }
EXPORT_SYMBOL(ath_regd_get_band_ctl);
...@@ -17,6 +17,25 @@ ...@@ -17,6 +17,25 @@
#ifndef REGD_H #ifndef REGD_H
#define REGD_H #define REGD_H
#include <linux/nl80211.h>
#include <net/cfg80211.h>
#define NO_CTL 0xff
#define SD_NO_CTL 0xE0
#define NO_CTL 0xff
#define CTL_MODE_M 7
#define CTL_11A 0
#define CTL_11B 1
#define CTL_11G 2
#define CTL_2GHT20 5
#define CTL_5GHT20 6
#define CTL_2GHT40 7
#define CTL_5GHT40 8
#define CTRY_DEBUG 0x1ff
#define CTRY_DEFAULT 0
#define COUNTRY_ERD_FLAG 0x8000 #define COUNTRY_ERD_FLAG 0x8000
#define WORLDWIDE_ROAMING_FLAG 0x4000 #define WORLDWIDE_ROAMING_FLAG 0x4000
...@@ -40,7 +59,7 @@ struct country_code_to_enum_rd { ...@@ -40,7 +59,7 @@ struct country_code_to_enum_rd {
const char *isoName; const char *isoName;
}; };
struct ath9k_regulatory { struct ath_regulatory {
char alpha2[2]; char alpha2[2];
u16 country_code; u16 country_code;
u16 max_power_level; u16 max_power_level;
...@@ -233,15 +252,14 @@ enum CountryCode { ...@@ -233,15 +252,14 @@ enum CountryCode {
CTRY_BELGIUM2 = 5002 CTRY_BELGIUM2 = 5002
}; };
bool ath9k_is_world_regd(struct ath_hw *ah); bool ath_is_world_regd(struct ath_regulatory *reg);
const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah); int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy,
const struct ieee80211_regdomain *ath9k_default_world_regdomain(void); int (*reg_notifier)(struct wiphy *wiphy,
void ath9k_reg_apply_world_flags(struct wiphy *wiphy, struct regulatory_request *request));
enum nl80211_reg_initiator initiator); u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
void ath9k_reg_apply_radar_flags(struct wiphy *wiphy); enum ieee80211_band band);
int ath9k_regd_init(struct ath_hw *ah); int ath_reg_notifier_apply(struct wiphy *wiphy,
bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah); struct regulatory_request *request,
u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan); struct ath_regulatory *reg);
int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
#endif #endif
...@@ -3,7 +3,6 @@ config B43 ...@@ -3,7 +3,6 @@ config B43
depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA
select SSB select SSB
select FW_LOADER select FW_LOADER
select HW_RANDOM
---help--- ---help---
b43 is a driver for the Broadcom 43xx series wireless devices. b43 is a driver for the Broadcom 43xx series wireless devices.
...@@ -106,6 +105,13 @@ config B43_RFKILL ...@@ -106,6 +105,13 @@ config B43_RFKILL
depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43) depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43)
default y default y
# This config option automatically enables b43 HW-RNG support,
# if the HW-RNG core is enabled.
config B43_HWRNG
bool
depends on B43 && (HW_RANDOM = y || HW_RANDOM = B43)
default y
config B43_DEBUG config B43_DEBUG
bool "Broadcom 43xx debugging" bool "Broadcom 43xx debugging"
depends on B43 depends on B43
......
...@@ -625,9 +625,11 @@ struct b43_wl { ...@@ -625,9 +625,11 @@ struct b43_wl {
/* Stats about the wireless interface */ /* Stats about the wireless interface */
struct ieee80211_low_level_stats ieee_stats; struct ieee80211_low_level_stats ieee_stats;
#ifdef CONFIG_B43_HWRNG
struct hwrng rng; struct hwrng rng;
u8 rng_initialized; bool rng_initialized;
char rng_name[30 + 1]; char rng_name[30 + 1];
#endif /* CONFIG_B43_HWRNG */
/* The RF-kill button */ /* The RF-kill button */
struct b43_rfkill rfkill; struct b43_rfkill rfkill;
...@@ -776,8 +778,8 @@ struct b43_wldev { ...@@ -776,8 +778,8 @@ struct b43_wldev {
/* Reason code of the last interrupt. */ /* Reason code of the last interrupt. */
u32 irq_reason; u32 irq_reason;
u32 dma_reason[6]; u32 dma_reason[6];
/* saved irq enable/disable state bitfield. */ /* The currently active generic-interrupt mask. */
u32 irq_savedstate; u32 irq_mask;
/* Link Quality calculation context. */ /* Link Quality calculation context. */
struct b43_noise_calculation noisecalc; struct b43_noise_calculation noisecalc;
/* if > 0 MAC is suspended. if == 0 MAC is enabled. */ /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
......
...@@ -673,32 +673,6 @@ static void b43_short_slot_timing_disable(struct b43_wldev *dev) ...@@ -673,32 +673,6 @@ static void b43_short_slot_timing_disable(struct b43_wldev *dev)
b43_set_slot_time(dev, 20); b43_set_slot_time(dev, 20);
} }
/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
* Returns the _previously_ enabled IRQ mask.
*/
static inline u32 b43_interrupt_enable(struct b43_wldev *dev, u32 mask)
{
u32 old_mask;
old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask | mask);
return old_mask;
}
/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
* Returns the _previously_ enabled IRQ mask.
*/
static inline u32 b43_interrupt_disable(struct b43_wldev *dev, u32 mask)
{
u32 old_mask;
old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
return old_mask;
}
/* Synchronize IRQ top- and bottom-half. /* Synchronize IRQ top- and bottom-half.
* IRQs must be masked before calling this. * IRQs must be masked before calling this.
* This must not be called with the irq_lock held. * This must not be called with the irq_lock held.
...@@ -1593,7 +1567,7 @@ static void handle_irq_beacon(struct b43_wldev *dev) ...@@ -1593,7 +1567,7 @@ static void handle_irq_beacon(struct b43_wldev *dev)
/* This is the bottom half of the asynchronous beacon update. */ /* This is the bottom half of the asynchronous beacon update. */
/* Ignore interrupt in the future. */ /* Ignore interrupt in the future. */
dev->irq_savedstate &= ~B43_IRQ_BEACON; dev->irq_mask &= ~B43_IRQ_BEACON;
cmd = b43_read32(dev, B43_MMIO_MACCMD); cmd = b43_read32(dev, B43_MMIO_MACCMD);
beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID); beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
...@@ -1602,7 +1576,7 @@ static void handle_irq_beacon(struct b43_wldev *dev) ...@@ -1602,7 +1576,7 @@ static void handle_irq_beacon(struct b43_wldev *dev)
/* Schedule interrupt manually, if busy. */ /* Schedule interrupt manually, if busy. */
if (beacon0_valid && beacon1_valid) { if (beacon0_valid && beacon1_valid) {
b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON); b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
dev->irq_savedstate |= B43_IRQ_BEACON; dev->irq_mask |= B43_IRQ_BEACON;
return; return;
} }
...@@ -1641,11 +1615,9 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) ...@@ -1641,11 +1615,9 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
spin_lock_irq(&wl->irq_lock); spin_lock_irq(&wl->irq_lock);
/* update beacon right away or defer to irq */ /* update beacon right away or defer to irq */
dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
handle_irq_beacon(dev); handle_irq_beacon(dev);
/* The handler might have updated the IRQ mask. */ /* The handler might have updated the IRQ mask. */
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
dev->irq_savedstate);
mmiowb(); mmiowb();
spin_unlock_irq(&wl->irq_lock); spin_unlock_irq(&wl->irq_lock);
} }
...@@ -1879,7 +1851,7 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev) ...@@ -1879,7 +1851,7 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
if (reason & B43_IRQ_TX_OK) if (reason & B43_IRQ_TX_OK)
handle_irq_transmit_status(dev); handle_irq_transmit_status(dev);
b43_interrupt_enable(dev, dev->irq_savedstate); b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
mmiowb(); mmiowb();
spin_unlock_irqrestore(&dev->wl->irq_lock, flags); spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
} }
...@@ -1893,7 +1865,9 @@ static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason) ...@@ -1893,7 +1865,9 @@ static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason)
b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]); b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);
b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]); b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);
b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]); b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);
/* Unused ring
b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]); b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
*/
} }
/* Interrupt handler top-half */ /* Interrupt handler top-half */
...@@ -1903,18 +1877,19 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) ...@@ -1903,18 +1877,19 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
struct b43_wldev *dev = dev_id; struct b43_wldev *dev = dev_id;
u32 reason; u32 reason;
if (!dev) B43_WARN_ON(!dev);
return IRQ_NONE;
spin_lock(&dev->wl->irq_lock); spin_lock(&dev->wl->irq_lock);
if (b43_status(dev) < B43_STAT_STARTED) if (unlikely(b43_status(dev) < B43_STAT_STARTED)) {
/* This can only happen on shared IRQ lines. */
goto out; goto out;
}
reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
if (reason == 0xffffffff) /* shared IRQ */ if (reason == 0xffffffff) /* shared IRQ */
goto out; goto out;
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
reason &= b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); reason &= dev->irq_mask;
if (!reason) if (!reason)
goto out; goto out;
...@@ -1928,16 +1903,18 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) ...@@ -1928,16 +1903,18 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
& 0x0001DC00; & 0x0001DC00;
dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON) dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON)
& 0x0000DC00; & 0x0000DC00;
/* Unused ring
dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON) dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON)
& 0x0000DC00; & 0x0000DC00;
*/
b43_interrupt_ack(dev, reason); b43_interrupt_ack(dev, reason);
/* disable all IRQs. They are enabled again in the bottom half. */ /* disable all IRQs. They are enabled again in the bottom half. */
dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
/* save the reason code and call our bottom half. */ /* save the reason code and call our bottom half. */
dev->irq_reason = reason; dev->irq_reason = reason;
tasklet_schedule(&dev->isr_tasklet); tasklet_schedule(&dev->isr_tasklet);
out: out:
mmiowb(); mmiowb();
spin_unlock(&dev->wl->irq_lock); spin_unlock(&dev->wl->irq_lock);
...@@ -2980,6 +2957,7 @@ static void b43_security_init(struct b43_wldev *dev) ...@@ -2980,6 +2957,7 @@ static void b43_security_init(struct b43_wldev *dev)
b43_clear_keys(dev); b43_clear_keys(dev);
} }
#ifdef CONFIG_B43_HWRNG
static int b43_rng_read(struct hwrng *rng, u32 *data) static int b43_rng_read(struct hwrng *rng, u32 *data)
{ {
struct b43_wl *wl = (struct b43_wl *)rng->priv; struct b43_wl *wl = (struct b43_wl *)rng->priv;
...@@ -2995,17 +2973,21 @@ static int b43_rng_read(struct hwrng *rng, u32 *data) ...@@ -2995,17 +2973,21 @@ static int b43_rng_read(struct hwrng *rng, u32 *data)
return (sizeof(u16)); return (sizeof(u16));
} }
#endif /* CONFIG_B43_HWRNG */
static void b43_rng_exit(struct b43_wl *wl) static void b43_rng_exit(struct b43_wl *wl)
{ {
#ifdef CONFIG_B43_HWRNG
if (wl->rng_initialized) if (wl->rng_initialized)
hwrng_unregister(&wl->rng); hwrng_unregister(&wl->rng);
#endif /* CONFIG_B43_HWRNG */
} }
static int b43_rng_init(struct b43_wl *wl) static int b43_rng_init(struct b43_wl *wl)
{ {
int err; int err = 0;
#ifdef CONFIG_B43_HWRNG
snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name), snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name),
"%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy)); "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy));
wl->rng.name = wl->rng_name; wl->rng.name = wl->rng_name;
...@@ -3018,6 +3000,7 @@ static int b43_rng_init(struct b43_wl *wl) ...@@ -3018,6 +3000,7 @@ static int b43_rng_init(struct b43_wl *wl)
b43err(wl, "Failed to register the random " b43err(wl, "Failed to register the random "
"number generator (%d)\n", err); "number generator (%d)\n", err);
} }
#endif /* CONFIG_B43_HWRNG */
return err; return err;
} }
...@@ -3793,7 +3776,7 @@ static void b43_wireless_core_stop(struct b43_wldev *dev) ...@@ -3793,7 +3776,7 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
* setting the status to INITIALIZED, as the interrupt handler * setting the status to INITIALIZED, as the interrupt handler
* won't care about IRQs then. */ * won't care about IRQs then. */
spin_lock_irqsave(&wl->irq_lock, flags); spin_lock_irqsave(&wl->irq_lock, flags);
dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */ b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */
spin_unlock_irqrestore(&wl->irq_lock, flags); spin_unlock_irqrestore(&wl->irq_lock, flags);
b43_synchronize_irq(dev); b43_synchronize_irq(dev);
...@@ -3834,7 +3817,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev) ...@@ -3834,7 +3817,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
/* Start data flow (TX/RX). */ /* Start data flow (TX/RX). */
b43_mac_enable(dev); b43_mac_enable(dev);
b43_interrupt_enable(dev, dev->irq_savedstate); b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
/* Start maintainance work */ /* Start maintainance work */
b43_periodic_tasks_setup(dev); b43_periodic_tasks_setup(dev);
...@@ -3997,9 +3980,9 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev) ...@@ -3997,9 +3980,9 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
/* IRQ related flags */ /* IRQ related flags */
dev->irq_reason = 0; dev->irq_reason = 0;
memset(dev->dma_reason, 0, sizeof(dev->dma_reason)); memset(dev->dma_reason, 0, sizeof(dev->dma_reason));
dev->irq_savedstate = B43_IRQ_MASKTEMPLATE; dev->irq_mask = B43_IRQ_MASKTEMPLATE;
if (b43_modparam_verbose < B43_VERBOSITY_DEBUG) if (b43_modparam_verbose < B43_VERBOSITY_DEBUG)
dev->irq_savedstate &= ~B43_IRQ_PHY_TXERR; dev->irq_mask &= ~B43_IRQ_PHY_TXERR;
dev->mac_suspended = 1; dev->mac_suspended = 1;
......
...@@ -139,7 +139,6 @@ void b43_rfkill_init(struct b43_wldev *dev) ...@@ -139,7 +139,6 @@ void b43_rfkill_init(struct b43_wldev *dev)
rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
rfk->rfkill->data = dev; rfk->rfkill->data = dev;
rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle; rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle;
rfk->rfkill->user_claim_unsupported = 1;
rfk->poll_dev = input_allocate_polled_device(); rfk->poll_dev = input_allocate_polled_device();
if (!rfk->poll_dev) { if (!rfk->poll_dev) {
......
...@@ -3,7 +3,6 @@ config B43LEGACY ...@@ -3,7 +3,6 @@ config B43LEGACY
depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA
select SSB select SSB
select FW_LOADER select FW_LOADER
select HW_RANDOM
---help--- ---help---
b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and
BCM4303) and early model 802.11g chips (BCM4306 Ver. 2) used in the BCM4303) and early model 802.11g chips (BCM4306 Ver. 2) used in the
...@@ -51,6 +50,13 @@ config B43LEGACY_RFKILL ...@@ -51,6 +50,13 @@ config B43LEGACY_RFKILL
depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43LEGACY) depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43LEGACY)
default y default y
# This config option automatically enables b43 HW-RNG support,
# if the HW-RNG core is enabled.
config B43LEGACY_HWRNG
bool
depends on B43LEGACY && (HW_RANDOM = y || HW_RANDOM = B43LEGACY)
default y
config B43LEGACY_DEBUG config B43LEGACY_DEBUG
bool "Broadcom 43xx-legacy debugging" bool "Broadcom 43xx-legacy debugging"
depends on B43LEGACY depends on B43LEGACY
......
...@@ -59,7 +59,8 @@ ...@@ -59,7 +59,8 @@
#define B43legacy_MMIO_XMITSTAT_1 0x174 #define B43legacy_MMIO_XMITSTAT_1 0x174
#define B43legacy_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ #define B43legacy_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */
#define B43legacy_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ #define B43legacy_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */
#define B43legacy_MMIO_TSF_CFP_REP 0x188
#define B43legacy_MMIO_TSF_CFP_START 0x18C
/* 32-bit DMA */ /* 32-bit DMA */
#define B43legacy_MMIO_DMA32_BASE0 0x200 #define B43legacy_MMIO_DMA32_BASE0 0x200
#define B43legacy_MMIO_DMA32_BASE1 0x220 #define B43legacy_MMIO_DMA32_BASE1 0x220
...@@ -258,7 +259,6 @@ ...@@ -258,7 +259,6 @@
#define B43legacy_IRQ_ALL 0xFFFFFFFF #define B43legacy_IRQ_ALL 0xFFFFFFFF
#define B43legacy_IRQ_MASKTEMPLATE (B43legacy_IRQ_MAC_SUSPENDED | \ #define B43legacy_IRQ_MASKTEMPLATE (B43legacy_IRQ_MAC_SUSPENDED | \
B43legacy_IRQ_BEACON | \
B43legacy_IRQ_TBTT_INDI | \ B43legacy_IRQ_TBTT_INDI | \
B43legacy_IRQ_ATIM_END | \ B43legacy_IRQ_ATIM_END | \
B43legacy_IRQ_PMQ | \ B43legacy_IRQ_PMQ | \
...@@ -596,9 +596,11 @@ struct b43legacy_wl { ...@@ -596,9 +596,11 @@ struct b43legacy_wl {
/* Stats about the wireless interface */ /* Stats about the wireless interface */
struct ieee80211_low_level_stats ieee_stats; struct ieee80211_low_level_stats ieee_stats;
#ifdef CONFIG_B43LEGACY_HWRNG
struct hwrng rng; struct hwrng rng;
u8 rng_initialized; u8 rng_initialized;
char rng_name[30 + 1]; char rng_name[30 + 1];
#endif
/* The RF-kill button */ /* The RF-kill button */
struct b43legacy_rfkill rfkill; struct b43legacy_rfkill rfkill;
...@@ -614,6 +616,8 @@ struct b43legacy_wl { ...@@ -614,6 +616,8 @@ struct b43legacy_wl {
struct sk_buff *current_beacon; struct sk_buff *current_beacon;
bool beacon0_uploaded; bool beacon0_uploaded;
bool beacon1_uploaded; bool beacon1_uploaded;
bool beacon_templates_virgin; /* Never wrote the templates? */
struct work_struct beacon_update_trigger;
}; };
/* Pointers to the firmware data and meta information about it. */ /* Pointers to the firmware data and meta information about it. */
......
...@@ -142,7 +142,6 @@ void b43legacy_rfkill_init(struct b43legacy_wldev *dev) ...@@ -142,7 +142,6 @@ void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
rfk->rfkill->data = dev; rfk->rfkill->data = dev;
rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle; rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle;
rfk->rfkill->user_claim_unsupported = 1;
rfk->poll_dev = input_allocate_polled_device(); rfk->poll_dev = input_allocate_polled_device();
if (!rfk->poll_dev) { if (!rfk->poll_dev) {
......
...@@ -274,7 +274,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, ...@@ -274,7 +274,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
/* PHY TX Control word */ /* PHY TX Control word */
if (rate_ofdm) if (rate_ofdm)
phy_ctl |= B43legacy_TX4_PHY_OFDM; phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM;
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL; phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL;
switch (info->antenna_sel_tx) { switch (info->antenna_sel_tx) {
......
...@@ -67,7 +67,9 @@ struct b43legacy_txhdr_fw3 { ...@@ -67,7 +67,9 @@ struct b43legacy_txhdr_fw3 {
#define B43legacy_TX4_EFT_RTSFBOFDM 0x0010 /* RTS/CTS fallback rate type */ #define B43legacy_TX4_EFT_RTSFBOFDM 0x0010 /* RTS/CTS fallback rate type */
/* PHY TX control word */ /* PHY TX control word */
#define B43legacy_TX4_PHY_OFDM 0x0001 /* Data frame rate type */ #define B43legacy_TX4_PHY_ENC 0x0003 /* Data frame encoding */
#define B43legacy_TX4_PHY_ENC_CCK 0x0000 /* CCK */
#define B43legacy_TX4_PHY_ENC_OFDM 0x0001 /* Data frame rate type */
#define B43legacy_TX4_PHY_SHORTPRMBL 0x0010 /* Use short preamble */ #define B43legacy_TX4_PHY_SHORTPRMBL 0x0010 /* Use short preamble */
#define B43legacy_TX4_PHY_ANT 0x03C0 /* Antenna selection */ #define B43legacy_TX4_PHY_ANT 0x03C0 /* Antenna selection */
#define B43legacy_TX4_PHY_ANT0 0x0000 /* Use antenna 0 */ #define B43legacy_TX4_PHY_ANT0 0x0000 /* Use antenna 0 */
......
...@@ -435,7 +435,7 @@ static int prism2_plx_probe(struct pci_dev *pdev, ...@@ -435,7 +435,7 @@ static int prism2_plx_probe(struct pci_dev *pdev,
unsigned long pccard_attr_mem; unsigned long pccard_attr_mem;
unsigned int pccard_attr_len; unsigned int pccard_attr_len;
void __iomem *attr_mem = NULL; void __iomem *attr_mem = NULL;
unsigned int cor_offset, cor_index; unsigned int cor_offset = 0, cor_index = 0;
u32 reg; u32 reg;
local_info_t *local = NULL; local_info_t *local = NULL;
struct net_device *dev = NULL; struct net_device *dev = NULL;
......
...@@ -719,7 +719,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, ...@@ -719,7 +719,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
IWL_DEBUG_RATE(priv, "LQ: ADD station %pm\n", IWL_DEBUG_RATE(priv, "LQ: ADD station %pm\n",
hdr->addr1); hdr->addr1);
sta_id = iwl3945_add_station(priv, sta_id = iwl3945_add_station(priv,
hdr->addr1, 0, CMD_ASYNC); hdr->addr1, 0, CMD_ASYNC, NULL);
} }
if (sta_id != IWL_INVALID_STATION) if (sta_id != IWL_INVALID_STATION)
rs_sta->ibss_sta_added = 1; rs_sta->ibss_sta_added = 1;
......
...@@ -162,7 +162,6 @@ struct iwl3945_frame { ...@@ -162,7 +162,6 @@ struct iwl3945_frame {
#define STATUS_TEMPERATURE 8 #define STATUS_TEMPERATURE 8
#define STATUS_GEO_CONFIGURED 9 #define STATUS_GEO_CONFIGURED 9
#define STATUS_EXIT_PENDING 10 #define STATUS_EXIT_PENDING 10
#define STATUS_IN_SUSPEND 11
#define STATUS_STATISTICS 12 #define STATUS_STATISTICS 12
#define STATUS_SCANNING 13 #define STATUS_SCANNING 13
#define STATUS_SCAN_ABORTING 14 #define STATUS_SCAN_ABORTING 14
...@@ -207,7 +206,8 @@ struct iwl3945_addsta_cmd; ...@@ -207,7 +206,8 @@ struct iwl3945_addsta_cmd;
extern int iwl3945_send_add_station(struct iwl_priv *priv, extern int iwl3945_send_add_station(struct iwl_priv *priv,
struct iwl3945_addsta_cmd *sta, u8 flags); struct iwl3945_addsta_cmd *sta, u8 flags);
extern u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *bssid, extern u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *bssid,
int is_ap, u8 flags); int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info);
extern void iwl3945_clear_stations_table(struct iwl_priv *priv);
extern int iwl3945_power_init_handle(struct iwl_priv *priv); extern int iwl3945_power_init_handle(struct iwl_priv *priv);
extern int iwl3945_eeprom_init(struct iwl_priv *priv); extern int iwl3945_eeprom_init(struct iwl_priv *priv);
extern int iwl3945_calc_db_from_ratio(int sig_ratio); extern int iwl3945_calc_db_from_ratio(int sig_ratio);
...@@ -278,6 +278,8 @@ extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv, ...@@ -278,6 +278,8 @@ extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb); struct iwl_rx_mem_buffer *rxb);
extern void iwl3945_disable_events(struct iwl_priv *priv); extern void iwl3945_disable_events(struct iwl_priv *priv);
extern int iwl4965_get_temperature(const struct iwl_priv *priv); extern int iwl4965_get_temperature(const struct iwl_priv *priv);
extern void iwl3945_post_associate(struct iwl_priv *priv);
extern void iwl3945_config_ap(struct iwl_priv *priv);
/** /**
* iwl3945_hw_find_station - Find station id for a given BSSID * iwl3945_hw_find_station - Find station id for a given BSSID
......
...@@ -2268,9 +2268,17 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) ...@@ -2268,9 +2268,17 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
cancel_work_sync(&priv->txpower_work); cancel_work_sync(&priv->txpower_work);
} }
static struct iwl_station_mgmt_ops iwl4965_station_mgmt = {
.add_station = iwl_add_station_flags,
.remove_station = iwl_remove_station,
.find_station = iwl_find_station,
.clear_station_table = iwl_clear_stations_table,
};
static struct iwl_hcmd_ops iwl4965_hcmd = { static struct iwl_hcmd_ops iwl4965_hcmd = {
.rxon_assoc = iwl4965_send_rxon_assoc, .rxon_assoc = iwl4965_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
.set_rxon_chain = iwl_set_rxon_chain,
}; };
static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
...@@ -2324,12 +2332,15 @@ static struct iwl_lib_ops iwl4965_lib = { ...@@ -2324,12 +2332,15 @@ static struct iwl_lib_ops iwl4965_lib = {
.send_tx_power = iwl4965_send_tx_power, .send_tx_power = iwl4965_send_tx_power,
.update_chain_flags = iwl_update_chain_flags, .update_chain_flags = iwl_update_chain_flags,
.temperature = iwl4965_temperature_calib, .temperature = iwl4965_temperature_calib,
.post_associate = iwl_post_associate,
.config_ap = iwl_config_ap,
}; };
static struct iwl_ops iwl4965_ops = { static struct iwl_ops iwl4965_ops = {
.lib = &iwl4965_lib, .lib = &iwl4965_lib,
.hcmd = &iwl4965_hcmd, .hcmd = &iwl4965_hcmd,
.utils = &iwl4965_hcmd_utils, .utils = &iwl4965_hcmd_utils,
.smgmt = &iwl4965_station_mgmt,
}; };
struct iwl_cfg iwl4965_agn_cfg = { struct iwl_cfg iwl4965_agn_cfg = {
...@@ -2350,8 +2361,6 @@ MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); ...@@ -2350,8 +2361,6 @@ MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX));
module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
module_param_named(disable, iwl4965_mod_params.disable, int, 0444);
MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444);
MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
module_param_named(debug, iwl4965_mod_params.debug, uint, 0444); module_param_named(debug, iwl4965_mod_params.debug, uint, 0444);
......
...@@ -678,7 +678,7 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv) ...@@ -678,7 +678,7 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv)
goto restart; goto restart;
} }
iwl_clear_stations_table(priv); priv->cfg->ops->smgmt->clear_station_table(priv);
ret = priv->cfg->ops->lib->alive_notify(priv); ret = priv->cfg->ops->lib->alive_notify(priv);
if (ret) { if (ret) {
IWL_WARN(priv, IWL_WARN(priv,
...@@ -1472,8 +1472,17 @@ int iwl5000_calc_rssi(struct iwl_priv *priv, ...@@ -1472,8 +1472,17 @@ int iwl5000_calc_rssi(struct iwl_priv *priv,
return max_rssi - agc - IWL49_RSSI_OFFSET; return max_rssi - agc - IWL49_RSSI_OFFSET;
} }
struct iwl_station_mgmt_ops iwl5000_station_mgmt = {
.add_station = iwl_add_station_flags,
.remove_station = iwl_remove_station,
.find_station = iwl_find_station,
.clear_station_table = iwl_clear_stations_table,
};
struct iwl_hcmd_ops iwl5000_hcmd = { struct iwl_hcmd_ops iwl5000_hcmd = {
.rxon_assoc = iwl5000_send_rxon_assoc, .rxon_assoc = iwl5000_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
.set_rxon_chain = iwl_set_rxon_chain,
}; };
struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
...@@ -1527,12 +1536,15 @@ struct iwl_lib_ops iwl5000_lib = { ...@@ -1527,12 +1536,15 @@ struct iwl_lib_ops iwl5000_lib = {
.calib_version = iwl5000_eeprom_calib_version, .calib_version = iwl5000_eeprom_calib_version,
.query_addr = iwl5000_eeprom_query_addr, .query_addr = iwl5000_eeprom_query_addr,
}, },
.post_associate = iwl_post_associate,
.config_ap = iwl_config_ap,
}; };
struct iwl_ops iwl5000_ops = { struct iwl_ops iwl5000_ops = {
.lib = &iwl5000_lib, .lib = &iwl5000_lib,
.hcmd = &iwl5000_hcmd, .hcmd = &iwl5000_hcmd,
.utils = &iwl5000_hcmd_utils, .utils = &iwl5000_hcmd_utils,
.smgmt = &iwl5000_station_mgmt,
}; };
struct iwl_mod_params iwl50_mod_params = { struct iwl_mod_params iwl50_mod_params = {
...@@ -1643,9 +1655,6 @@ struct iwl_cfg iwl5150_agn_cfg = { ...@@ -1643,9 +1655,6 @@ struct iwl_cfg iwl5150_agn_cfg = {
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));
module_param_named(disable50, iwl50_mod_params.disable, int, 0444);
MODULE_PARM_DESC(disable50,
"manually disable the 50XX radio (default 0 [radio on])");
module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444);
MODULE_PARM_DESC(swcrypto50, MODULE_PARM_DESC(swcrypto50,
"using software crypto engine (default 0 [hardware])\n"); "using software crypto engine (default 0 [hardware])\n");
......
...@@ -72,6 +72,7 @@ static struct iwl_ops iwl6000_ops = { ...@@ -72,6 +72,7 @@ static struct iwl_ops iwl6000_ops = {
.lib = &iwl5000_lib, .lib = &iwl5000_lib,
.hcmd = &iwl5000_hcmd, .hcmd = &iwl5000_hcmd,
.utils = &iwl6000_hcmd_utils, .utils = &iwl6000_hcmd_utils,
.smgmt = &iwl5000_station_mgmt,
}; };
struct iwl_cfg iwl6000_2ag_cfg = { struct iwl_cfg iwl6000_2ag_cfg = {
......
...@@ -2469,11 +2469,12 @@ struct iwl_ssid_ie { ...@@ -2469,11 +2469,12 @@ struct iwl_ssid_ie {
u8 ssid[32]; u8 ssid[32];
} __attribute__ ((packed)); } __attribute__ ((packed));
#define PROBE_OPTION_MAX_API1 0x4 #define PROBE_OPTION_MAX_3945 4
#define PROBE_OPTION_MAX 0x14 #define PROBE_OPTION_MAX 20
#define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF)
#define IWL_GOOD_CRC_TH cpu_to_le16(1) #define IWL_GOOD_CRC_TH cpu_to_le16(1)
#define IWL_MAX_SCAN_SIZE 1024 #define IWL_MAX_SCAN_SIZE 1024
#define IWL_MAX_PROBE_REQUEST 200
/* /*
* REPLY_SCAN_CMD = 0x80 (command) * REPLY_SCAN_CMD = 0x80 (command)
...@@ -2552,7 +2553,7 @@ struct iwl3945_scan_cmd { ...@@ -2552,7 +2553,7 @@ struct iwl3945_scan_cmd {
struct iwl3945_tx_cmd tx_cmd; struct iwl3945_tx_cmd tx_cmd;
/* For directed active scans (set to all-0s otherwise) */ /* For directed active scans (set to all-0s otherwise) */
struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_API1]; struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945];
/* /*
* Probe request frame, followed by channel list. * Probe request frame, followed by channel list.
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册