Commit 5eeaa2db authored by David S. Miller's avatar David S. Miller

Merge branch 'for-davem' of...

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
parents c5e90f56 c64557d6
......@@ -1358,16 +1358,19 @@ F: drivers/mtd/devices/block2mtd.c
BLUETOOTH DRIVERS
M: Marcel Holtmann <marcel@holtmann.org>
M: Gustavo F. Padovan <padovan@profusion.mobi>
L: linux-bluetooth@vger.kernel.org
W: http://www.bluez.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git
S: Maintained
F: drivers/bluetooth/
BLUETOOTH SUBSYSTEM
M: Marcel Holtmann <marcel@holtmann.org>
M: Gustavo F. Padovan <padovan@profusion.mobi>
L: linux-bluetooth@vger.kernel.org
W: http://www.bluez.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git
S: Maintained
F: net/bluetooth/
F: include/net/bluetooth/
......@@ -6458,8 +6461,7 @@ L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
S: Maintained
F: drivers/net/wireless/wl12xx/*
X: drivers/net/wireless/wl12xx/wl1271*
F: drivers/net/wireless/wl1251/*
WL1271 WIRELESS DRIVER
M: Luciano Coelho <luciano.coelho@nokia.com>
......
......@@ -117,8 +117,8 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
(event->data[2] == MODULE_ALREADY_UP)) ?
"Bring-up succeed" : "Bring-up failed");
if (event->length > 3)
priv->btmrvl_dev.dev_type = event->data[3];
if (event->length > 3 && event->data[3])
priv->btmrvl_dev.dev_type = HCI_AMP;
else
priv->btmrvl_dev.dev_type = HCI_BREDR;
......
......@@ -46,6 +46,9 @@ static const struct sdio_device_id btsdio_table[] = {
/* Generic Bluetooth Type-B SDIO device */
{ SDIO_DEVICE_CLASS(SDIO_CLASS_BT_B) },
/* Generic Bluetooth AMP controller */
{ SDIO_DEVICE_CLASS(SDIO_CLASS_BT_AMP) },
{ } /* Terminating entry */
};
......@@ -329,6 +332,11 @@ static int btsdio_probe(struct sdio_func *func,
hdev->bus = HCI_SDIO;
hdev->driver_data = data;
if (id->class == SDIO_CLASS_BT_AMP)
hdev->dev_type = HCI_AMP;
else
hdev->dev_type = HCI_BREDR;
data->hdev = hdev;
SET_HCIDEV_DEV(hdev, &func->dev);
......
......@@ -59,9 +59,15 @@ static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
/* Apple MacBookPro 7,1 */
{ USB_DEVICE(0x05ac, 0x8213) },
/* Apple iMac11,1 */
{ USB_DEVICE(0x05ac, 0x8215) },
/* Apple MacBookPro6,2 */
{ USB_DEVICE(0x05ac, 0x8218) },
/* AVM BlueFRITZ! USB v2.0 */
{ USB_DEVICE(0x057c, 0x3800) },
......
......@@ -101,7 +101,7 @@ static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
break;
case HCI_SCODATA_PKT:
hdev->stat.cmd_tx++;
hdev->stat.sco_tx++;
break;
}
}
......
......@@ -279,6 +279,7 @@ source "drivers/net/wireless/libertas/Kconfig"
source "drivers/net/wireless/orinoco/Kconfig"
source "drivers/net/wireless/p54/Kconfig"
source "drivers/net/wireless/rt2x00/Kconfig"
source "drivers/net/wireless/wl1251/Kconfig"
source "drivers/net/wireless/wl12xx/Kconfig"
source "drivers/net/wireless/zd1211rw/Kconfig"
......
......@@ -49,6 +49,7 @@ obj-$(CONFIG_ATH_COMMON) += ath/
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
obj-$(CONFIG_WL1251) += wl1251/
obj-$(CONFIG_WL12XX) += wl12xx/
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/
......
......@@ -1525,8 +1525,7 @@ static void at76_rx_tasklet(unsigned long param)
if (priv->device_unplugged) {
at76_dbg(DBG_DEVSTART, "device unplugged");
if (urb)
at76_dbg(DBG_DEVSTART, "urb status %d", urb->status);
at76_dbg(DBG_DEVSTART, "urb status %d", urb->status);
return;
}
......
......@@ -19,6 +19,7 @@
#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <linux/spinlock.h>
#include <net/mac80211.h>
/*
......@@ -42,6 +43,13 @@ struct ath_ani {
struct timer_list timer;
};
struct ath_cycle_counters {
u32 cycles;
u32 rx_busy;
u32 rx_frame;
u32 tx_frame;
};
enum ath_device_state {
ATH_HW_UNAVAILABLE,
ATH_HW_INITIALIZED,
......@@ -145,6 +153,12 @@ struct ath_common {
DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX);
enum ath_crypt_caps crypt_caps;
unsigned int clockrate;
spinlock_t cc_lock;
struct ath_cycle_counters cc_ani;
struct ath_cycle_counters cc_survey;
struct ath_regulatory regulatory;
const struct ath_ops *ops;
const struct ath_bus_ops *bus_ops;
......@@ -161,5 +175,7 @@ int ath_key_config(struct ath_common *common,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key);
bool ath_hw_keyreset(struct ath_common *common, u16 entry);
void ath_hw_cycle_counters_update(struct ath_common *common);
int32_t ath_hw_get_listen_time(struct ath_common *common);
#endif /* ATH_H */
......@@ -355,41 +355,28 @@ ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as)
/**
* ath5k_hw_ani_get_listen_time() - Calculate time spent listening
* ath5k_hw_ani_get_listen_time() - Update counters and return listening time
*
* Return an approximation of the time spent "listening" in milliseconds (ms)
* since the last call of this function by deducting the cycles spent
* transmitting and receiving from the total cycle count.
* Save profile count values for debugging/statistics and because we might want
* to use them later.
*
* We assume no one else clears these registers!
* since the last call of this function.
* Save a snapshot of the counter values for debugging/statistics.
*/
static int
ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as)
{
struct ath_common *common = ath5k_hw_common(ah);
int listen;
/* freeze */
ath5k_hw_reg_write(ah, AR5K_MIBC_FMC, AR5K_MIBC);
/* read */
as->pfc_cycles = ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE);
as->pfc_busy = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR);
as->pfc_tx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX);
as->pfc_rx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX);
/* clear */
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
/* un-freeze */
ath5k_hw_reg_write(ah, 0, AR5K_MIBC);
/* TODO: where does 44000 come from? (11g clock rate?) */
listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000;
if (as->pfc_cycles == 0 || listen < 0)
return 0;
spin_lock_bh(&common->cc_lock);
ath_hw_cycle_counters_update(common);
memcpy(&as->last_cc, &common->cc_ani, sizeof(as->last_cc));
/* clears common->cc_ani */
listen = ath_hw_get_listen_time(common);
spin_unlock_bh(&common->cc_lock);
return listen;
}
......
......@@ -75,10 +75,7 @@ struct ath5k_ani_state {
unsigned int cck_errors;
/* debug/statistics only: numbers from last ANI calibration */
unsigned int pfc_tx;
unsigned int pfc_rx;
unsigned int pfc_busy;
unsigned int pfc_cycles;
struct ath_cycle_counters last_cc;
unsigned int last_listen;
unsigned int last_ofdm_errors;
unsigned int last_cck_errors;
......
......@@ -1201,7 +1201,7 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
/* Clock rate related functions */
unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah);
void ath5k_hw_set_clockrate(struct ath5k_hw *ah);
/* Queue Control Unit, DFS Control Unit Functions */
int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
......
......@@ -62,6 +62,7 @@
#include "reg.h"
#include "debug.h"
#include "ani.h"
#include "../debug.h"
static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
......@@ -517,12 +518,14 @@ struct ath_vif_iter_data {
bool need_set_hw_addr;
bool found_active;
bool any_assoc;
enum nl80211_iftype opmode;
};
static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
struct ath_vif_iter_data *iter_data = data;
int i;
struct ath5k_vif *avf = (void *)vif->drv_priv;
if (iter_data->hw_macaddr)
for (i = 0; i < ETH_ALEN; i++)
......@@ -539,13 +542,32 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
iter_data->need_set_hw_addr = false;
if (!iter_data->any_assoc) {
struct ath5k_vif *avf = (void *)vif->drv_priv;
if (avf->assoc)
iter_data->any_assoc = true;
}
/* Calculate combined mode - when APs are active, operate in AP mode.
* Otherwise use the mode of the new interface. This can currently
* only deal with combinations of APs and STAs. Only one ad-hoc
* interfaces is allowed above.
*/
if (avf->opmode == NL80211_IFTYPE_AP)
iter_data->opmode = NL80211_IFTYPE_AP;
else
if (iter_data->opmode == NL80211_IFTYPE_UNSPECIFIED)
iter_data->opmode = avf->opmode;
}
void ath5k_update_bssid_mask(struct ath5k_softc *sc, struct ieee80211_vif *vif)
static void ath_do_set_opmode(struct ath5k_softc *sc)
{
struct ath5k_hw *ah = sc->ah;
ath5k_hw_set_opmode(ah, sc->opmode);
ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
sc->opmode, ath_opmode_to_string(sc->opmode));
}
void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
struct ieee80211_vif *vif)
{
struct ath_common *common = ath5k_hw_common(sc->ah);
struct ath_vif_iter_data iter_data;
......@@ -558,6 +580,7 @@ void ath5k_update_bssid_mask(struct ath5k_softc *sc, struct ieee80211_vif *vif)
memset(&iter_data.mask, 0xff, ETH_ALEN);
iter_data.found_active = false;
iter_data.need_set_hw_addr = true;
iter_data.opmode = NL80211_IFTYPE_UNSPECIFIED;
if (vif)
ath_vif_iter(&iter_data, vif->addr, vif);
......@@ -567,10 +590,18 @@ void ath5k_update_bssid_mask(struct ath5k_softc *sc, struct ieee80211_vif *vif)
&iter_data);
memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN);
sc->opmode = iter_data.opmode;
if (sc->opmode == NL80211_IFTYPE_UNSPECIFIED)
/* Nothing active, default to station mode */
sc->opmode = NL80211_IFTYPE_STATION;
ath_do_set_opmode(sc);
if (iter_data.need_set_hw_addr && iter_data.found_active)
ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac);
ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
if (ath5k_hw_hasbssidmask(sc->ah))
ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
}
static void
......@@ -582,15 +613,9 @@ ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif)
/* configure rx filter */
rfilt = sc->filter_flags;
ath5k_hw_set_rx_filter(ah, rfilt);
if (ath5k_hw_hasbssidmask(ah))
ath5k_update_bssid_mask(sc, vif);
/* configure operational mode */
ath5k_hw_set_opmode(ah, sc->opmode);
ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode);
ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
ath5k_update_bssid_mask_and_opmode(sc, vif);
}
static inline int
......@@ -2688,7 +2713,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
SET_IEEE80211_PERM_ADDR(hw, mac);
memcpy(&sc->lladdr, mac, ETH_ALEN);
/* All MAC address bits matter for ACKs */
ath5k_update_bssid_mask(sc, NULL);
ath5k_update_bssid_mask_and_opmode(sc, NULL);
regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
......@@ -2786,7 +2811,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
{
struct ath5k_softc *sc = hw->priv;
int ret;
struct ath5k_hw *ah = sc->ah;
struct ath5k_vif *avf = (void *)vif->drv_priv;
mutex_lock(&sc->lock);
......@@ -2850,18 +2874,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
sc->num_adhoc_vifs++;
}
/* Set combined mode - when APs are configured, operate in AP mode.
* Otherwise use the mode of the new interface. This can currently
* only deal with combinations of APs and STAs. Only one ad-hoc
* interfaces is allowed above.
*/
if (sc->num_ap_vifs)
sc->opmode = NL80211_IFTYPE_AP;
else
sc->opmode = vif->type;
ath5k_hw_set_opmode(ah, sc->opmode);
/* Any MAC address is fine, all others are included through the
* filter.
*/
......@@ -2905,7 +2917,7 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
else if (avf->opmode == NL80211_IFTYPE_ADHOC)
sc->num_adhoc_vifs--;
ath5k_update_bssid_mask(sc, NULL);
ath5k_update_bssid_mask_and_opmode(sc, NULL);
mutex_unlock(&sc->lock);
}
......@@ -3529,8 +3541,6 @@ ath5k_pci_probe(struct pci_dev *pdev,
sc->hw = hw;
sc->pdev = pdev;
ath5k_debug_init_device(sc);
/*
* Mark the device as detached to avoid processing
* interrupts until setup is complete.
......@@ -3638,6 +3648,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
}
}
ath5k_debug_init_device(sc);
/* ready to process interrupts */
__clear_bit(ATH_STAT_INVALID, sc->status);
......@@ -3724,8 +3735,6 @@ init_ath5k_pci(void)
{
int ret;
ath5k_debug_init();
ret = pci_register_driver(&ath5k_pci_driver);
if (ret) {
printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
......@@ -3739,8 +3748,6 @@ static void __exit
exit_ath5k_pci(void)
{
pci_unregister_driver(&ath5k_pci_driver);
ath5k_debug_finish();
}
module_init(init_ath5k_pci);
......
......@@ -60,6 +60,7 @@
#include "base.h"
#include "debug.h"
#include "../debug.h"
static unsigned int ath5k_debug;
module_param_named(debug, ath5k_debug, uint, 0);
......@@ -71,8 +72,6 @@ module_param_named(debug, ath5k_debug, uint, 0);
#include "reg.h"
#include "ani.h"
static struct dentry *ath5k_global_debugfs;
static int ath5k_debugfs_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
......@@ -520,9 +519,10 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
if (filt & AR5K_RX_FILTER_PHYERR_5211)
snprintf(buf+len, sizeof(buf)-len, " PHYERR-5211");
if (filt & AR5K_RX_FILTER_RADARERR_5211)
len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211\n");
else
len += snprintf(buf+len, sizeof(buf)-len, "\n");
len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211");
len += snprintf(buf+len, sizeof(buf)-len, "\nopmode: %s (%d)\n",
ath_opmode_to_string(sc->opmode), sc->opmode);
if (len > sizeof(buf))
len = sizeof(buf);
......@@ -715,20 +715,21 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf,
len += snprintf(buf+len, sizeof(buf)-len,
"beacon RSSI average:\t%d\n",
sc->ah->ah_beacon_rssi_avg.avg);
#define CC_PRINT(_struct, _field) \
_struct._field, \
_struct.cycles > 0 ? \
_struct._field*100/_struct.cycles : 0
len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n",
as->pfc_tx,
as->pfc_cycles > 0 ?
as->pfc_tx*100/as->pfc_cycles : 0);
CC_PRINT(as->last_cc, tx_frame));
len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n",
as->pfc_rx,
as->pfc_cycles > 0 ?
as->pfc_rx*100/as->pfc_cycles : 0);
CC_PRINT(as->last_cc, rx_frame));
len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n",
as->pfc_busy,
as->pfc_cycles > 0 ?
as->pfc_busy*100/as->pfc_cycles : 0);
CC_PRINT(as->last_cc, rx_busy));
#undef CC_PRINT
len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n",
as->pfc_cycles);
as->last_cc.cycles);
len += snprintf(buf+len, sizeof(buf)-len,
"listen time\t\t%d\tlast: %d\n",
as->listen_time, as->last_listen);
......@@ -879,21 +880,13 @@ static const struct file_operations fops_queue = {
};
/* init */
void
ath5k_debug_init(void)
{
ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL);
}
void
ath5k_debug_init_device(struct ath5k_softc *sc)
{
sc->debug.level = ath5k_debug;
sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
ath5k_global_debugfs);
sc->debug.debugfs_phydir = debugfs_create_dir("ath5k",
sc->hw->wiphy->debugfsdir);
sc->debug.debugfs_debug = debugfs_create_file("debug",
S_IWUSR | S_IRUSR,
......@@ -933,12 +926,6 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
&fops_queue);
}
void
ath5k_debug_finish(void)
{
debugfs_remove(ath5k_global_debugfs);
}
void
ath5k_debug_finish_device(struct ath5k_softc *sc)
{
......
......@@ -137,15 +137,9 @@ enum ath5k_debug_level {
__func__, __LINE__, ##__VA_ARGS__); \
} while (0)
void
ath5k_debug_init(void);
void
ath5k_debug_init_device(struct ath5k_softc *sc);
void
ath5k_debug_finish(void);
void
ath5k_debug_finish_device(struct ath5k_softc *sc);
......@@ -173,15 +167,9 @@ static inline void __attribute__ ((format (printf, 3, 4)))
ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
{}
static inline void
ath5k_debug_init(void) {}
static inline void
ath5k_debug_init_device(struct ath5k_softc *sc) {}
static inline void
ath5k_debug_finish(void) {}
static inline void
ath5k_debug_finish_device(struct ath5k_softc *sc) {}
......
......@@ -207,7 +207,8 @@ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
*/
unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
{
return usec * ath5k_hw_get_clockrate(ah);
struct ath_common *common = ath5k_hw_common(ah);
return usec * common->clockrate;
}
/**
......@@ -216,17 +217,19 @@ unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
*/
unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
{
return clock / ath5k_hw_get_clockrate(ah);
struct ath_common *common = ath5k_hw_common(ah);
return clock / common->clockrate;
}
/**
* ath5k_hw_get_clockrate - Get the clock rate for current mode
* ath5k_hw_set_clockrate - Set common->clockrate for the current channel
*
* @ah: The &struct ath5k_hw
*/
unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah)
void ath5k_hw_set_clockrate(struct ath5k_hw *ah)
{
struct ieee80211_channel *channel = ah->ah_current_channel;
struct ath_common *common = ath5k_hw_common(ah);
int clock;
if (channel->hw_value & CHANNEL_5GHZ)
......@@ -240,7 +243,7 @@ unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah)
if (channel->hw_value & CHANNEL_TURBO)
clock *= 2;
return clock;
common->clockrate = clock;
}
/**
......
......@@ -1093,6 +1093,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
ah->ah_current_channel = channel;
ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
ath5k_hw_set_clockrate(ah);
return 0;
}
......
......@@ -465,40 +465,6 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
}
static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
{
struct ath9k_channel *chan = ah->curchan;
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
u8 clockrate; /* in MHz */
if (!ah->curchan) /* should really check for CCK instead */
clockrate = ATH9K_CLOCK_RATE_CCK;
else if (conf->channel->band == IEEE80211_BAND_2GHZ)
clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
else if (IS_CHAN_A_FAST_CLOCK(ah, chan))
clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
else
clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
if (conf_is_ht40(conf))
return clockrate * 2;
return clockrate;
}
static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
{
int32_t listen_time;
int32_t clock_rate;
ath9k_hw_update_cycle_counters(ah);
clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;
listen_time = ah->listen_time / clock_rate;
ah->listen_time = 0;
return listen_time;
}
static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
{
struct ar5416AniState *aniState;
......@@ -667,7 +633,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
REGWRITE_BUFFER_FLUSH(ah);
}
static void ath9k_hw_ani_read_counters(struct ath_hw *ah)
static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ar5416AniState *aniState = &ah->curchan->ani;
......@@ -677,11 +643,13 @@ static void ath9k_hw_ani_read_counters(struct ath_hw *ah)
u32 phyCnt1, phyCnt2;
int32_t listenTime;
listenTime = ath9k_hw_ani_get_listen_time(ah);
if (listenTime < 0) {
ath_hw_cycle_counters_update(common);
listenTime = ath_hw_get_listen_time(common);
if (listenTime <= 0) {
ah->stats.ast_ani_lneg++;
ath9k_ani_restart(ah);
return;
return false;
}
if (!use_new_ani(ah)) {
......@@ -696,7 +664,7 @@ static void ath9k_hw_ani_read_counters(struct ath_hw *ah)
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
if (use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
if (phyCnt1 < ofdm_base) {
ath_print(common, ATH_DBG_ANI,
"phyCnt1 0x%x, resetting "
......@@ -715,7 +683,7 @@ static void ath9k_hw_ani_read_counters(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_ERR_MASK_2,
AR_PHY_ERR_CCK_TIMING);
}
return;
return false;
}
ofdmPhyErrCnt = phyCnt1 - ofdm_base;
......@@ -727,7 +695,7 @@ static void ath9k_hw_ani_read_counters(struct ath_hw *ah)
ah->stats.ast_ani_cckerrs +=
cckPhyErrCnt - aniState->cckPhyErrCount;
aniState->cckPhyErrCount = cckPhyErrCnt;
return true;
}
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
......@@ -743,7 +711,8 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
if (WARN_ON(!aniState))
return;
ath9k_hw_ani_read_counters(ah);
if (!ath9k_hw_ani_read_counters(ah))
return;
ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
aniState->listenTime;
......@@ -818,54 +787,6 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
void ath9k_hw_update_cycle_counters(struct ath_hw *ah)
{
struct ath_cycle_counters cc;
bool clear;
memcpy(&cc, &ah->cc, sizeof(cc));
/* freeze counters */
REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
ah->cc.cycles = REG_READ(ah, AR_CCCNT);
if (ah->cc.cycles < cc.cycles) {
clear = true;
goto skip;
}
ah->cc.rx_clear = REG_READ(ah, AR_RCCNT);
ah->cc.rx_frame = REG_READ(ah, AR_RFCNT);
ah->cc.tx_frame = REG_READ(ah, AR_TFCNT);
/* prevent wraparound */
if (ah->cc.cycles & BIT(31))
clear = true;
#define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field
CC_DELTA(cycles, AR_CCCNT);
CC_DELTA(rx_frame, AR_RFCNT);
CC_DELTA(rx_clear, AR_RCCNT);
CC_DELTA(tx_frame, AR_TFCNT);
#undef CC_DELTA
ah->listen_time += (ah->cc.cycles - cc.cycles) -
((ah->cc.rx_frame - cc.rx_frame) +
(ah->cc.tx_frame - cc.tx_frame));
skip:
if (clear) {
REG_WRITE(ah, AR_CCCNT, 0);
REG_WRITE(ah, AR_RFCNT, 0);
REG_WRITE(ah, AR_RCCNT, 0);
REG_WRITE(ah, AR_TFCNT, 0);
memset(&ah->cc, 0, sizeof(ah->cc));
}
/* unfreeze counters */
REG_WRITE(ah, AR_MIBC, 0);
}
/*
* Process a MIB interrupt. We may potentially be invoked because
* any of the MIB counters overflow/trigger so don't assume we're
......
......@@ -93,13 +93,6 @@ struct ath9k_mib_stats {
u32 beacons;
};
struct ath_cycle_counters {
u32 cycles;
u32 rx_frame;
u32 rx_clear;
u32 tx_frame;
};
/* INI default values for ANI registers */
struct ath9k_ani_default {
u16 m1ThreshLow;
......@@ -164,7 +157,6 @@ struct ar5416Stats {
void ath9k_enable_mib_counters(struct ath_hw *ah);
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
void ath9k_hw_update_cycle_counters(struct ath_hw *ah);
void ath9k_hw_ani_setup(struct ath_hw *ah);
void ath9k_hw_ani_init(struct ath_hw *ah);
int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
......
This diff is collapsed.
......@@ -16,7 +16,6 @@
#include "hw.h"
#include "ar9003_mac.h"
#include "ar9003_2p0_initvals.h"
#include "ar9003_2p2_initvals.h"
/* General hardware code for the AR9003 hadware family */
......@@ -32,79 +31,12 @@ static bool ar9003_hw_macversion_supported(u32 macversion)
return false;
}
/* AR9003 2.0 */
static void ar9003_2p0_hw_init_mode_regs(struct ath_hw *ah)
{
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar9300_2p0_mac_core,
ARRAY_SIZE(ar9300_2p0_mac_core), 2);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9300_2p0_mac_postamble,
ARRAY_SIZE(ar9300_2p0_mac_postamble), 5);
/* bb */
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9300_2p0_baseband_core,
ARRAY_SIZE(ar9300_2p0_baseband_core), 2);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9300_2p0_baseband_postamble,
ARRAY_SIZE(ar9300_2p0_baseband_postamble), 5);
/* radio */
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9300_2p0_radio_core,
ARRAY_SIZE(ar9300_2p0_radio_core), 2);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9300_2p0_radio_postamble,
ARRAY_SIZE(ar9300_2p0_radio_postamble), 5);
/* soc */
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9300_2p0_soc_preamble,
ARRAY_SIZE(ar9300_2p0_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9300_2p0_soc_postamble,
ARRAY_SIZE(ar9300_2p0_soc_postamble), 5);
/* rx/tx gain */
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_rx_gain_table_2p0,
ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), 2);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
5);
/* Load PCIE SERDES settings from INI */
/* Awake Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9300PciePhy_pll_on_clkreq_disable_L1_2p0,
ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p0),
2);
/* Sleep Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
ar9300PciePhy_clkreq_enable_L1_2p0,
ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p0),
2);
/* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesAdditional,
ar9300Modes_fast_clock_2p0,
ARRAY_SIZE(ar9300Modes_fast_clock_2p0),
3);
}
/* AR9003 2.2 */
static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah)
/*
* The AR9003 family uses a new INI format (pre, core, post
* arrays per subsystem). This provides support for the
* AR9003 2.2 chipsets.
*/
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
{
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
......@@ -174,57 +106,27 @@ static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah)
3);
}
/*
* The AR9003 family uses a new INI format (pre, core, post
* arrays per subsystem).
*/
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
{
if (AR_SREV_9300_20(ah))
ar9003_2p0_hw_init_mode_regs(ah);
else
ar9003_2p2_hw_init_mode_regs(ah);
}
static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
{
switch (ar9003_hw_get_tx_gain_idx(ah)) {
case 0:
default:
if (AR_SREV_9300_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
5);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
5);
break;
case 1:
if (AR_SREV_9300_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
5);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
5);
break;
case 2:
if (AR_SREV_9300_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_low_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_low_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
5);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_low_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
5);
break;
}
}
......@@ -234,28 +136,16 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
switch (ar9003_hw_get_rx_gain_idx(ah)) {
case 0:
default:
if (AR_SREV_9300_20(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_rx_gain_table_2p0,
ARRAY_SIZE(ar9300Common_rx_gain_table_2p0),
2);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_rx_gain_table_2p2,
ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
2);
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_rx_gain_table_2p2,
ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
2);
break;
case 1:
if (AR_SREV_9300_20(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_wo_xlna_rx_gain_table_2p0,
ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0),
2);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_wo_xlna_rx_gain_table_2p2,
ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
2);
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_wo_xlna_rx_gain_table_2p2,
ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
2);
break;
}
}
......
......@@ -1254,13 +1254,12 @@ void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
"** BB mode: BB_gen_controls=0x%08x **\n",
REG_READ(ah, AR_PHY_GEN_CTRL));
ath9k_hw_update_cycle_counters(ah);
#define PCT(_field) (ah->cc_delta._field * 100 / ah->cc_delta.cycles)
if (ah->cc_delta.cycles)
#define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles)
if (common->cc_survey.cycles)
ath_print(common, ATH_DBG_RESET,
"** BB busy times: rx_clear=%d%%, "
"rx_frame=%d%%, tx_frame=%d%% **\n",
PCT(rx_clear), PCT(rx_frame), PCT(tx_frame));
PCT(rx_busy), PCT(rx_frame), PCT(tx_frame));
ath_print(common, ATH_DBG_RESET,
"==== BB update: done ====\n\n");
......
......@@ -239,12 +239,11 @@ struct ath_buf {
struct sk_buff *bf_mpdu; /* enclosing frame structure */
void *bf_desc; /* virtual addr of desc */
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer */
dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
bool bf_stale;
bool bf_tx_aborted;
u16 bf_flags;
struct ath_buf_state bf_state;
dma_addr_t bf_dmacontext;
struct ath_wiphy *aphy;
};
......@@ -593,6 +592,8 @@ struct ath_softc {
struct delayed_work wiphy_work;
unsigned long wiphy_scheduler_int;
int wiphy_scheduler_index;
struct survey_info *cur_survey;
struct survey_info survey[ATH9K_NUM_CHANNELS];
struct tasklet_struct intr_tq;
struct tasklet_struct bcon_tasklet;
......@@ -621,8 +622,6 @@ struct ath_softc {
struct ath_rx rx;
struct ath_tx tx;
struct ath_beacon beacon;
const struct ath_rate_table *cur_rate_table;
enum wireless_mode cur_rate_mode;
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
struct ath_led radio_led;
......
......@@ -136,9 +136,10 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
bf = avp->av_bcbuf;
skb = bf->bf_mpdu;
if (skb) {
dma_unmap_single(sc->dev, bf->bf_dmacontext,
dma_unmap_single(sc->dev, bf->bf_buf_addr,
skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
bf->bf_buf_addr = 0;
}
/* Get a new beacon from mac80211 */
......@@ -162,12 +163,12 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
}
bf->bf_buf_addr = bf->bf_dmacontext =
dma_map_single(sc->dev, skb->data,
skb->len, DMA_TO_DEVICE);
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
skb->len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
bf->bf_buf_addr = 0;
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error on beaconing\n");
return NULL;
......@@ -252,10 +253,11 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
bf = avp->av_bcbuf;
if (bf->bf_mpdu != NULL) {
skb = bf->bf_mpdu;
dma_unmap_single(sc->dev, bf->bf_dmacontext,
dma_unmap_single(sc->dev, bf->bf_buf_addr,
skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
bf->bf_buf_addr = 0;
}
/* NB: the beacon data buffer must be 32-bit aligned. */
......@@ -296,12 +298,12 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
avp->tsf_adjust = cpu_to_le64(0);
bf->bf_mpdu = skb;
bf->bf_buf_addr = bf->bf_dmacontext =
dma_map_single(sc->dev, skb->data,
skb->len, DMA_TO_DEVICE);
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
skb->len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
bf->bf_buf_addr = 0;
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error on beacon alloc\n");
return -ENOMEM;
......@@ -324,10 +326,11 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
bf = avp->av_bcbuf;
if (bf->bf_mpdu != NULL) {
struct sk_buff *skb = bf->bf_mpdu;
dma_unmap_single(sc->dev, bf->bf_dmacontext,
dma_unmap_single(sc->dev, bf->bf_buf_addr,
skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
bf->bf_buf_addr = 0;
}
list_add_tail(&bf->list, &sc->beacon.bbuf);
......
......@@ -378,95 +378,6 @@ static const struct file_operations fops_interrupt = {
.owner = THIS_MODULE
};
void ath_debug_stat_rc(struct ath_softc *sc, int final_rate)
{
struct ath_rc_stats *stats;
stats = &sc->debug.stats.rcstats[final_rate];
stats->success++;
}
void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per)
{
struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix];
stats->xretries += xretries;
stats->retries += retries;
stats->per = per;
}
static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char *buf;
unsigned int len = 0, max;
int i = 0;
ssize_t retval;
if (sc->cur_rate_table == NULL)
return 0;
max = 80 + sc->cur_rate_table->rate_cnt * 1024 + 1;
buf = kmalloc(max, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
len += sprintf(buf, "%6s %6s %6s "
"%10s %10s %10s %10s\n",
"HT", "MCS", "Rate",
"Success", "Retries", "XRetries", "PER");
for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
u32 ratekbps = sc->cur_rate_table->info[i].ratekbps;
struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i];
char mcs[5];
char htmode[5];
int used_mcs = 0, used_htmode = 0;
if (WLAN_RC_PHY_HT(sc->cur_rate_table->info[i].phy)) {
used_mcs = snprintf(mcs, 5, "%d",
sc->cur_rate_table->info[i].ratecode);
if (WLAN_RC_PHY_40(sc->cur_rate_table->info[i].phy))
used_htmode = snprintf(htmode, 5, "HT40");
else if (WLAN_RC_PHY_20(sc->cur_rate_table->info[i].phy))
used_htmode = snprintf(htmode, 5, "HT20");
else
used_htmode = snprintf(htmode, 5, "????");
}
mcs[used_mcs] = '\0';
htmode[used_htmode] = '\0';
len += snprintf(buf + len, max - len,
"%6s %6s %3u.%d: "
"%10u %10u %10u %10u\n",
htmode,
mcs,
ratekbps / 1000,
(ratekbps % 1000) / 100,
stats->success,
stats->retries,
stats->xretries,
stats->per);
}
if (len > max)
len = max;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
static const struct file_operations fops_rcstat = {
.read = read_file_rcstat,
.open = ath9k_debugfs_open,
.owner = THIS_MODULE
};
static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
{
switch (state) {
......@@ -977,10 +888,6 @@ int ath9k_init_debug(struct ath_hw *ah)
sc, &fops_interrupt))
goto err;
if (!debugfs_create_file("rcstat", S_IRUSR, sc->debug.debugfs_phy,
sc, &fops_rcstat))
goto err;
if (!debugfs_create_file("wiphy", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_wiphy))
goto err;
......
......@@ -80,13 +80,6 @@ struct ath_interrupt_stats {
u32 bb_watchdog;
};
struct ath_rc_stats {
u32 success;
u32 retries;
u32 xretries;
u8 per;
};
/**
* struct ath_tx_stats - Statistics about TX
* @tx_pkts_all: No. of total frames transmitted, including ones that
......@@ -160,7 +153,6 @@ struct ath_rx_stats {
struct ath_stats {
struct ath_interrupt_stats istats;
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
struct ath_rx_stats rxstats;
};
......@@ -177,12 +169,9 @@ void ath9k_exit_debug(struct ath_hw *ah);
int ath9k_debug_create_root(void);
void ath9k_debug_remove_root(void);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_rc(struct ath_softc *sc, int final_rate);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf, struct ath_tx_status *ts);
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per);
#else
......@@ -209,11 +198,6 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
{
}
static inline void ath_debug_stat_rc(struct ath_softc *sc,
int final_rate)
{
}
static inline void ath_debug_stat_tx(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_buf *bf,
......@@ -226,11 +210,6 @@ static inline void ath_debug_stat_rx(struct ath_softc *sc,
{
}
static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per)
{
}
#endif /* CONFIG_ATH9K_DEBUGFS */
#endif /* DEBUG_H */
......@@ -566,7 +566,7 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
{
if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) {
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
priv->sbands[IEEE80211_BAND_2GHZ].channels =
ath9k_2ghz_channels;
priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
......@@ -577,7 +577,7 @@ static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
ARRAY_SIZE(ath9k_legacy_rates);
}
if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) {
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
......@@ -740,18 +740,18 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
sizeof(struct htc_frame_hdr) + 4;
if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&priv->sbands[IEEE80211_BAND_2GHZ];
if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&priv->sbands[IEEE80211_BAND_5GHZ];
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
setup_ht_cap(priv,
&priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
setup_ht_cap(priv,
&priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
}
......
......@@ -1454,6 +1454,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
FIF_PSPOLL | \
FIF_OTHER_BSS | \
FIF_BCN_PRBRESP_PROMISC | \
FIF_PROBE_REQ | \
FIF_FCSFAIL)
static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
......
......@@ -369,8 +369,7 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv)
| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
| ATH9K_RX_FILTER_MCAST;
/* If not a STA, enable processing of Probe Requests */
if (ah->opmode != NL80211_IFTYPE_STATION)
if (priv->rxfilter & FIF_PROBE_REQ)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
/*
......
......@@ -88,29 +88,32 @@ static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah)
/* Helper Functions */
/********************/
static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
static void ath9k_hw_set_clockrate(struct ath_hw *ah)
{
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
struct ath_common *common = ath9k_hw_common(ah);
unsigned int clockrate;
if (!ah->curchan) /* should really check for CCK instead */
return usecs *ATH9K_CLOCK_RATE_CCK;
if (conf->channel->band == IEEE80211_BAND_2GHZ)
return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM;
if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
return usecs * ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
clockrate = ATH9K_CLOCK_RATE_CCK;
else if (conf->channel->band == IEEE80211_BAND_2GHZ)
clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
else
return usecs * ATH9K_CLOCK_RATE_5GHZ_OFDM;
clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
if (conf_is_ht40(conf))
clockrate *= 2;
common->clockrate = clockrate;
}
static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
{
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
struct ath_common *common = ath9k_hw_common(ah);
if (conf_is_ht40(conf))
return ath9k_hw_mac_clks(ah, usecs) * 2;
else
return ath9k_hw_mac_clks(ah, usecs);
return usecs * common->clockrate;
}
bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
......@@ -1156,6 +1159,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
"Failed to set channel\n");
return false;
}
ath9k_hw_set_clockrate(ah);
ah->eep_ops->set_txpower(ah, chan,
ath9k_regd_get_ctl(regulatory, chan),
......@@ -1368,6 +1372,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (r)
return r;
ath9k_hw_set_clockrate(ah);
ENABLE_REGWRITE_BUFFER(ah);
for (i = 0; i < AR_NUM_DCU; i++)
......@@ -1794,37 +1800,11 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
return -EINVAL;
}
bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
if (eeval & AR5416_OPFLAGS_11A) {
set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
if (ah->config.ht_enable) {
if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
set_bit(ATH9K_MODE_11NA_HT20,
pCap->wireless_modes);
if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
set_bit(ATH9K_MODE_11NA_HT40PLUS,
pCap->wireless_modes);
set_bit(ATH9K_MODE_11NA_HT40MINUS,
pCap->wireless_modes);
}
}
}
if (eeval & AR5416_OPFLAGS_11A)
pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
if (eeval & AR5416_OPFLAGS_11G) {
set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
if (ah->config.ht_enable) {
if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
set_bit(ATH9K_MODE_11NG_HT20,
pCap->wireless_modes);
if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
set_bit(ATH9K_MODE_11NG_HT40PLUS,
pCap->wireless_modes);
set_bit(ATH9K_MODE_11NG_HT40MINUS,
pCap->wireless_modes);
}
}
}
if (eeval & AR5416_OPFLAGS_11G)
pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
/*
......
......@@ -61,6 +61,8 @@
#define ATH9K_RSSI_BAD -128
#define ATH9K_NUM_CHANNELS 38
/* Register read/write primitives */
#define REG_WRITE(_ah, _reg, _val) \
ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg))
......@@ -162,18 +164,6 @@ enum ath_ini_subsys {
ATH_INI_NUM_SPLIT,
};
enum wireless_mode {
ATH9K_MODE_11A = 0,
ATH9K_MODE_11G,
ATH9K_MODE_11NA_HT20,
ATH9K_MODE_11NG_HT20,
ATH9K_MODE_11NA_HT40PLUS,
ATH9K_MODE_11NA_HT40MINUS,
ATH9K_MODE_11NG_HT40PLUS,
ATH9K_MODE_11NG_HT40MINUS,
ATH9K_MODE_MAX,
};
enum ath9k_hw_caps {
ATH9K_HW_CAP_HT = BIT(0),
ATH9K_HW_CAP_RFSILENT = BIT(1),
......@@ -188,11 +178,12 @@ enum ath9k_hw_caps {
ATH9K_HW_CAP_SGI_20 = BIT(10),
ATH9K_HW_CAP_PAPRD = BIT(11),
ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12),
ATH9K_HW_CAP_2GHZ = BIT(13),
ATH9K_HW_CAP_5GHZ = BIT(14),
};
struct ath9k_hw_capabilities {
u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */
u16 total_queues;
u16 keycache_size;
u16 low_5ghz_chan, high_5ghz_chan;
......@@ -618,7 +609,7 @@ struct ath_hw {
struct ath9k_hw_version hw_version;
struct ath9k_ops_config config;
struct ath9k_hw_capabilities caps;
struct ath9k_channel channels[38];
struct ath9k_channel channels[ATH9K_NUM_CHANNELS];
struct ath9k_channel *curchan;
union {
......@@ -740,8 +731,6 @@ struct ath_hw {
int coarse_low[5];
int firpwr[5];
enum ath9k_ani_cmd ani_function;
struct ath_cycle_counters cc, cc_delta;
int32_t listen_time;
/* Bluetooth coexistance */
struct ath_btcoex_hw btcoex_hw;
......
......@@ -481,7 +481,11 @@ static int ath9k_init_channels_rates(struct ath_softc *sc)
{
void *channels;
if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) +
ARRAY_SIZE(ath9k_5ghz_chantable) !=
ATH9K_NUM_CHANNELS);
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
channels = kmemdup(ath9k_2ghz_chantable,
sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
if (!channels)
......@@ -496,7 +500,7 @@ static int ath9k_init_channels_rates(struct ath_softc *sc)
ARRAY_SIZE(ath9k_legacy_rates);
}
if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
channels = kmemdup(ath9k_5ghz_chantable,
sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
if (!channels) {
......@@ -677,17 +681,17 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->rate_control_algorithm = "ath9k_rate_control";
#endif
if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&sc->sbands[IEEE80211_BAND_2GHZ];
if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&sc->sbands[IEEE80211_BAND_5GHZ];
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
}
......
......@@ -18,36 +18,6 @@
#include "ath9k.h"
#include "btcoex.h"
static void ath_cache_conf_rate(struct ath_softc *sc,
struct ieee80211_conf *conf)
{
switch (conf->channel->band) {
case IEEE80211_BAND_2GHZ:
if (conf_is_ht20(conf))
sc->cur_rate_mode = ATH9K_MODE_11NG_HT20;
else if (conf_is_ht40_minus(conf))
sc->cur_rate_mode = ATH9K_MODE_11NG_HT40MINUS;
else if (conf_is_ht40_plus(conf))
sc->cur_rate_mode = ATH9K_MODE_11NG_HT40PLUS;
else
sc->cur_rate_mode = ATH9K_MODE_11G;
break;
case IEEE80211_BAND_5GHZ:
if (conf_is_ht20(conf))
sc->cur_rate_mode = ATH9K_MODE_11NA_HT20;
else if (conf_is_ht40_minus(conf))
sc->cur_rate_mode = ATH9K_MODE_11NA_HT40MINUS;
else if (conf_is_ht40_plus(conf))
sc->cur_rate_mode = ATH9K_MODE_11NA_HT40PLUS;
else
sc->cur_rate_mode = ATH9K_MODE_11A;
break;
default:
BUG_ON(1);
break;
}
}
static void ath_update_txpow(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
......@@ -121,6 +91,7 @@ bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
void ath9k_ps_wakeup(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
unsigned long flags;
spin_lock_irqsave(&sc->sc_pm_lock, flags);
......@@ -129,18 +100,33 @@ void ath9k_ps_wakeup(struct ath_softc *sc)
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
/*
* While the hardware is asleep, the cycle counters contain no
* useful data. Better clear them now so that they don't mess up
* survey data results.
*/
spin_lock(&common->cc_lock);
ath_hw_cycle_counters_update(common);
memset(&common->cc_survey, 0, sizeof(common->cc_survey));
spin_unlock(&common->cc_lock);
unlock:
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
}
void ath9k_ps_restore(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
unsigned long flags;
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if (--sc->ps_usecount != 0)
goto unlock;
spin_lock(&common->cc_lock);
ath_hw_cycle_counters_update(common);
spin_unlock(&common->cc_lock);
if (sc->ps_idle)
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
else if (sc->ps_enabled &&
......@@ -175,6 +161,45 @@ static void ath_start_ani(struct ath_common *common)
msecs_to_jiffies((u32)ah->config.ani_poll_interval));
}
static void ath_update_survey_nf(struct ath_softc *sc, int channel)
{
struct ath_hw *ah = sc->sc_ah;
struct ath9k_channel *chan = &ah->channels[channel];
struct survey_info *survey = &sc->survey[channel];
if (chan->noisefloor) {
survey->filled |= SURVEY_INFO_NOISE_DBM;
survey->noise = chan->noisefloor;
}
}
static void ath_update_survey_stats(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
int pos = ah->curchan - &ah->channels[0];
struct survey_info *survey = &sc->survey[pos];
struct ath_cycle_counters *cc = &common->cc_survey;
unsigned int div = common->clockrate * 1000;
if (ah->power_mode == ATH9K_PM_AWAKE)
ath_hw_cycle_counters_update(common);
if (cc->cycles > 0) {
survey->filled |= SURVEY_INFO_CHANNEL_TIME |
SURVEY_INFO_CHANNEL_TIME_BUSY |
SURVEY_INFO_CHANNEL_TIME_RX |
SURVEY_INFO_CHANNEL_TIME_TX;
survey->channel_time += cc->cycles / div;
survey->channel_time_busy += cc->rx_busy / div;
survey->channel_time_rx += cc->rx_frame / div;
survey->channel_time_tx += cc->tx_frame / div;
}
memset(cc, 0, sizeof(*cc));
ath_update_survey_nf(sc, pos);
}
/*
* Set/change channels. If the channel is really being changed, it's done
* by reseting the chip. To accomplish this we must first cleanup any pending
......@@ -251,7 +276,6 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
goto ps_restore;
}
ath_cache_conf_rate(sc, &hw->conf);
ath_update_txpow(sc);
ath9k_hw_set_interrupts(ah, ah->imask);
......@@ -399,6 +423,7 @@ void ath_ani_calibrate(unsigned long data)
bool aniflag = false;
unsigned int timestamp = jiffies_to_msecs(jiffies);
u32 cal_interval, short_cal_interval, long_cal_interval;
unsigned long flags;
if (ah->caldata && ah->caldata->nfcal_interference)
long_cal_interval = ATH_LONG_CALINTERVAL_INT;
......@@ -449,8 +474,12 @@ void ath_ani_calibrate(unsigned long data)
/* Skip all processing if there's nothing to do. */
if (longcal || shortcal || aniflag) {
/* Call ANI routine if necessary */
if (aniflag)
if (aniflag) {
spin_lock_irqsave(&common->cc_lock, flags);
ath9k_hw_ani_monitor(ah, ah->curchan);
ath_update_survey_stats(sc);
spin_unlock_irqrestore(&common->cc_lock, flags);
}
/* Perform calibration if necessary */
if (longcal || shortcal) {
......@@ -635,6 +664,7 @@ irqreturn_t ath_isr(int irq, void *dev)
struct ath_softc *sc = dev;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
enum ath9k_int status;
bool sched = false;
......@@ -684,7 +714,12 @@ irqreturn_t ath_isr(int irq, void *dev)
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
(status & ATH9K_INT_BB_WATCHDOG)) {
spin_lock(&common->cc_lock);
ath_hw_cycle_counters_update(common);
ar9003_hw_bb_watchdog_dbg_info(ah);
spin_unlock(&common->cc_lock);
goto chip_reset;
}
......@@ -713,7 +748,9 @@ irqreturn_t ath_isr(int irq, void *dev)
* it will clear whatever condition caused
* the interrupt.
*/
spin_lock(&common->cc_lock);
ath9k_hw_proc_mib_event(ah);
spin_unlock(&common->cc_lock);
ath9k_hw_set_interrupts(ah, ah->imask);
}
......@@ -945,8 +982,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
* that changes the channel so update any state that
* might change as a result.
*/
ath_cache_conf_rate(sc, &hw->conf);
ath_update_txpow(sc);
if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
......@@ -1153,8 +1188,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
if (ah->caps.hw_caps & ATH9K_HW_CAP_HT)
ah->imask |= ATH9K_INT_CST;
ath_cache_conf_rate(sc, &hw->conf);
sc->sc_flags &= ~SC_OP_INVALID;
/* Disable BMISS interrupt when we're not associated */
......@@ -1522,7 +1555,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &hw->conf;
bool disable_radio;
......@@ -1588,6 +1622,11 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
int pos = curchan->hw_value;
int old_pos = -1;
unsigned long flags;
if (ah->curchan)
old_pos = ah->curchan - &ah->channels[0];
aphy->chan_idx = pos;
aphy->chan_is_ht = conf_is_ht(conf);
......@@ -1615,12 +1654,45 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
ath_update_chainmask(sc, conf_is_ht(conf));
/* update survey stats for the old channel before switching */
spin_lock_irqsave(&common->cc_lock, flags);
ath_update_survey_stats(sc);
spin_unlock_irqrestore(&common->cc_lock, flags);
/*
* If the operating channel changes, change the survey in-use flags
* along with it.
* Reset the survey data for the new channel, unless we're switching
* back to the operating channel from an off-channel operation.
*/
if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) &&
sc->cur_survey != &sc->survey[pos]) {
if (sc->cur_survey)
sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
sc->cur_survey = &sc->survey[pos];
memset(sc->cur_survey, 0, sizeof(struct survey_info));
sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
} else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
memset(&sc->survey[pos], 0, sizeof(struct survey_info));
}
if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
ath_print(common, ATH_DBG_FATAL,
"Unable to set channel\n");
mutex_unlock(&sc->mutex);
return -EINVAL;
}
/*
* The most recent snapshot of channel->noisefloor for the old
* channel is only available after the hardware reset. Copy it to
* the survey stats now.
*/
if (old_pos >= 0)
ath_update_survey_nf(sc, old_pos);
}
skip_chan_change:
......@@ -1651,6 +1723,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
FIF_PSPOLL | \
FIF_OTHER_BSS | \
FIF_BCN_PRBRESP_PROMISC | \
FIF_PROBE_REQ | \
FIF_FCSFAIL)
/* FIXME: sc->sc_full_reset ? */
......@@ -1990,9 +2063,15 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ieee80211_supported_band *sband;
struct ath9k_channel *chan;
struct ieee80211_channel *chan;
unsigned long flags;
int pos;
spin_lock_irqsave(&common->cc_lock, flags);
if (idx == 0)
ath_update_survey_stats(sc);
sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
if (sband && idx >= sband->n_channels) {
......@@ -2003,21 +2082,17 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
if (!sband)
sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];
if (!sband || idx >= sband->n_channels)
return -ENOENT;
survey->channel = &sband->channels[idx];
chan = &ah->channels[survey->channel->hw_value];
survey->filled = 0;
if (chan == ah->curchan)
survey->filled |= SURVEY_INFO_IN_USE;
if (chan->noisefloor) {
survey->filled |= SURVEY_INFO_NOISE_DBM;
survey->noise = chan->noisefloor;
if (!sband || idx >= sband->n_channels) {
spin_unlock_irqrestore(&common->cc_lock, flags);
return -ENOENT;
}
chan = &sband->channels[idx];
pos = chan->hw_value;
memcpy(survey, &sc->survey[pos], sizeof(*survey));
survey->channel = chan;
spin_unlock_irqrestore(&common->cc_lock, flags);
return 0;
}
......
......@@ -302,7 +302,7 @@ static const struct ath_rate_table ar5416_11ng_ratetable = {
[64] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
205100, 20, 20, 8, 64, 65, 65 }, /* 243 Mb */
[65] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
224700, 20, 20, 8, 64, 65, 65 }, /* 170 Mb */
224700, 20, 20, 8, 64, 65, 65 }, /* 270 Mb */
[66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
263100, 21, 21, 8, 66, 67, 67 }, /* 324 Mb */
[67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
......@@ -378,17 +378,6 @@ static const struct ath_rate_table ar5416_11g_ratetable = {
0, /* Phy rates allowed initially */
};
static const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX] = {
[ATH9K_MODE_11A] = &ar5416_11a_ratetable,
[ATH9K_MODE_11G] = &ar5416_11g_ratetable,
[ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable,
[ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable,
[ATH9K_MODE_11NA_HT40PLUS] = &ar5416_11na_ratetable,
[ATH9K_MODE_11NA_HT40MINUS] = &ar5416_11na_ratetable,
[ATH9K_MODE_11NG_HT40PLUS] = &ar5416_11ng_ratetable,
[ATH9K_MODE_11NG_HT40MINUS] = &ar5416_11ng_ratetable,
};
static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
struct ieee80211_tx_rate *rate);
......@@ -791,7 +780,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
*/
try_per_rate = 4;
rate_table = sc->cur_rate_table;
rate_table = ath_rc_priv->rate_table;
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
/*
......@@ -1026,6 +1015,16 @@ static bool ath_rc_update_per(struct ath_softc *sc,
return state_change;
}
static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
int xretries, int retries, u8 per)
{
struct ath_rc_stats *stats = &rc->rcstats[rix];
stats->xretries += xretries;
stats->retries += retries;
stats->per = per;
}
/* Update PER, RSSI and whatever else that the code thinks it is doing.
If you can make sense of all this, you really need to go out more. */
......@@ -1038,7 +1037,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
int rate;
u8 last_per;
bool state_change = false;
const struct ath_rate_table *rate_table = sc->cur_rate_table;
const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
int size = ath_rc_priv->rate_table_size;
if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
......@@ -1098,7 +1097,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
ath_rc_priv->per_down_time = now_msec;
}
ath_debug_stat_retries(sc, tx_rate, xretries, retries,
ath_debug_stat_retries(ath_rc_priv, tx_rate, xretries, retries,
ath_rc_priv->per[tx_rate]);
}
......@@ -1140,7 +1139,7 @@ static void ath_rc_tx_status(struct ath_softc *sc,
u8 flags;
u32 i = 0, rix;
rate_table = sc->cur_rate_table;
rate_table = ath_rc_priv->rate_table;
/*
* If the first rate is not the final index, there
......@@ -1190,39 +1189,23 @@ static void ath_rc_tx_status(struct ath_softc *sc,
static const
struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
enum ieee80211_band band,
bool is_ht,
bool is_cw_40)
bool is_ht)
{
int mode = 0;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
switch(band) {
case IEEE80211_BAND_2GHZ:
mode = ATH9K_MODE_11G;
if (is_ht)
mode = ATH9K_MODE_11NG_HT20;
if (is_cw_40)
mode = ATH9K_MODE_11NG_HT40PLUS;
break;
return &ar5416_11ng_ratetable;
return &ar5416_11g_ratetable;
case IEEE80211_BAND_5GHZ:
mode = ATH9K_MODE_11A;
if (is_ht)
mode = ATH9K_MODE_11NA_HT20;
if (is_cw_40)
mode = ATH9K_MODE_11NA_HT40PLUS;
break;
return &ar5416_11na_ratetable;
return &ar5416_11a_ratetable;
default:
ath_print(common, ATH_DBG_CONFIG, "Invalid band\n");
return NULL;
}
BUG_ON(mode >= ATH9K_MODE_MAX);
ath_print(common, ATH_DBG_CONFIG,
"Choosing rate table for mode: %d\n", mode);
sc->cur_rate_mode = mode;
return hw_rate_table[mode];
}
static void ath_rc_init(struct ath_softc *sc,
......@@ -1293,7 +1276,7 @@ static void ath_rc_init(struct ath_softc *sc,
ath_rc_priv->max_valid_rate = k;
ath_rc_sort_validrates(rate_table, ath_rc_priv);
ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
sc->cur_rate_table = rate_table;
ath_rc_priv->rate_table = rate_table;
ath_print(common, ATH_DBG_CONFIG,
"RC Initialized with capabilities: 0x%x\n",
......@@ -1340,6 +1323,15 @@ static bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an,
/* mac80211 Rate Control callbacks */
/***********************************/
static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
{
struct ath_rc_stats *stats;
stats = &rc->rcstats[final_rate];
stats->success++;
}
static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
......@@ -1375,6 +1367,12 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
return;
if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) {
tx_info->status.ampdu_ack_len =
(tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0);
tx_info->status.ampdu_len = 1;
}
/*
* If an underrun error is seen assume it as an excessive retry only
* if max frame trigger level has been reached (2 KB for singel stream,
......@@ -1413,8 +1411,9 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
}
}
ath_debug_stat_rc(sc, ath_rc_get_rateindex(sc->cur_rate_table,
&tx_info->status.rates[final_ts_idx]));
ath_debug_stat_rc(ath_rc_priv,
ath_rc_get_rateindex(ath_rc_priv->rate_table,
&tx_info->status.rates[final_ts_idx]));
}
static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
......@@ -1454,14 +1453,8 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
/* Choose rate table first */
if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) ||
(sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
rate_table = ath_choose_rate_table(sc, sband->band,
sta->ht_cap.ht_supported, is_cw40);
} else {
rate_table = hw_rate_table[sc->cur_rate_mode];
}
rate_table = ath_choose_rate_table(sc, sband->band,
sta->ht_cap.ht_supported);
ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi);
ath_rc_init(sc, priv_sta, sband, sta, rate_table);
......@@ -1501,8 +1494,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) {
rate_table = ath_choose_rate_table(sc, sband->band,
sta->ht_cap.ht_supported,
oper_cw40);
sta->ht_cap.ht_supported);
ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta,
oper_cw40, oper_sgi);
ath_rc_init(sc, priv_sta, sband, sta, rate_table);
......@@ -1510,11 +1502,98 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
"Operating HT Bandwidth changed to: %d\n",
sc->hw->conf.channel_type);
sc->cur_rate_table = hw_rate_table[sc->cur_rate_mode];
}
}
}
#ifdef CONFIG_ATH9K_DEBUGFS
static int ath9k_debugfs_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
}
static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_rate_priv *rc = file->private_data;
char *buf;
unsigned int len = 0, max;
int i = 0;
ssize_t retval;
if (rc->rate_table == NULL)
return 0;
max = 80 + rc->rate_table->rate_cnt * 1024 + 1;
buf = kmalloc(max, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
len += sprintf(buf, "%6s %6s %6s "
"%10s %10s %10s %10s\n",
"HT", "MCS", "Rate",
"Success", "Retries", "XRetries", "PER");
for (i = 0; i < rc->rate_table->rate_cnt; i++) {
u32 ratekbps = rc->rate_table->info[i].ratekbps;
struct ath_rc_stats *stats = &rc->rcstats[i];
char mcs[5];
char htmode[5];
int used_mcs = 0, used_htmode = 0;
if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) {
used_mcs = snprintf(mcs, 5, "%d",
rc->rate_table->info[i].ratecode);
if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy))
used_htmode = snprintf(htmode, 5, "HT40");
else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy))
used_htmode = snprintf(htmode, 5, "HT20");
else
used_htmode = snprintf(htmode, 5, "????");
}
mcs[used_mcs] = '\0';
htmode[used_htmode] = '\0';
len += snprintf(buf + len, max - len,
"%6s %6s %3u.%d: "
"%10u %10u %10u %10u\n",
htmode,
mcs,
ratekbps / 1000,
(ratekbps % 1000) / 100,
stats->success,
stats->retries,
stats->xretries,
stats->per);
}
if (len > max)
len = max;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
static const struct file_operations fops_rcstat = {
.read = read_file_rcstat,
.open = ath9k_debugfs_open,
.owner = THIS_MODULE
};
static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta,
struct dentry *dir)
{
struct ath_rate_priv *rc = priv_sta;
debugfs_create_file("rc_stats", S_IRUGO, dir, rc, &fops_rcstat);
}
#endif /* CONFIG_ATH9K_DEBUGFS */
static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
struct ath_wiphy *aphy = hw->priv;
......@@ -1561,6 +1640,9 @@ static struct rate_control_ops ath_rate_ops = {
.free = ath_rate_free,
.alloc_sta = ath_rate_alloc_sta,
.free_sta = ath_rate_free_sta,
#ifdef CONFIG_ATH9K_DEBUGFS
.add_sta_debugfs = ath_rate_add_sta_debugfs,
#endif
};
int ath_rate_control_register(void)
......
......@@ -135,20 +135,21 @@ enum {
/**
* struct ath_rate_table - Rate Control table
* @valid: valid for use in rate control
* @valid_single_stream: valid for use in rate control for
* single stream operation
* @phy: CCK/OFDM
* @rate_cnt: total number of rates for the given wireless mode
* @mcs_start: MCS rate index offset
* @rate_flags: Rate Control flags
* @phy: CCK/OFDM/HT20/HT40
* @ratekbps: rate in Kbits per second
* @user_ratekbps: user rate in Kbits per second
* @ratecode: rate that goes into HW descriptors
* @short_preamble: Mask for enabling short preamble in ratecode for CCK
* @dot11rate: value that goes into supported
* rates info element of MLME
* @ctrl_rate: Index of next lower basic rate, used for duration computation
* @max_4ms_framelen: maximum frame length(bytes) for tx duration
* @cw40index: Index of rates having 40MHz channel width
* @sgi_index: Index of rates having Short Guard Interval
* @ht_index: high throughput rates having 40MHz channel width and
* Short Guard Interval
* @probe_interval: interval for rate control to probe for other rates
* @rssi_reduce_interval: interval for rate control to reduce rssi
* @initial_ratemax: initial ratemax value
*/
struct ath_rate_table {
......@@ -175,6 +176,13 @@ struct ath_rateset {
u8 rs_rates[ATH_RATE_MAX];
};
struct ath_rc_stats {
u32 success;
u32 retries;
u32 xretries;
u8 per;
};
/**
* struct ath_rate_priv - Rate Control priv data
* @state: RC state
......@@ -211,6 +219,10 @@ struct ath_rate_priv {
struct ath_rateset neg_rates;
struct ath_rateset neg_ht_rates;
struct ath_rate_softc *asc;
const struct ath_rate_table *rate_table;
struct dentry *debugfs_rcstats;
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
};
#define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0)
......
......@@ -268,6 +268,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)
bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
bf->bf_buf_addr = 0;
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error() on RX init\n");
error = -ENOMEM;
......@@ -358,12 +359,12 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
bf->bf_buf_addr = 0;
ath_print(common, 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;
}
......@@ -393,6 +394,8 @@ void ath_rx_cleanup(struct ath_softc *sc)
common->rx_bufsize,
DMA_FROM_DEVICE);
dev_kfree_skb(skb);
bf->bf_buf_addr = 0;
bf->bf_mpdu = NULL;
}
}
......@@ -430,8 +433,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
| ATH9K_RX_FILTER_MCAST;
/* If not a STA, enable processing of Probe Requests */
if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
if (sc->rx.rxfilter & FIF_PROBE_REQ)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
/*
......@@ -1735,12 +1737,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
bf->bf_buf_addr))) {
dev_kfree_skb_any(requeue_skb);
bf->bf_mpdu = NULL;
bf->bf_buf_addr = 0;
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error() on RX\n");
ath_rx_send_to_mac80211(hw, sc, skb, rxs);
break;
}
bf->bf_dmacontext = bf->bf_buf_addr;
/*
* change the default rx antenna if rx diversity chooses the
......
......@@ -107,12 +107,6 @@
#define AR_RXCFG_DMASZ_256B 6
#define AR_RXCFG_DMASZ_512B 7
#define AR_MIBC 0x0040
#define AR_MIBC_COW 0x00000001
#define AR_MIBC_FMC 0x00000002
#define AR_MIBC_CMC 0x00000004
#define AR_MIBC_MCS 0x00000008
#define AR_TOPS 0x0044
#define AR_TOPS_MASK 0x0000FFFF
......@@ -859,9 +853,6 @@
#define AR_SREV_9300(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
#define AR_SREV_9300_20(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9300_20))
#define AR_SREV_9300_20_OR_LATER(_ah) \
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \
......@@ -1524,11 +1515,6 @@ enum {
#define AR_TPC_CHIRP 0x003f0000
#define AR_TPC_CHIRP_S 0x16
#define AR_TFCNT 0x80ec
#define AR_RFCNT 0x80f0
#define AR_RCCNT 0x80f4
#define AR_CCCNT 0x80f8
#define AR_QUIET1 0x80fc
#define AR_QUIET1_NEXT_QUIET_S 0
#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff
......
......@@ -294,7 +294,6 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
tbf->bf_buf_addr = bf->bf_buf_addr;
memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
tbf->bf_state = bf->bf_state;
tbf->bf_dmacontext = bf->bf_dmacontext;
return tbf;
}
......@@ -317,6 +316,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;
bool rc_update = true;
struct ieee80211_tx_rate rates[4];
int nframes;
skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
......@@ -325,6 +325,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
hw = bf->aphy->hw;
memcpy(rates, tx_info->control.rates, sizeof(rates));
nframes = bf->bf_nframes;
rcu_read_lock();
......@@ -341,7 +342,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
!bf->bf_stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head);
ath_tx_rc_status(bf, ts, 0, 0, false);
ath_tx_rc_status(bf, ts, 1, 0, false);
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
0, 0);
......@@ -446,6 +447,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
memcpy(tx_info->control.rates, rates, sizeof(rates));
bf->bf_nframes = nframes;
ath_tx_rc_status(bf, ts, nbad, txok, true);
rc_update = false;
} else {
......@@ -1637,17 +1639,16 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
bf->bf_mpdu = skb;
bf->bf_dmacontext = dma_map_single(sc->dev, skb->data,
skb->len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) {
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
skb->len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
bf->bf_mpdu = NULL;
bf->bf_buf_addr = 0;
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
"dma_mapping_error() on TX\n");
return -ENOMEM;
}
bf->bf_buf_addr = bf->bf_dmacontext;
bf->bf_tx_aborted = false;
return 0;
......@@ -1911,7 +1912,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
tx_flags |= ATH_TX_XRETRY;
}
dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
bf->bf_buf_addr = 0;
if (bf->bf_state.bfs_paprd) {
if (time_after(jiffies,
......@@ -1921,9 +1923,13 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
else
complete(&sc->paprd_complete);
} else {
ath_tx_complete(sc, skb, bf->aphy, tx_flags);
ath_debug_stat_tx(sc, txq, bf, ts);
ath_tx_complete(sc, skb, bf->aphy, tx_flags);
}
/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
* accidentally reference it later.
*/
bf->bf_mpdu = NULL;
/*
* Return the list of ath_buf of this mpdu to free queue
......@@ -1979,9 +1985,15 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
if (ts->ts_status & ATH9K_TXERR_FILT)
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc)
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
BUG_ON(nbad > bf->bf_nframes);
tx_info->status.ampdu_len = bf->bf_nframes;
tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
}
if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
(bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
if (ieee80211_is_data(hdr->frame_control)) {
......@@ -1991,8 +2003,6 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
if ((ts->ts_status & ATH9K_TXERR_XRETRY) ||
(ts->ts_status & ATH9K_TXERR_FIFO))
tx_info->pad[0] |= ATH_TX_INFO_XRETRY;
tx_info->status.ampdu_len = bf->bf_nframes;
tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
}
}
......@@ -2102,7 +2112,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
*/
if (ts.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(bf, &ts, 0, txok, true);
ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
}
if (bf_isampdu(bf))
......@@ -2220,7 +2230,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
if (!bf_isampdu(bf)) {
if (txs.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(bf, &txs, 0, txok, true);
ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
}
if (bf_isampdu(bf))
......
......@@ -576,6 +576,41 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
}
}
static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
{
__le16 fc;
if ((ms & AR9170_RX_STATUS_MPDU) == AR9170_RX_STATUS_MPDU_SINGLE) {
/*
* This frame is not part of an aMPDU.
* Therefore it is not subjected to any
* of the following content restrictions.
*/
return true;
}
/*
* "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts
* certain frame types can be part of an aMPDU.
*
* In order to keep the processing cost down, I opted for a
* stateless filter solely based on the frame control field.
*/
fc = ((struct ieee80211_hdr *)buf)->frame_control;
if (ieee80211_is_data_qos(fc) && ieee80211_is_data_present(fc))
return true;
if (ieee80211_is_ack(fc) || ieee80211_is_back(fc) ||
ieee80211_is_back_req(fc))
return true;
if (ieee80211_is_action(fc))
return true;
return false;
}
/*
* If the frame alignment is right (or the kernel has
* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
......@@ -594,24 +629,19 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
struct ieee80211_rx_status status;
struct sk_buff *skb;
int mpdu_len;
u8 mac_status;
if (!IS_STARTED(ar))
return;
if (unlikely(len < sizeof(*mac))) {
ar->rx_dropped++;
return;
}
if (unlikely(len < sizeof(*mac)))
goto drop;
mpdu_len = len - sizeof(*mac);
mac = (void *)(buf + mpdu_len);
if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) {
ar->rx_dropped++;
return;
}
switch (mac->status & AR9170_RX_STATUS_MPDU) {
mac_status = mac->status;
switch (mac_status & AR9170_RX_STATUS_MPDU) {
case AR9170_RX_STATUS_MPDU_FIRST:
/* Aggregated MPDUs start with an PLCP header */
if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) {
......@@ -638,8 +668,7 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
"is clipped.\n");
}
ar->rx_dropped++;
return;
goto drop;
}
break;
......@@ -659,8 +688,7 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
"is clipped.\n");
}
ar->rx_dropped++;
return;
goto drop;
}
case AR9170_RX_STATUS_MPDU_MIDDLE:
......@@ -672,8 +700,7 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
wiphy_err(ar->hw->wiphy, "rx stream does not start "
"with a first_mpdu frame tag.\n");
ar->rx_dropped++;
return;
goto drop;
}
head = &ar->rx_plcp;
......@@ -696,16 +723,15 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
}
/* FC + DU + RA + FCS */
if (unlikely(mpdu_len < (2 + 2 + 6 + FCS_LEN))) {
ar->rx_dropped++;
return;
}
if (unlikely(mpdu_len < (2 + 2 + ETH_ALEN + FCS_LEN)))
goto drop;
memset(&status, 0, sizeof(status));
if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status))) {
ar->rx_dropped++;
return;
}
if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status)))
goto drop;
if (!carl9170_ampdu_check(ar, buf, mac_status))
goto drop;
if (phy)
carl9170_rx_phy_status(ar, phy, &status);
......@@ -713,12 +739,15 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
carl9170_ps_beacon(ar, buf, mpdu_len);
skb = carl9170_rx_copy_data(buf, mpdu_len);
if (likely(skb)) {
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
ieee80211_rx(ar->hw, skb);
} else {
ar->rx_dropped++;
}
if (!skb)
goto drop;
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
ieee80211_rx(ar->hw, skb);
return;
drop:
ar->rx_dropped++;
}
static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf,
......
......@@ -74,6 +74,9 @@
#define AR9170_RX_STATUS_MPDU_MIDDLE 0x30
#define AR9170_RX_STATUS_MPDU_LAST 0x10
#define AR9170_RX_STATUS_CONT_AGGR 0x40
#define AR9170_RX_STATUS_TOTAL_ERROR 0x80
#define AR9170_RX_ERROR_RXTO 0x01
#define AR9170_RX_ERROR_OVERRUN 0x02
#define AR9170_RX_ERROR_DECRYPT 0x04
......@@ -81,7 +84,6 @@
#define AR9170_RX_ERROR_WRONG_RA 0x10
#define AR9170_RX_ERROR_PLCP 0x20
#define AR9170_RX_ERROR_MMIC 0x40
#define AR9170_RX_ERROR_FATAL 0x80
/* these are either-or */
#define AR9170_TX_MAC_PROT_RTS 0x0001
......@@ -329,13 +331,15 @@ struct _carl9170_tx_superframe {
#define CARL9170_TX_SUPERDESC_LEN 24
#define AR9170_TX_HWDESC_LEN 8
#define AR9170_TX_SUPERFRAME_LEN (CARL9170_TX_HWDESC_LEN + \
AR9170_TX_SUPERDESC_LEN)
#define CARL9170_TX_SUPERFRAME_LEN (CARL9170_TX_SUPERDESC_LEN + \
AR9170_TX_HWDESC_LEN)
struct ar9170_rx_head {
u8 plcp[12];
} __packed;
#define AR9170_RX_HEAD_LEN 12
struct ar9170_rx_phystatus {
union {
struct {
......@@ -350,12 +354,16 @@ struct ar9170_rx_phystatus {
u8 phy_err;
} __packed;
#define AR9170_RX_PHYSTATUS_LEN 20
struct ar9170_rx_macstatus {
u8 SAidx, DAidx;
u8 error;
u8 status;
} __packed;
#define AR9170_RX_MACSTATUS_LEN 4
struct ar9170_rx_frame_single {
struct ar9170_rx_head phy_head;
struct ieee80211_hdr i3e;
......
......@@ -30,3 +30,32 @@ void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
va_end(args);
}
EXPORT_SYMBOL(ath_print);
const char *ath_opmode_to_string(enum nl80211_iftype opmode)
{
switch (opmode) {
case NL80211_IFTYPE_UNSPECIFIED:
return "UNSPEC";
case NL80211_IFTYPE_ADHOC:
return "ADHOC";
case NL80211_IFTYPE_STATION:
return "STATION";
case NL80211_IFTYPE_AP:
return "AP";
case NL80211_IFTYPE_AP_VLAN:
return "AP-VLAN";
case NL80211_IFTYPE_WDS:
return "WDS";
case NL80211_IFTYPE_MONITOR:
return "MONITOR";
case NL80211_IFTYPE_MESH_POINT:
return "MESH";
case NL80211_IFTYPE_P2P_CLIENT:
return "P2P-CLIENT";
case NL80211_IFTYPE_P2P_GO:
return "P2P-GO";
default:
return "UNKNOWN";
}
}
EXPORT_SYMBOL(ath_opmode_to_string);
......@@ -77,4 +77,14 @@ ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
}
#endif /* CONFIG_ATH_DEBUG */
/** Returns string describing opmode, or NULL if unknown mode. */
#ifdef CONFIG_ATH_DEBUG
const char *ath_opmode_to_string(enum nl80211_iftype opmode);
#else
static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
{
return "UNKNOWN";
}
#endif
#endif /* ATH_DEBUG_H */
......@@ -124,3 +124,62 @@ void ath_hw_setbssidmask(struct ath_common *common)
REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
}
EXPORT_SYMBOL(ath_hw_setbssidmask);
/**
* ath_hw_cycle_counters_update - common function to update cycle counters
*
* @common: the ath_common struct for the device.
*
* This function is used to update all cycle counters in one place.
* It has to be called while holding common->cc_lock!
*/
void ath_hw_cycle_counters_update(struct ath_common *common)
{
u32 cycles, busy, rx, tx;
void *ah = common->ah;
/* freeze */
REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
/* read */
cycles = REG_READ(ah, AR_CCCNT);
busy = REG_READ(ah, AR_RCCNT);
rx = REG_READ(ah, AR_RFCNT);
tx = REG_READ(ah, AR_TFCNT);
/* clear */
REG_WRITE(ah, 0, AR_CCCNT);
REG_WRITE(ah, 0, AR_RFCNT);
REG_WRITE(ah, 0, AR_RCCNT);
REG_WRITE(ah, 0, AR_TFCNT);
/* unfreeze */
REG_WRITE(ah, 0, AR_MIBC);
/* update all cycle counters here */
common->cc_ani.cycles += cycles;
common->cc_ani.rx_busy += busy;
common->cc_ani.rx_frame += rx;
common->cc_ani.tx_frame += tx;
common->cc_survey.cycles += cycles;
common->cc_survey.rx_busy += busy;
common->cc_survey.rx_frame += rx;
common->cc_survey.tx_frame += tx;
}
EXPORT_SYMBOL(ath_hw_cycle_counters_update);
int32_t ath_hw_get_listen_time(struct ath_common *common)
{
struct ath_cycle_counters *cc = &common->cc_ani;
int32_t listen_time;
listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) /
(common->clockrate * 1000);
memset(cc, 0, sizeof(*cc));
return listen_time;
}
EXPORT_SYMBOL(ath_hw_get_listen_time);
......@@ -17,6 +17,12 @@
#ifndef ATH_REGISTERS_H
#define ATH_REGISTERS_H
#define AR_MIBC 0x0040
#define AR_MIBC_COW 0x00000001
#define AR_MIBC_FMC 0x00000002
#define AR_MIBC_CMC 0x00000004
#define AR_MIBC_MCS 0x00000008
/*
* BSSID mask registers. See ath_hw_set_bssid_mask()
* for detailed documentation about these registers.
......@@ -24,6 +30,11 @@
#define AR_BSSMSKL 0x80e0
#define AR_BSSMSKU 0x80e4
#define AR_TFCNT 0x80ec
#define AR_RFCNT 0x80f0
#define AR_RCCNT 0x80f4
#define AR_CCCNT 0x80f8
#define AR_KEYTABLE_0 0x8800
#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
#define AR_KEY_CACHE_SIZE 128
......
b43-y += main.o
b43-y += tables.o
b43-$(CONFIG_B43_NPHY) += tables_nphy.o
b43-$(CONFIG_B43_NPHY) += radio_2055.o
b43-$(CONFIG_B43_NPHY) += radio_2056.o
b43-y += phy_common.o
b43-y += phy_g.o
b43-y += phy_a.o
......
......@@ -2,6 +2,7 @@
#define LINUX_B43_PHY_COMMON_H_
#include <linux/types.h>
#include <linux/nl80211.h>
struct b43_wldev;
......@@ -250,8 +251,10 @@ struct b43_phy {
* check is needed. */
unsigned long next_txpwr_check_time;
/* current channel */
/* Current channel */
unsigned int channel;
u16 channel_freq;
enum nl80211_channel_type channel_type;
/* PHY TX errors counter. */
atomic_t txerr_cnt;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
Broadcom B43 wireless driver
IEEE 802.11n 2056 radio device data tables
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "b43.h"
#include "radio_2056.h"
#include "phy_common.h"
static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = {
};
const struct b43_nphy_channeltab_entry_rev3 *
b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
{
const struct b43_nphy_channeltab_entry_rev3 *e;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev3); i++) {
e = &(b43_nphy_channeltab_rev3[i]);
if (e->freq == freq)
return e;
}
return NULL;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -12,7 +12,7 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o
iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
iwlagn-objs += iwl-agn-tt.o
iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment