mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 01:31:44 +00:00
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
5eeaa2db16
@ -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);
|
||||
spin_lock_bh(&common->cc_lock);
|
||||
|
||||
/* TODO: where does 44000 come from? (11g clock rate?) */
|
||||
listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000;
|
||||
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);
|
||||
|
||||
if (as->pfc_cycles == 0 || listen < 0)
|
||||
return 0;
|
||||
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,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 @@ out:
|
||||
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)
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
|
||||
|
||||
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_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 @@ skip_chan_change:
|
||||
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
|
||||
|
@ -1,6 +1,8 @@
|
||||
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;
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "b43.h"
|
||||
#include "phy_n.h"
|
||||
#include "tables_nphy.h"
|
||||
#include "radio_2055.h"
|
||||
#include "radio_2056.h"
|
||||
#include "main.h"
|
||||
|
||||
struct nphy_txgains {
|
||||
@ -74,19 +76,11 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
|
||||
static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
|
||||
u16 value, u8 core);
|
||||
|
||||
static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec)
|
||||
static inline bool b43_channel_type_is_40mhz(
|
||||
enum nl80211_channel_type channel_type)
|
||||
{
|
||||
return !chanspec->channel && !chanspec->sideband &&
|
||||
!chanspec->b_width && !chanspec->b_freq;
|
||||
}
|
||||
|
||||
static inline bool b43_eq_chanspecs(struct b43_chanspec *chanspec1,
|
||||
struct b43_chanspec *chanspec2)
|
||||
{
|
||||
return (chanspec1->channel == chanspec2->channel &&
|
||||
chanspec1->sideband == chanspec2->sideband &&
|
||||
chanspec1->b_width == chanspec2->b_width &&
|
||||
chanspec1->b_freq == chanspec2->b_freq);
|
||||
return (channel_type == NL80211_CHAN_HT40MINUS ||
|
||||
channel_type == NL80211_CHAN_HT40PLUS);
|
||||
}
|
||||
|
||||
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
|
||||
@ -781,7 +775,7 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
|
||||
u8 channel = nphy->radio_chanspec.channel;
|
||||
u8 channel = dev->phy.channel;
|
||||
int tone[2] = { 57, 58 };
|
||||
u32 noise[2] = { 0x3FF, 0x3FF };
|
||||
|
||||
@ -855,9 +849,9 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
|
||||
gain[0] = 6;
|
||||
gain[1] = 6;
|
||||
} else {
|
||||
tmp = 40370 - 315 * nphy->radio_chanspec.channel;
|
||||
tmp = 40370 - 315 * dev->phy.channel;
|
||||
gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
|
||||
tmp = 23242 - 224 * nphy->radio_chanspec.channel;
|
||||
tmp = 23242 - 224 * dev->phy.channel;
|
||||
gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
|
||||
}
|
||||
} else {
|
||||
@ -2083,12 +2077,12 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
|
||||
u16 *rssical_phy_regs = NULL;
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
if (b43_empty_chanspec(&nphy->rssical_chanspec_2G))
|
||||
if (!nphy->rssical_chanspec_2G.center_freq)
|
||||
return;
|
||||
rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
|
||||
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
|
||||
} else {
|
||||
if (b43_empty_chanspec(&nphy->rssical_chanspec_5G))
|
||||
if (!nphy->rssical_chanspec_5G.center_freq)
|
||||
return;
|
||||
rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
|
||||
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
|
||||
@ -2544,8 +2538,9 @@ static void b43_nphy_save_cal(struct b43_wldev *dev)
|
||||
txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
|
||||
txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
|
||||
}
|
||||
*iqcal_chanspec = nphy->radio_chanspec;
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 8, table);
|
||||
iqcal_chanspec->center_freq = dev->phy.channel_freq;
|
||||
iqcal_chanspec->channel_type = dev->phy.channel_type;
|
||||
b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
|
||||
|
||||
if (nphy->hang_avoid)
|
||||
b43_nphy_stay_in_carrier_search(dev, 0);
|
||||
@ -2565,12 +2560,12 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev)
|
||||
struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
if (b43_empty_chanspec(&nphy->iqcal_chanspec_2G))
|
||||
if (!nphy->iqcal_chanspec_2G.center_freq)
|
||||
return;
|
||||
table = nphy->cal_cache.txcal_coeffs_2G;
|
||||
loft = &nphy->cal_cache.txcal_coeffs_2G[5];
|
||||
} else {
|
||||
if (b43_empty_chanspec(&nphy->iqcal_chanspec_5G))
|
||||
if (!nphy->iqcal_chanspec_5G.center_freq)
|
||||
return;
|
||||
table = nphy->cal_cache.txcal_coeffs_5G;
|
||||
loft = &nphy->cal_cache.txcal_coeffs_5G[5];
|
||||
@ -2815,7 +2810,10 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
|
||||
b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
|
||||
nphy->txiqlocal_bestc);
|
||||
nphy->txiqlocal_coeffsvalid = true;
|
||||
nphy->txiqlocal_chanspec = nphy->radio_chanspec;
|
||||
nphy->txiqlocal_chanspec.center_freq =
|
||||
dev->phy.channel_freq;
|
||||
nphy->txiqlocal_chanspec.channel_type =
|
||||
dev->phy.channel_type;
|
||||
} else {
|
||||
length = 11;
|
||||
if (dev->phy.rev < 3)
|
||||
@ -2851,7 +2849,8 @@ static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
|
||||
bool equal = true;
|
||||
|
||||
if (!nphy->txiqlocal_coeffsvalid ||
|
||||
b43_eq_chanspecs(&nphy->txiqlocal_chanspec, &nphy->radio_chanspec))
|
||||
nphy->txiqlocal_chanspec.center_freq != dev->phy.channel_freq ||
|
||||
nphy->txiqlocal_chanspec.channel_type != dev->phy.channel_type)
|
||||
return;
|
||||
|
||||
b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
|
||||
@ -3257,11 +3256,9 @@ int b43_phy_initn(struct b43_wldev *dev)
|
||||
do_rssi_cal = false;
|
||||
if (phy->rev >= 3) {
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
|
||||
do_rssi_cal =
|
||||
b43_empty_chanspec(&nphy->rssical_chanspec_2G);
|
||||
do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;
|
||||
else
|
||||
do_rssi_cal =
|
||||
b43_empty_chanspec(&nphy->rssical_chanspec_5G);
|
||||
do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;
|
||||
|
||||
if (do_rssi_cal)
|
||||
b43_nphy_rssi_cal(dev);
|
||||
@ -3273,9 +3270,9 @@ int b43_phy_initn(struct b43_wldev *dev)
|
||||
|
||||
if (!((nphy->measure_hold & 0x6) != 0)) {
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
|
||||
do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_2G);
|
||||
do_cal = !nphy->iqcal_chanspec_2G.center_freq;
|
||||
else
|
||||
do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_5G);
|
||||
do_cal = !nphy->iqcal_chanspec_5G.center_freq;
|
||||
|
||||
if (nphy->mute)
|
||||
do_cal = false;
|
||||
@ -3323,24 +3320,25 @@ int b43_phy_initn(struct b43_wldev *dev)
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
|
||||
static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
|
||||
static void b43_nphy_channel_setup(struct b43_wldev *dev,
|
||||
const struct b43_phy_n_sfo_cfg *e,
|
||||
struct b43_chanspec chanspec)
|
||||
struct ieee80211_channel *new_channel)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
|
||||
u16 tmp;
|
||||
u16 old_band_5ghz;
|
||||
u32 tmp32;
|
||||
|
||||
tmp = b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
|
||||
if (chanspec.b_freq == 1 && tmp == 0) {
|
||||
old_band_5ghz =
|
||||
b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
|
||||
if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
|
||||
tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
|
||||
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
|
||||
b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
|
||||
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
|
||||
b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
|
||||
} else if (chanspec.b_freq == 1) {
|
||||
} else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
|
||||
b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
|
||||
tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
|
||||
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
|
||||
@ -3350,13 +3348,12 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
|
||||
|
||||
b43_chantab_phy_upload(dev, e);
|
||||
|
||||
|
||||
if (nphy->radio_chanspec.channel == 14) {
|
||||
if (new_channel->hw_value == 14) {
|
||||
b43_nphy_classifier(dev, 2, 0);
|
||||
b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);
|
||||
} else {
|
||||
b43_nphy_classifier(dev, 2, 2);
|
||||
if (chanspec.b_freq == 2)
|
||||
if (new_channel->band == IEEE80211_BAND_2GHZ)
|
||||
b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
|
||||
}
|
||||
|
||||
@ -3379,53 +3376,57 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
|
||||
static int b43_nphy_set_chanspec(struct b43_wldev *dev,
|
||||
struct b43_chanspec chanspec)
|
||||
static int b43_nphy_set_channel(struct b43_wldev *dev,
|
||||
struct ieee80211_channel *channel,
|
||||
enum nl80211_channel_type channel_type)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
|
||||
const struct b43_nphy_channeltab_entry_rev2 *tabent_r2;
|
||||
const struct b43_nphy_channeltab_entry_rev3 *tabent_r3;
|
||||
|
||||
u8 tmp;
|
||||
u8 channel = chanspec.channel;
|
||||
|
||||
if (dev->phy.rev >= 3) {
|
||||
/* TODO */
|
||||
tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
|
||||
channel->center_freq);
|
||||
tabent_r3 = NULL;
|
||||
if (!tabent_r3)
|
||||
return -ESRCH;
|
||||
} else {
|
||||
tabent_r2 = b43_nphy_get_chantabent_rev2(dev, channel);
|
||||
tabent_r2 = b43_nphy_get_chantabent_rev2(dev,
|
||||
channel->hw_value);
|
||||
if (!tabent_r2)
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
nphy->radio_chanspec = chanspec;
|
||||
/* Channel is set later in common code, but we need to set it on our
|
||||
own to let this function's subcalls work properly. */
|
||||
phy->channel = channel->hw_value;
|
||||
phy->channel_freq = channel->center_freq;
|
||||
|
||||
if (chanspec.b_width != nphy->b_width)
|
||||
; /* TODO: BMAC BW Set (chanspec.b_width) */
|
||||
if (b43_channel_type_is_40mhz(phy->channel_type) !=
|
||||
b43_channel_type_is_40mhz(channel_type))
|
||||
; /* TODO: BMAC BW Set (channel_type) */
|
||||
|
||||
/* TODO: use defines */
|
||||
if (chanspec.b_width == 3) {
|
||||
if (chanspec.sideband == 2)
|
||||
b43_phy_set(dev, B43_NPHY_RXCTL,
|
||||
B43_NPHY_RXCTL_BSELU20);
|
||||
else
|
||||
b43_phy_mask(dev, B43_NPHY_RXCTL,
|
||||
~B43_NPHY_RXCTL_BSELU20);
|
||||
}
|
||||
if (channel_type == NL80211_CHAN_HT40PLUS)
|
||||
b43_phy_set(dev, B43_NPHY_RXCTL,
|
||||
B43_NPHY_RXCTL_BSELU20);
|
||||
else if (channel_type == NL80211_CHAN_HT40MINUS)
|
||||
b43_phy_mask(dev, B43_NPHY_RXCTL,
|
||||
~B43_NPHY_RXCTL_BSELU20);
|
||||
|
||||
if (dev->phy.rev >= 3) {
|
||||
tmp = (chanspec.b_freq == 1) ? 4 : 0;
|
||||
tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
|
||||
b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
|
||||
/* TODO: PHY Radio2056 Setup (dev, tabent_r3); */
|
||||
b43_nphy_chanspec_setup(dev, &(tabent_r3->phy_regs), chanspec);
|
||||
b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
|
||||
} else {
|
||||
tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050;
|
||||
tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050;
|
||||
b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
|
||||
b43_radio_2055_setup(dev, tabent_r2);
|
||||
b43_nphy_chanspec_setup(dev, &(tabent_r2->phy_regs), chanspec);
|
||||
b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -3567,8 +3568,8 @@ static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
|
||||
static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
|
||||
unsigned int new_channel)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
struct b43_chanspec chanspec;
|
||||
struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
|
||||
enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
if ((new_channel < 1) || (new_channel > 14))
|
||||
@ -3578,10 +3579,7 @@ static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chanspec = nphy->radio_chanspec;
|
||||
chanspec.channel = new_channel;
|
||||
|
||||
return b43_nphy_set_chanspec(dev, chanspec);
|
||||
return b43_nphy_set_channel(dev, channel, channel_type);
|
||||
}
|
||||
|
||||
static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
|
||||
|
@ -714,223 +714,11 @@
|
||||
#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */
|
||||
#define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A)
|
||||
|
||||
|
||||
/* Broadcom 2055 radio registers */
|
||||
|
||||
#define B2055_GEN_SPARE 0x00 /* GEN spare */
|
||||
#define B2055_SP_PINPD 0x02 /* SP PIN PD */
|
||||
#define B2055_C1_SP_RSSI 0x03 /* SP RSSI Core 1 */
|
||||
#define B2055_C1_SP_PDMISC 0x04 /* SP PD MISC Core 1 */
|
||||
#define B2055_C2_SP_RSSI 0x05 /* SP RSSI Core 2 */
|
||||
#define B2055_C2_SP_PDMISC 0x06 /* SP PD MISC Core 2 */
|
||||
#define B2055_C1_SP_RXGC1 0x07 /* SP RX GC1 Core 1 */
|
||||
#define B2055_C1_SP_RXGC2 0x08 /* SP RX GC2 Core 1 */
|
||||
#define B2055_C2_SP_RXGC1 0x09 /* SP RX GC1 Core 2 */
|
||||
#define B2055_C2_SP_RXGC2 0x0A /* SP RX GC2 Core 2 */
|
||||
#define B2055_C1_SP_LPFBWSEL 0x0B /* SP LPF BW select Core 1 */
|
||||
#define B2055_C2_SP_LPFBWSEL 0x0C /* SP LPF BW select Core 2 */
|
||||
#define B2055_C1_SP_TXGC1 0x0D /* SP TX GC1 Core 1 */
|
||||
#define B2055_C1_SP_TXGC2 0x0E /* SP TX GC2 Core 1 */
|
||||
#define B2055_C2_SP_TXGC1 0x0F /* SP TX GC1 Core 2 */
|
||||
#define B2055_C2_SP_TXGC2 0x10 /* SP TX GC2 Core 2 */
|
||||
#define B2055_MASTER1 0x11 /* Master control 1 */
|
||||
#define B2055_MASTER2 0x12 /* Master control 2 */
|
||||
#define B2055_PD_LGEN 0x13 /* PD LGEN */
|
||||
#define B2055_PD_PLLTS 0x14 /* PD PLL TS */
|
||||
#define B2055_C1_PD_LGBUF 0x15 /* PD Core 1 LGBUF */
|
||||
#define B2055_C1_PD_TX 0x16 /* PD Core 1 TX */
|
||||
#define B2055_C1_PD_RXTX 0x17 /* PD Core 1 RXTX */
|
||||
#define B2055_C1_PD_RSSIMISC 0x18 /* PD Core 1 RSSI MISC */
|
||||
#define B2055_C2_PD_LGBUF 0x19 /* PD Core 2 LGBUF */
|
||||
#define B2055_C2_PD_TX 0x1A /* PD Core 2 TX */
|
||||
#define B2055_C2_PD_RXTX 0x1B /* PD Core 2 RXTX */
|
||||
#define B2055_C2_PD_RSSIMISC 0x1C /* PD Core 2 RSSI MISC */
|
||||
#define B2055_PWRDET_LGEN 0x1D /* PWRDET LGEN */
|
||||
#define B2055_C1_PWRDET_LGBUF 0x1E /* PWRDET LGBUF Core 1 */
|
||||
#define B2055_C1_PWRDET_RXTX 0x1F /* PWRDET RXTX Core 1 */
|
||||
#define B2055_C2_PWRDET_LGBUF 0x20 /* PWRDET LGBUF Core 2 */
|
||||
#define B2055_C2_PWRDET_RXTX 0x21 /* PWRDET RXTX Core 2 */
|
||||
#define B2055_RRCCAL_CS 0x22 /* RRCCAL Control spare */
|
||||
#define B2055_RRCCAL_NOPTSEL 0x23 /* RRCCAL N OPT SEL */
|
||||
#define B2055_CAL_MISC 0x24 /* CAL MISC */
|
||||
#define B2055_CAL_COUT 0x25 /* CAL Counter out */
|
||||
#define B2055_CAL_COUT2 0x26 /* CAL Counter out 2 */
|
||||
#define B2055_CAL_CVARCTL 0x27 /* CAL CVAR Control */
|
||||
#define B2055_CAL_RVARCTL 0x28 /* CAL RVAR Control */
|
||||
#define B2055_CAL_LPOCTL 0x29 /* CAL LPO Control */
|
||||
#define B2055_CAL_TS 0x2A /* CAL TS */
|
||||
#define B2055_CAL_RCCALRTS 0x2B /* CAL RCCAL READ TS */
|
||||
#define B2055_CAL_RCALRTS 0x2C /* CAL RCAL READ TS */
|
||||
#define B2055_PADDRV 0x2D /* PAD driver */
|
||||
#define B2055_XOCTL1 0x2E /* XO Control 1 */
|
||||
#define B2055_XOCTL2 0x2F /* XO Control 2 */
|
||||
#define B2055_XOREGUL 0x30 /* XO Regulator */
|
||||
#define B2055_XOMISC 0x31 /* XO misc */
|
||||
#define B2055_PLL_LFC1 0x32 /* PLL LF C1 */
|
||||
#define B2055_PLL_CALVTH 0x33 /* PLL CAL VTH */
|
||||
#define B2055_PLL_LFC2 0x34 /* PLL LF C2 */
|
||||
#define B2055_PLL_REF 0x35 /* PLL reference */
|
||||
#define B2055_PLL_LFR1 0x36 /* PLL LF R1 */
|
||||
#define B2055_PLL_PFDCP 0x37 /* PLL PFD CP */
|
||||
#define B2055_PLL_IDAC_CPOPAMP 0x38 /* PLL IDAC CPOPAMP */
|
||||
#define B2055_PLL_CPREG 0x39 /* PLL CP Regulator */
|
||||
#define B2055_PLL_RCAL 0x3A /* PLL RCAL */
|
||||
#define B2055_RF_PLLMOD0 0x3B /* RF PLL MOD0 */
|
||||
#define B2055_RF_PLLMOD1 0x3C /* RF PLL MOD1 */
|
||||
#define B2055_RF_MMDIDAC1 0x3D /* RF MMD IDAC 1 */
|
||||
#define B2055_RF_MMDIDAC0 0x3E /* RF MMD IDAC 0 */
|
||||
#define B2055_RF_MMDSP 0x3F /* RF MMD spare */
|
||||
#define B2055_VCO_CAL1 0x40 /* VCO cal 1 */
|
||||
#define B2055_VCO_CAL2 0x41 /* VCO cal 2 */
|
||||
#define B2055_VCO_CAL3 0x42 /* VCO cal 3 */
|
||||
#define B2055_VCO_CAL4 0x43 /* VCO cal 4 */
|
||||
#define B2055_VCO_CAL5 0x44 /* VCO cal 5 */
|
||||
#define B2055_VCO_CAL6 0x45 /* VCO cal 6 */
|
||||
#define B2055_VCO_CAL7 0x46 /* VCO cal 7 */
|
||||
#define B2055_VCO_CAL8 0x47 /* VCO cal 8 */
|
||||
#define B2055_VCO_CAL9 0x48 /* VCO cal 9 */
|
||||
#define B2055_VCO_CAL10 0x49 /* VCO cal 10 */
|
||||
#define B2055_VCO_CAL11 0x4A /* VCO cal 11 */
|
||||
#define B2055_VCO_CAL12 0x4B /* VCO cal 12 */
|
||||
#define B2055_VCO_CAL13 0x4C /* VCO cal 13 */
|
||||
#define B2055_VCO_CAL14 0x4D /* VCO cal 14 */
|
||||
#define B2055_VCO_CAL15 0x4E /* VCO cal 15 */
|
||||
#define B2055_VCO_CAL16 0x4F /* VCO cal 16 */
|
||||
#define B2055_VCO_KVCO 0x50 /* VCO KVCO */
|
||||
#define B2055_VCO_CAPTAIL 0x51 /* VCO CAP TAIL */
|
||||
#define B2055_VCO_IDACVCO 0x52 /* VCO IDAC VCO */
|
||||
#define B2055_VCO_REG 0x53 /* VCO Regulator */
|
||||
#define B2055_PLL_RFVTH 0x54 /* PLL RF VTH */
|
||||
#define B2055_LGBUF_CENBUF 0x55 /* LGBUF CEN BUF */
|
||||
#define B2055_LGEN_TUNE1 0x56 /* LGEN tune 1 */
|
||||
#define B2055_LGEN_TUNE2 0x57 /* LGEN tune 2 */
|
||||
#define B2055_LGEN_IDAC1 0x58 /* LGEN IDAC 1 */
|
||||
#define B2055_LGEN_IDAC2 0x59 /* LGEN IDAC 2 */
|
||||
#define B2055_LGEN_BIASC 0x5A /* LGEN BIAS counter */
|
||||
#define B2055_LGEN_BIASIDAC 0x5B /* LGEN BIAS IDAC */
|
||||
#define B2055_LGEN_RCAL 0x5C /* LGEN RCAL */
|
||||
#define B2055_LGEN_DIV 0x5D /* LGEN div */
|
||||
#define B2055_LGEN_SPARE2 0x5E /* LGEN spare 2 */
|
||||
#define B2055_C1_LGBUF_ATUNE 0x5F /* Core 1 LGBUF A tune */
|
||||
#define B2055_C1_LGBUF_GTUNE 0x60 /* Core 1 LGBUF G tune */
|
||||
#define B2055_C1_LGBUF_DIV 0x61 /* Core 1 LGBUF div */
|
||||
#define B2055_C1_LGBUF_AIDAC 0x62 /* Core 1 LGBUF A IDAC */
|
||||
#define B2055_C1_LGBUF_GIDAC 0x63 /* Core 1 LGBUF G IDAC */
|
||||
#define B2055_C1_LGBUF_IDACFO 0x64 /* Core 1 LGBUF IDAC filter override */
|
||||
#define B2055_C1_LGBUF_SPARE 0x65 /* Core 1 LGBUF spare */
|
||||
#define B2055_C1_RX_RFSPC1 0x66 /* Core 1 RX RF SPC1 */
|
||||
#define B2055_C1_RX_RFR1 0x67 /* Core 1 RX RF reg 1 */
|
||||
#define B2055_C1_RX_RFR2 0x68 /* Core 1 RX RF reg 2 */
|
||||
#define B2055_C1_RX_RFRCAL 0x69 /* Core 1 RX RF RCAL */
|
||||
#define B2055_C1_RX_BB_BLCMP 0x6A /* Core 1 RX Baseband BUFI LPF CMP */
|
||||
#define B2055_C1_RX_BB_LPF 0x6B /* Core 1 RX Baseband LPF */
|
||||
#define B2055_C1_RX_BB_MIDACHP 0x6C /* Core 1 RX Baseband MIDAC High-pass */
|
||||
#define B2055_C1_RX_BB_VGA1IDAC 0x6D /* Core 1 RX Baseband VGA1 IDAC */
|
||||
#define B2055_C1_RX_BB_VGA2IDAC 0x6E /* Core 1 RX Baseband VGA2 IDAC */
|
||||
#define B2055_C1_RX_BB_VGA3IDAC 0x6F /* Core 1 RX Baseband VGA3 IDAC */
|
||||
#define B2055_C1_RX_BB_BUFOCTL 0x70 /* Core 1 RX Baseband BUFO Control */
|
||||
#define B2055_C1_RX_BB_RCCALCTL 0x71 /* Core 1 RX Baseband RCCAL Control */
|
||||
#define B2055_C1_RX_BB_RSSICTL1 0x72 /* Core 1 RX Baseband RSSI Control 1 */
|
||||
#define B2055_C1_RX_BB_RSSICTL2 0x73 /* Core 1 RX Baseband RSSI Control 2 */
|
||||
#define B2055_C1_RX_BB_RSSICTL3 0x74 /* Core 1 RX Baseband RSSI Control 3 */
|
||||
#define B2055_C1_RX_BB_RSSICTL4 0x75 /* Core 1 RX Baseband RSSI Control 4 */
|
||||
#define B2055_C1_RX_BB_RSSICTL5 0x76 /* Core 1 RX Baseband RSSI Control 5 */
|
||||
#define B2055_C1_RX_BB_REG 0x77 /* Core 1 RX Baseband Regulator */
|
||||
#define B2055_C1_RX_BB_SPARE1 0x78 /* Core 1 RX Baseband spare 1 */
|
||||
#define B2055_C1_RX_TXBBRCAL 0x79 /* Core 1 RX TX BB RCAL */
|
||||
#define B2055_C1_TX_RF_SPGA 0x7A /* Core 1 TX RF SGM PGA */
|
||||
#define B2055_C1_TX_RF_SPAD 0x7B /* Core 1 TX RF SGM PAD */
|
||||
#define B2055_C1_TX_RF_CNTPGA1 0x7C /* Core 1 TX RF counter PGA 1 */
|
||||
#define B2055_C1_TX_RF_CNTPAD1 0x7D /* Core 1 TX RF counter PAD 1 */
|
||||
#define B2055_C1_TX_RF_PGAIDAC 0x7E /* Core 1 TX RF PGA IDAC */
|
||||
#define B2055_C1_TX_PGAPADTN 0x7F /* Core 1 TX PGA PAD TN */
|
||||
#define B2055_C1_TX_PADIDAC1 0x80 /* Core 1 TX PAD IDAC 1 */
|
||||
#define B2055_C1_TX_PADIDAC2 0x81 /* Core 1 TX PAD IDAC 2 */
|
||||
#define B2055_C1_TX_MXBGTRIM 0x82 /* Core 1 TX MX B/G TRIM */
|
||||
#define B2055_C1_TX_RF_RCAL 0x83 /* Core 1 TX RF RCAL */
|
||||
#define B2055_C1_TX_RF_PADTSSI1 0x84 /* Core 1 TX RF PAD TSSI1 */
|
||||
#define B2055_C1_TX_RF_PADTSSI2 0x85 /* Core 1 TX RF PAD TSSI2 */
|
||||
#define B2055_C1_TX_RF_SPARE 0x86 /* Core 1 TX RF spare */
|
||||
#define B2055_C1_TX_RF_IQCAL1 0x87 /* Core 1 TX RF I/Q CAL 1 */
|
||||
#define B2055_C1_TX_RF_IQCAL2 0x88 /* Core 1 TX RF I/Q CAL 2 */
|
||||
#define B2055_C1_TXBB_RCCAL 0x89 /* Core 1 TXBB RC CAL Control */
|
||||
#define B2055_C1_TXBB_LPF1 0x8A /* Core 1 TXBB LPF 1 */
|
||||
#define B2055_C1_TX_VOSCNCL 0x8B /* Core 1 TX VOS CNCL */
|
||||
#define B2055_C1_TX_LPF_MXGMIDAC 0x8C /* Core 1 TX LPF MXGM IDAC */
|
||||
#define B2055_C1_TX_BB_MXGM 0x8D /* Core 1 TX BB MXGM */
|
||||
#define B2055_C2_LGBUF_ATUNE 0x8E /* Core 2 LGBUF A tune */
|
||||
#define B2055_C2_LGBUF_GTUNE 0x8F /* Core 2 LGBUF G tune */
|
||||
#define B2055_C2_LGBUF_DIV 0x90 /* Core 2 LGBUF div */
|
||||
#define B2055_C2_LGBUF_AIDAC 0x91 /* Core 2 LGBUF A IDAC */
|
||||
#define B2055_C2_LGBUF_GIDAC 0x92 /* Core 2 LGBUF G IDAC */
|
||||
#define B2055_C2_LGBUF_IDACFO 0x93 /* Core 2 LGBUF IDAC filter override */
|
||||
#define B2055_C2_LGBUF_SPARE 0x94 /* Core 2 LGBUF spare */
|
||||
#define B2055_C2_RX_RFSPC1 0x95 /* Core 2 RX RF SPC1 */
|
||||
#define B2055_C2_RX_RFR1 0x96 /* Core 2 RX RF reg 1 */
|
||||
#define B2055_C2_RX_RFR2 0x97 /* Core 2 RX RF reg 2 */
|
||||
#define B2055_C2_RX_RFRCAL 0x98 /* Core 2 RX RF RCAL */
|
||||
#define B2055_C2_RX_BB_BLCMP 0x99 /* Core 2 RX Baseband BUFI LPF CMP */
|
||||
#define B2055_C2_RX_BB_LPF 0x9A /* Core 2 RX Baseband LPF */
|
||||
#define B2055_C2_RX_BB_MIDACHP 0x9B /* Core 2 RX Baseband MIDAC High-pass */
|
||||
#define B2055_C2_RX_BB_VGA1IDAC 0x9C /* Core 2 RX Baseband VGA1 IDAC */
|
||||
#define B2055_C2_RX_BB_VGA2IDAC 0x9D /* Core 2 RX Baseband VGA2 IDAC */
|
||||
#define B2055_C2_RX_BB_VGA3IDAC 0x9E /* Core 2 RX Baseband VGA3 IDAC */
|
||||
#define B2055_C2_RX_BB_BUFOCTL 0x9F /* Core 2 RX Baseband BUFO Control */
|
||||
#define B2055_C2_RX_BB_RCCALCTL 0xA0 /* Core 2 RX Baseband RCCAL Control */
|
||||
#define B2055_C2_RX_BB_RSSICTL1 0xA1 /* Core 2 RX Baseband RSSI Control 1 */
|
||||
#define B2055_C2_RX_BB_RSSICTL2 0xA2 /* Core 2 RX Baseband RSSI Control 2 */
|
||||
#define B2055_C2_RX_BB_RSSICTL3 0xA3 /* Core 2 RX Baseband RSSI Control 3 */
|
||||
#define B2055_C2_RX_BB_RSSICTL4 0xA4 /* Core 2 RX Baseband RSSI Control 4 */
|
||||
#define B2055_C2_RX_BB_RSSICTL5 0xA5 /* Core 2 RX Baseband RSSI Control 5 */
|
||||
#define B2055_C2_RX_BB_REG 0xA6 /* Core 2 RX Baseband Regulator */
|
||||
#define B2055_C2_RX_BB_SPARE1 0xA7 /* Core 2 RX Baseband spare 1 */
|
||||
#define B2055_C2_RX_TXBBRCAL 0xA8 /* Core 2 RX TX BB RCAL */
|
||||
#define B2055_C2_TX_RF_SPGA 0xA9 /* Core 2 TX RF SGM PGA */
|
||||
#define B2055_C2_TX_RF_SPAD 0xAA /* Core 2 TX RF SGM PAD */
|
||||
#define B2055_C2_TX_RF_CNTPGA1 0xAB /* Core 2 TX RF counter PGA 1 */
|
||||
#define B2055_C2_TX_RF_CNTPAD1 0xAC /* Core 2 TX RF counter PAD 1 */
|
||||
#define B2055_C2_TX_RF_PGAIDAC 0xAD /* Core 2 TX RF PGA IDAC */
|
||||
#define B2055_C2_TX_PGAPADTN 0xAE /* Core 2 TX PGA PAD TN */
|
||||
#define B2055_C2_TX_PADIDAC1 0xAF /* Core 2 TX PAD IDAC 1 */
|
||||
#define B2055_C2_TX_PADIDAC2 0xB0 /* Core 2 TX PAD IDAC 2 */
|
||||
#define B2055_C2_TX_MXBGTRIM 0xB1 /* Core 2 TX MX B/G TRIM */
|
||||
#define B2055_C2_TX_RF_RCAL 0xB2 /* Core 2 TX RF RCAL */
|
||||
#define B2055_C2_TX_RF_PADTSSI1 0xB3 /* Core 2 TX RF PAD TSSI1 */
|
||||
#define B2055_C2_TX_RF_PADTSSI2 0xB4 /* Core 2 TX RF PAD TSSI2 */
|
||||
#define B2055_C2_TX_RF_SPARE 0xB5 /* Core 2 TX RF spare */
|
||||
#define B2055_C2_TX_RF_IQCAL1 0xB6 /* Core 2 TX RF I/Q CAL 1 */
|
||||
#define B2055_C2_TX_RF_IQCAL2 0xB7 /* Core 2 TX RF I/Q CAL 2 */
|
||||
#define B2055_C2_TXBB_RCCAL 0xB8 /* Core 2 TXBB RC CAL Control */
|
||||
#define B2055_C2_TXBB_LPF1 0xB9 /* Core 2 TXBB LPF 1 */
|
||||
#define B2055_C2_TX_VOSCNCL 0xBA /* Core 2 TX VOS CNCL */
|
||||
#define B2055_C2_TX_LPF_MXGMIDAC 0xBB /* Core 2 TX LPF MXGM IDAC */
|
||||
#define B2055_C2_TX_BB_MXGM 0xBC /* Core 2 TX BB MXGM */
|
||||
#define B2055_PRG_GCHP21 0xBD /* PRG GC HPVGA23 21 */
|
||||
#define B2055_PRG_GCHP22 0xBE /* PRG GC HPVGA23 22 */
|
||||
#define B2055_PRG_GCHP23 0xBF /* PRG GC HPVGA23 23 */
|
||||
#define B2055_PRG_GCHP24 0xC0 /* PRG GC HPVGA23 24 */
|
||||
#define B2055_PRG_GCHP25 0xC1 /* PRG GC HPVGA23 25 */
|
||||
#define B2055_PRG_GCHP26 0xC2 /* PRG GC HPVGA23 26 */
|
||||
#define B2055_PRG_GCHP27 0xC3 /* PRG GC HPVGA23 27 */
|
||||
#define B2055_PRG_GCHP28 0xC4 /* PRG GC HPVGA23 28 */
|
||||
#define B2055_PRG_GCHP29 0xC5 /* PRG GC HPVGA23 29 */
|
||||
#define B2055_PRG_GCHP30 0xC6 /* PRG GC HPVGA23 30 */
|
||||
#define B2055_C1_LNA_GAINBST 0xCD /* Core 1 LNA GAINBST */
|
||||
#define B2055_C1_B0NB_RSSIVCM 0xD2 /* Core 1 B0 narrow-band RSSI VCM */
|
||||
#define B2055_C1_GENSPARE2 0xD6 /* Core 1 GEN spare 2 */
|
||||
#define B2055_C2_LNA_GAINBST 0xD9 /* Core 2 LNA GAINBST */
|
||||
#define B2055_C2_B0NB_RSSIVCM 0xDE /* Core 2 B0 narrow-band RSSI VCM */
|
||||
#define B2055_C2_GENSPARE2 0xE2 /* Core 2 GEN spare 2 */
|
||||
|
||||
|
||||
|
||||
struct b43_wldev;
|
||||
|
||||
struct b43_chanspec {
|
||||
u8 channel;
|
||||
u8 sideband;
|
||||
u8 b_width;
|
||||
u8 b_freq;
|
||||
u16 center_freq;
|
||||
enum nl80211_channel_type channel_type;
|
||||
};
|
||||
|
||||
struct b43_phy_n_iq_comp {
|
||||
@ -984,8 +772,6 @@ struct b43_phy_n {
|
||||
u16 papd_epsilon_offset[2];
|
||||
s32 preamble_override;
|
||||
u32 bb_mult_save;
|
||||
u8 b_width;
|
||||
struct b43_chanspec radio_chanspec;
|
||||
|
||||
bool gain_boost;
|
||||
bool elna_gain_config;
|
||||
|
1332
drivers/net/wireless/b43/radio_2055.c
Normal file
1332
drivers/net/wireless/b43/radio_2055.c
Normal file
File diff suppressed because it is too large
Load Diff
254
drivers/net/wireless/b43/radio_2055.h
Normal file
254
drivers/net/wireless/b43/radio_2055.h
Normal file
@ -0,0 +1,254 @@
|
||||
#ifndef B43_RADIO_2055_H_
|
||||
#define B43_RADIO_2055_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "tables_nphy.h"
|
||||
|
||||
#define B2055_GEN_SPARE 0x00 /* GEN spare */
|
||||
#define B2055_SP_PINPD 0x02 /* SP PIN PD */
|
||||
#define B2055_C1_SP_RSSI 0x03 /* SP RSSI Core 1 */
|
||||
#define B2055_C1_SP_PDMISC 0x04 /* SP PD MISC Core 1 */
|
||||
#define B2055_C2_SP_RSSI 0x05 /* SP RSSI Core 2 */
|
||||
#define B2055_C2_SP_PDMISC 0x06 /* SP PD MISC Core 2 */
|
||||
#define B2055_C1_SP_RXGC1 0x07 /* SP RX GC1 Core 1 */
|
||||
#define B2055_C1_SP_RXGC2 0x08 /* SP RX GC2 Core 1 */
|
||||
#define B2055_C2_SP_RXGC1 0x09 /* SP RX GC1 Core 2 */
|
||||
#define B2055_C2_SP_RXGC2 0x0A /* SP RX GC2 Core 2 */
|
||||
#define B2055_C1_SP_LPFBWSEL 0x0B /* SP LPF BW select Core 1 */
|
||||
#define B2055_C2_SP_LPFBWSEL 0x0C /* SP LPF BW select Core 2 */
|
||||
#define B2055_C1_SP_TXGC1 0x0D /* SP TX GC1 Core 1 */
|
||||
#define B2055_C1_SP_TXGC2 0x0E /* SP TX GC2 Core 1 */
|
||||
#define B2055_C2_SP_TXGC1 0x0F /* SP TX GC1 Core 2 */
|
||||
#define B2055_C2_SP_TXGC2 0x10 /* SP TX GC2 Core 2 */
|
||||
#define B2055_MASTER1 0x11 /* Master control 1 */
|
||||
#define B2055_MASTER2 0x12 /* Master control 2 */
|
||||
#define B2055_PD_LGEN 0x13 /* PD LGEN */
|
||||
#define B2055_PD_PLLTS 0x14 /* PD PLL TS */
|
||||
#define B2055_C1_PD_LGBUF 0x15 /* PD Core 1 LGBUF */
|
||||
#define B2055_C1_PD_TX 0x16 /* PD Core 1 TX */
|
||||
#define B2055_C1_PD_RXTX 0x17 /* PD Core 1 RXTX */
|
||||
#define B2055_C1_PD_RSSIMISC 0x18 /* PD Core 1 RSSI MISC */
|
||||
#define B2055_C2_PD_LGBUF 0x19 /* PD Core 2 LGBUF */
|
||||
#define B2055_C2_PD_TX 0x1A /* PD Core 2 TX */
|
||||
#define B2055_C2_PD_RXTX 0x1B /* PD Core 2 RXTX */
|
||||
#define B2055_C2_PD_RSSIMISC 0x1C /* PD Core 2 RSSI MISC */
|
||||
#define B2055_PWRDET_LGEN 0x1D /* PWRDET LGEN */
|
||||
#define B2055_C1_PWRDET_LGBUF 0x1E /* PWRDET LGBUF Core 1 */
|
||||
#define B2055_C1_PWRDET_RXTX 0x1F /* PWRDET RXTX Core 1 */
|
||||
#define B2055_C2_PWRDET_LGBUF 0x20 /* PWRDET LGBUF Core 2 */
|
||||
#define B2055_C2_PWRDET_RXTX 0x21 /* PWRDET RXTX Core 2 */
|
||||
#define B2055_RRCCAL_CS 0x22 /* RRCCAL Control spare */
|
||||
#define B2055_RRCCAL_NOPTSEL 0x23 /* RRCCAL N OPT SEL */
|
||||
#define B2055_CAL_MISC 0x24 /* CAL MISC */
|
||||
#define B2055_CAL_COUT 0x25 /* CAL Counter out */
|
||||
#define B2055_CAL_COUT2 0x26 /* CAL Counter out 2 */
|
||||
#define B2055_CAL_CVARCTL 0x27 /* CAL CVAR Control */
|
||||
#define B2055_CAL_RVARCTL 0x28 /* CAL RVAR Control */
|
||||
#define B2055_CAL_LPOCTL 0x29 /* CAL LPO Control */
|
||||
#define B2055_CAL_TS 0x2A /* CAL TS */
|
||||
#define B2055_CAL_RCCALRTS 0x2B /* CAL RCCAL READ TS */
|
||||
#define B2055_CAL_RCALRTS 0x2C /* CAL RCAL READ TS */
|
||||
#define B2055_PADDRV 0x2D /* PAD driver */
|
||||
#define B2055_XOCTL1 0x2E /* XO Control 1 */
|
||||
#define B2055_XOCTL2 0x2F /* XO Control 2 */
|
||||
#define B2055_XOREGUL 0x30 /* XO Regulator */
|
||||
#define B2055_XOMISC 0x31 /* XO misc */
|
||||
#define B2055_PLL_LFC1 0x32 /* PLL LF C1 */
|
||||
#define B2055_PLL_CALVTH 0x33 /* PLL CAL VTH */
|
||||
#define B2055_PLL_LFC2 0x34 /* PLL LF C2 */
|
||||
#define B2055_PLL_REF 0x35 /* PLL reference */
|
||||
#define B2055_PLL_LFR1 0x36 /* PLL LF R1 */
|
||||
#define B2055_PLL_PFDCP 0x37 /* PLL PFD CP */
|
||||
#define B2055_PLL_IDAC_CPOPAMP 0x38 /* PLL IDAC CPOPAMP */
|
||||
#define B2055_PLL_CPREG 0x39 /* PLL CP Regulator */
|
||||
#define B2055_PLL_RCAL 0x3A /* PLL RCAL */
|
||||
#define B2055_RF_PLLMOD0 0x3B /* RF PLL MOD0 */
|
||||
#define B2055_RF_PLLMOD1 0x3C /* RF PLL MOD1 */
|
||||
#define B2055_RF_MMDIDAC1 0x3D /* RF MMD IDAC 1 */
|
||||
#define B2055_RF_MMDIDAC0 0x3E /* RF MMD IDAC 0 */
|
||||
#define B2055_RF_MMDSP 0x3F /* RF MMD spare */
|
||||
#define B2055_VCO_CAL1 0x40 /* VCO cal 1 */
|
||||
#define B2055_VCO_CAL2 0x41 /* VCO cal 2 */
|
||||
#define B2055_VCO_CAL3 0x42 /* VCO cal 3 */
|
||||
#define B2055_VCO_CAL4 0x43 /* VCO cal 4 */
|
||||
#define B2055_VCO_CAL5 0x44 /* VCO cal 5 */
|
||||
#define B2055_VCO_CAL6 0x45 /* VCO cal 6 */
|
||||
#define B2055_VCO_CAL7 0x46 /* VCO cal 7 */
|
||||
#define B2055_VCO_CAL8 0x47 /* VCO cal 8 */
|
||||
#define B2055_VCO_CAL9 0x48 /* VCO cal 9 */
|
||||
#define B2055_VCO_CAL10 0x49 /* VCO cal 10 */
|
||||
#define B2055_VCO_CAL11 0x4A /* VCO cal 11 */
|
||||
#define B2055_VCO_CAL12 0x4B /* VCO cal 12 */
|
||||
#define B2055_VCO_CAL13 0x4C /* VCO cal 13 */
|
||||
#define B2055_VCO_CAL14 0x4D /* VCO cal 14 */
|
||||
#define B2055_VCO_CAL15 0x4E /* VCO cal 15 */
|
||||
#define B2055_VCO_CAL16 0x4F /* VCO cal 16 */
|
||||
#define B2055_VCO_KVCO 0x50 /* VCO KVCO */
|
||||
#define B2055_VCO_CAPTAIL 0x51 /* VCO CAP TAIL */
|
||||
#define B2055_VCO_IDACVCO 0x52 /* VCO IDAC VCO */
|
||||
#define B2055_VCO_REG 0x53 /* VCO Regulator */
|
||||
#define B2055_PLL_RFVTH 0x54 /* PLL RF VTH */
|
||||
#define B2055_LGBUF_CENBUF 0x55 /* LGBUF CEN BUF */
|
||||
#define B2055_LGEN_TUNE1 0x56 /* LGEN tune 1 */
|
||||
#define B2055_LGEN_TUNE2 0x57 /* LGEN tune 2 */
|
||||
#define B2055_LGEN_IDAC1 0x58 /* LGEN IDAC 1 */
|
||||
#define B2055_LGEN_IDAC2 0x59 /* LGEN IDAC 2 */
|
||||
#define B2055_LGEN_BIASC 0x5A /* LGEN BIAS counter */
|
||||
#define B2055_LGEN_BIASIDAC 0x5B /* LGEN BIAS IDAC */
|
||||
#define B2055_LGEN_RCAL 0x5C /* LGEN RCAL */
|
||||
#define B2055_LGEN_DIV 0x5D /* LGEN div */
|
||||
#define B2055_LGEN_SPARE2 0x5E /* LGEN spare 2 */
|
||||
#define B2055_C1_LGBUF_ATUNE 0x5F /* Core 1 LGBUF A tune */
|
||||
#define B2055_C1_LGBUF_GTUNE 0x60 /* Core 1 LGBUF G tune */
|
||||
#define B2055_C1_LGBUF_DIV 0x61 /* Core 1 LGBUF div */
|
||||
#define B2055_C1_LGBUF_AIDAC 0x62 /* Core 1 LGBUF A IDAC */
|
||||
#define B2055_C1_LGBUF_GIDAC 0x63 /* Core 1 LGBUF G IDAC */
|
||||
#define B2055_C1_LGBUF_IDACFO 0x64 /* Core 1 LGBUF IDAC filter override */
|
||||
#define B2055_C1_LGBUF_SPARE 0x65 /* Core 1 LGBUF spare */
|
||||
#define B2055_C1_RX_RFSPC1 0x66 /* Core 1 RX RF SPC1 */
|
||||
#define B2055_C1_RX_RFR1 0x67 /* Core 1 RX RF reg 1 */
|
||||
#define B2055_C1_RX_RFR2 0x68 /* Core 1 RX RF reg 2 */
|
||||
#define B2055_C1_RX_RFRCAL 0x69 /* Core 1 RX RF RCAL */
|
||||
#define B2055_C1_RX_BB_BLCMP 0x6A /* Core 1 RX Baseband BUFI LPF CMP */
|
||||
#define B2055_C1_RX_BB_LPF 0x6B /* Core 1 RX Baseband LPF */
|
||||
#define B2055_C1_RX_BB_MIDACHP 0x6C /* Core 1 RX Baseband MIDAC High-pass */
|
||||
#define B2055_C1_RX_BB_VGA1IDAC 0x6D /* Core 1 RX Baseband VGA1 IDAC */
|
||||
#define B2055_C1_RX_BB_VGA2IDAC 0x6E /* Core 1 RX Baseband VGA2 IDAC */
|
||||
#define B2055_C1_RX_BB_VGA3IDAC 0x6F /* Core 1 RX Baseband VGA3 IDAC */
|
||||
#define B2055_C1_RX_BB_BUFOCTL 0x70 /* Core 1 RX Baseband BUFO Control */
|
||||
#define B2055_C1_RX_BB_RCCALCTL 0x71 /* Core 1 RX Baseband RCCAL Control */
|
||||
#define B2055_C1_RX_BB_RSSICTL1 0x72 /* Core 1 RX Baseband RSSI Control 1 */
|
||||
#define B2055_C1_RX_BB_RSSICTL2 0x73 /* Core 1 RX Baseband RSSI Control 2 */
|
||||
#define B2055_C1_RX_BB_RSSICTL3 0x74 /* Core 1 RX Baseband RSSI Control 3 */
|
||||
#define B2055_C1_RX_BB_RSSICTL4 0x75 /* Core 1 RX Baseband RSSI Control 4 */
|
||||
#define B2055_C1_RX_BB_RSSICTL5 0x76 /* Core 1 RX Baseband RSSI Control 5 */
|
||||
#define B2055_C1_RX_BB_REG 0x77 /* Core 1 RX Baseband Regulator */
|
||||
#define B2055_C1_RX_BB_SPARE1 0x78 /* Core 1 RX Baseband spare 1 */
|
||||
#define B2055_C1_RX_TXBBRCAL 0x79 /* Core 1 RX TX BB RCAL */
|
||||
#define B2055_C1_TX_RF_SPGA 0x7A /* Core 1 TX RF SGM PGA */
|
||||
#define B2055_C1_TX_RF_SPAD 0x7B /* Core 1 TX RF SGM PAD */
|
||||
#define B2055_C1_TX_RF_CNTPGA1 0x7C /* Core 1 TX RF counter PGA 1 */
|
||||
#define B2055_C1_TX_RF_CNTPAD1 0x7D /* Core 1 TX RF counter PAD 1 */
|
||||
#define B2055_C1_TX_RF_PGAIDAC 0x7E /* Core 1 TX RF PGA IDAC */
|
||||
#define B2055_C1_TX_PGAPADTN 0x7F /* Core 1 TX PGA PAD TN */
|
||||
#define B2055_C1_TX_PADIDAC1 0x80 /* Core 1 TX PAD IDAC 1 */
|
||||
#define B2055_C1_TX_PADIDAC2 0x81 /* Core 1 TX PAD IDAC 2 */
|
||||
#define B2055_C1_TX_MXBGTRIM 0x82 /* Core 1 TX MX B/G TRIM */
|
||||
#define B2055_C1_TX_RF_RCAL 0x83 /* Core 1 TX RF RCAL */
|
||||
#define B2055_C1_TX_RF_PADTSSI1 0x84 /* Core 1 TX RF PAD TSSI1 */
|
||||
#define B2055_C1_TX_RF_PADTSSI2 0x85 /* Core 1 TX RF PAD TSSI2 */
|
||||
#define B2055_C1_TX_RF_SPARE 0x86 /* Core 1 TX RF spare */
|
||||
#define B2055_C1_TX_RF_IQCAL1 0x87 /* Core 1 TX RF I/Q CAL 1 */
|
||||
#define B2055_C1_TX_RF_IQCAL2 0x88 /* Core 1 TX RF I/Q CAL 2 */
|
||||
#define B2055_C1_TXBB_RCCAL 0x89 /* Core 1 TXBB RC CAL Control */
|
||||
#define B2055_C1_TXBB_LPF1 0x8A /* Core 1 TXBB LPF 1 */
|
||||
#define B2055_C1_TX_VOSCNCL 0x8B /* Core 1 TX VOS CNCL */
|
||||
#define B2055_C1_TX_LPF_MXGMIDAC 0x8C /* Core 1 TX LPF MXGM IDAC */
|
||||
#define B2055_C1_TX_BB_MXGM 0x8D /* Core 1 TX BB MXGM */
|
||||
#define B2055_C2_LGBUF_ATUNE 0x8E /* Core 2 LGBUF A tune */
|
||||
#define B2055_C2_LGBUF_GTUNE 0x8F /* Core 2 LGBUF G tune */
|
||||
#define B2055_C2_LGBUF_DIV 0x90 /* Core 2 LGBUF div */
|
||||
#define B2055_C2_LGBUF_AIDAC 0x91 /* Core 2 LGBUF A IDAC */
|
||||
#define B2055_C2_LGBUF_GIDAC 0x92 /* Core 2 LGBUF G IDAC */
|
||||
#define B2055_C2_LGBUF_IDACFO 0x93 /* Core 2 LGBUF IDAC filter override */
|
||||
#define B2055_C2_LGBUF_SPARE 0x94 /* Core 2 LGBUF spare */
|
||||
#define B2055_C2_RX_RFSPC1 0x95 /* Core 2 RX RF SPC1 */
|
||||
#define B2055_C2_RX_RFR1 0x96 /* Core 2 RX RF reg 1 */
|
||||
#define B2055_C2_RX_RFR2 0x97 /* Core 2 RX RF reg 2 */
|
||||
#define B2055_C2_RX_RFRCAL 0x98 /* Core 2 RX RF RCAL */
|
||||
#define B2055_C2_RX_BB_BLCMP 0x99 /* Core 2 RX Baseband BUFI LPF CMP */
|
||||
#define B2055_C2_RX_BB_LPF 0x9A /* Core 2 RX Baseband LPF */
|
||||
#define B2055_C2_RX_BB_MIDACHP 0x9B /* Core 2 RX Baseband MIDAC High-pass */
|
||||
#define B2055_C2_RX_BB_VGA1IDAC 0x9C /* Core 2 RX Baseband VGA1 IDAC */
|
||||
#define B2055_C2_RX_BB_VGA2IDAC 0x9D /* Core 2 RX Baseband VGA2 IDAC */
|
||||
#define B2055_C2_RX_BB_VGA3IDAC 0x9E /* Core 2 RX Baseband VGA3 IDAC */
|
||||
#define B2055_C2_RX_BB_BUFOCTL 0x9F /* Core 2 RX Baseband BUFO Control */
|
||||
#define B2055_C2_RX_BB_RCCALCTL 0xA0 /* Core 2 RX Baseband RCCAL Control */
|
||||
#define B2055_C2_RX_BB_RSSICTL1 0xA1 /* Core 2 RX Baseband RSSI Control 1 */
|
||||
#define B2055_C2_RX_BB_RSSICTL2 0xA2 /* Core 2 RX Baseband RSSI Control 2 */
|
||||
#define B2055_C2_RX_BB_RSSICTL3 0xA3 /* Core 2 RX Baseband RSSI Control 3 */
|
||||
#define B2055_C2_RX_BB_RSSICTL4 0xA4 /* Core 2 RX Baseband RSSI Control 4 */
|
||||
#define B2055_C2_RX_BB_RSSICTL5 0xA5 /* Core 2 RX Baseband RSSI Control 5 */
|
||||
#define B2055_C2_RX_BB_REG 0xA6 /* Core 2 RX Baseband Regulator */
|
||||
#define B2055_C2_RX_BB_SPARE1 0xA7 /* Core 2 RX Baseband spare 1 */
|
||||
#define B2055_C2_RX_TXBBRCAL 0xA8 /* Core 2 RX TX BB RCAL */
|
||||
#define B2055_C2_TX_RF_SPGA 0xA9 /* Core 2 TX RF SGM PGA */
|
||||
#define B2055_C2_TX_RF_SPAD 0xAA /* Core 2 TX RF SGM PAD */
|
||||
#define B2055_C2_TX_RF_CNTPGA1 0xAB /* Core 2 TX RF counter PGA 1 */
|
||||
#define B2055_C2_TX_RF_CNTPAD1 0xAC /* Core 2 TX RF counter PAD 1 */
|
||||
#define B2055_C2_TX_RF_PGAIDAC 0xAD /* Core 2 TX RF PGA IDAC */
|
||||
#define B2055_C2_TX_PGAPADTN 0xAE /* Core 2 TX PGA PAD TN */
|
||||
#define B2055_C2_TX_PADIDAC1 0xAF /* Core 2 TX PAD IDAC 1 */
|
||||
#define B2055_C2_TX_PADIDAC2 0xB0 /* Core 2 TX PAD IDAC 2 */
|
||||
#define B2055_C2_TX_MXBGTRIM 0xB1 /* Core 2 TX MX B/G TRIM */
|
||||
#define B2055_C2_TX_RF_RCAL 0xB2 /* Core 2 TX RF RCAL */
|
||||
#define B2055_C2_TX_RF_PADTSSI1 0xB3 /* Core 2 TX RF PAD TSSI1 */
|
||||
#define B2055_C2_TX_RF_PADTSSI2 0xB4 /* Core 2 TX RF PAD TSSI2 */
|
||||
#define B2055_C2_TX_RF_SPARE 0xB5 /* Core 2 TX RF spare */
|
||||
#define B2055_C2_TX_RF_IQCAL1 0xB6 /* Core 2 TX RF I/Q CAL 1 */
|
||||
#define B2055_C2_TX_RF_IQCAL2 0xB7 /* Core 2 TX RF I/Q CAL 2 */
|
||||
#define B2055_C2_TXBB_RCCAL 0xB8 /* Core 2 TXBB RC CAL Control */
|
||||
#define B2055_C2_TXBB_LPF1 0xB9 /* Core 2 TXBB LPF 1 */
|
||||
#define B2055_C2_TX_VOSCNCL 0xBA /* Core 2 TX VOS CNCL */
|
||||
#define B2055_C2_TX_LPF_MXGMIDAC 0xBB /* Core 2 TX LPF MXGM IDAC */
|
||||
#define B2055_C2_TX_BB_MXGM 0xBC /* Core 2 TX BB MXGM */
|
||||
#define B2055_PRG_GCHP21 0xBD /* PRG GC HPVGA23 21 */
|
||||
#define B2055_PRG_GCHP22 0xBE /* PRG GC HPVGA23 22 */
|
||||
#define B2055_PRG_GCHP23 0xBF /* PRG GC HPVGA23 23 */
|
||||
#define B2055_PRG_GCHP24 0xC0 /* PRG GC HPVGA23 24 */
|
||||
#define B2055_PRG_GCHP25 0xC1 /* PRG GC HPVGA23 25 */
|
||||
#define B2055_PRG_GCHP26 0xC2 /* PRG GC HPVGA23 26 */
|
||||
#define B2055_PRG_GCHP27 0xC3 /* PRG GC HPVGA23 27 */
|
||||
#define B2055_PRG_GCHP28 0xC4 /* PRG GC HPVGA23 28 */
|
||||
#define B2055_PRG_GCHP29 0xC5 /* PRG GC HPVGA23 29 */
|
||||
#define B2055_PRG_GCHP30 0xC6 /* PRG GC HPVGA23 30 */
|
||||
#define B2055_C1_LNA_GAINBST 0xCD /* Core 1 LNA GAINBST */
|
||||
#define B2055_C1_B0NB_RSSIVCM 0xD2 /* Core 1 B0 narrow-band RSSI VCM */
|
||||
#define B2055_C1_GENSPARE2 0xD6 /* Core 1 GEN spare 2 */
|
||||
#define B2055_C2_LNA_GAINBST 0xD9 /* Core 2 LNA GAINBST */
|
||||
#define B2055_C2_B0NB_RSSIVCM 0xDE /* Core 2 B0 narrow-band RSSI VCM */
|
||||
#define B2055_C2_GENSPARE2 0xE2 /* Core 2 GEN spare 2 */
|
||||
|
||||
struct b43_nphy_channeltab_entry_rev2 {
|
||||
/* The channel number */
|
||||
u8 channel;
|
||||
/* The channel frequency in MHz */
|
||||
u16 freq;
|
||||
/* An unknown value */
|
||||
u16 unk2;
|
||||
/* Radio register values on channelswitch */
|
||||
u8 radio_pll_ref;
|
||||
u8 radio_rf_pllmod0;
|
||||
u8 radio_rf_pllmod1;
|
||||
u8 radio_vco_captail;
|
||||
u8 radio_vco_cal1;
|
||||
u8 radio_vco_cal2;
|
||||
u8 radio_pll_lfc1;
|
||||
u8 radio_pll_lfr1;
|
||||
u8 radio_pll_lfc2;
|
||||
u8 radio_lgbuf_cenbuf;
|
||||
u8 radio_lgen_tune1;
|
||||
u8 radio_lgen_tune2;
|
||||
u8 radio_c1_lgbuf_atune;
|
||||
u8 radio_c1_lgbuf_gtune;
|
||||
u8 radio_c1_rx_rfr1;
|
||||
u8 radio_c1_tx_pgapadtn;
|
||||
u8 radio_c1_tx_mxbgtrim;
|
||||
u8 radio_c2_lgbuf_atune;
|
||||
u8 radio_c2_lgbuf_gtune;
|
||||
u8 radio_c2_rx_rfr1;
|
||||
u8 radio_c2_tx_pgapadtn;
|
||||
u8 radio_c2_tx_mxbgtrim;
|
||||
/* PHY register values on channelswitch */
|
||||
struct b43_phy_n_sfo_cfg phy_regs;
|
||||
};
|
||||
|
||||
/* Upload the default register value table.
|
||||
* If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz
|
||||
* table is uploaded. If "ignore_uploadflag" is true, we upload any value
|
||||
* and ignore the "UPLOAD" flag. */
|
||||
void b2055_upload_inittab(struct b43_wldev *dev,
|
||||
bool ghz5, bool ignore_uploadflag);
|
||||
|
||||
#endif /* B43_RADIO_2055_H_ */
|
43
drivers/net/wireless/b43/radio_2056.c
Normal file
43
drivers/net/wireless/b43/radio_2056.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
|
||||
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;
|
||||
}
|
42
drivers/net/wireless/b43/radio_2056.h
Normal file
42
drivers/net/wireless/b43/radio_2056.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
Broadcom B43 wireless driver
|
||||
|
||||
Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef B43_RADIO_2056_H_
|
||||
#define B43_RADIO_2056_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "tables_nphy.h"
|
||||
|
||||
struct b43_nphy_channeltab_entry_rev3 {
|
||||
/* The channel number */
|
||||
u8 channel;
|
||||
/* The channel frequency in MHz */
|
||||
u16 freq;
|
||||
/* Radio register values on channelswitch */
|
||||
/* TODO */
|
||||
/* PHY register values on channelswitch */
|
||||
struct b43_phy_n_sfo_cfg phy_regs;
|
||||
};
|
||||
|
||||
#endif /* B43_RADIO_2056_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,6 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
struct b43_phy_n_sfo_cfg {
|
||||
u16 phy_bw1a;
|
||||
u16 phy_bw2;
|
||||
@ -13,52 +12,6 @@ struct b43_phy_n_sfo_cfg {
|
||||
u16 phy_bw6;
|
||||
};
|
||||
|
||||
struct b43_nphy_channeltab_entry_rev2 {
|
||||
/* The channel number */
|
||||
u8 channel;
|
||||
/* The channel frequency in MHz */
|
||||
u16 freq;
|
||||
/* An unknown value */
|
||||
u16 unk2;
|
||||
/* Radio register values on channelswitch */
|
||||
u8 radio_pll_ref;
|
||||
u8 radio_rf_pllmod0;
|
||||
u8 radio_rf_pllmod1;
|
||||
u8 radio_vco_captail;
|
||||
u8 radio_vco_cal1;
|
||||
u8 radio_vco_cal2;
|
||||
u8 radio_pll_lfc1;
|
||||
u8 radio_pll_lfr1;
|
||||
u8 radio_pll_lfc2;
|
||||
u8 radio_lgbuf_cenbuf;
|
||||
u8 radio_lgen_tune1;
|
||||
u8 radio_lgen_tune2;
|
||||
u8 radio_c1_lgbuf_atune;
|
||||
u8 radio_c1_lgbuf_gtune;
|
||||
u8 radio_c1_rx_rfr1;
|
||||
u8 radio_c1_tx_pgapadtn;
|
||||
u8 radio_c1_tx_mxbgtrim;
|
||||
u8 radio_c2_lgbuf_atune;
|
||||
u8 radio_c2_lgbuf_gtune;
|
||||
u8 radio_c2_rx_rfr1;
|
||||
u8 radio_c2_tx_pgapadtn;
|
||||
u8 radio_c2_tx_mxbgtrim;
|
||||
/* PHY register values on channelswitch */
|
||||
struct b43_phy_n_sfo_cfg phy_regs;
|
||||
};
|
||||
|
||||
struct b43_nphy_channeltab_entry_rev3 {
|
||||
/* The channel number */
|
||||
u8 channel;
|
||||
/* The channel frequency in MHz */
|
||||
u16 freq;
|
||||
/* Radio register values on channelswitch */
|
||||
/* TODO */
|
||||
/* PHY register values on channelswitch */
|
||||
struct b43_phy_n_sfo_cfg phy_regs;
|
||||
};
|
||||
|
||||
|
||||
struct b43_wldev;
|
||||
|
||||
struct nphy_txiqcal_ladder {
|
||||
@ -82,18 +35,12 @@ struct nphy_rf_control_override_rev3 {
|
||||
u8 val_addr1;
|
||||
};
|
||||
|
||||
/* Upload the default register value table.
|
||||
* If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz
|
||||
* table is uploaded. If "ignore_uploadflag" is true, we upload any value
|
||||
* and ignore the "UPLOAD" flag. */
|
||||
void b2055_upload_inittab(struct b43_wldev *dev,
|
||||
bool ghz5, bool ignore_uploadflag);
|
||||
|
||||
|
||||
/* Get the NPHY Channel Switch Table entry for a channel number.
|
||||
/* Get the NPHY Channel Switch Table entry for a channel.
|
||||
* Returns NULL on failure to find an entry. */
|
||||
const struct b43_nphy_channeltab_entry_rev2 *
|
||||
b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
|
||||
const struct b43_nphy_channeltab_entry_rev3 *
|
||||
b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
|
||||
|
||||
|
||||
/* The N-PHY tables. */
|
||||
|
@ -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
|
||||
|
@ -151,8 +151,7 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
|
||||
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
|
||||
|
||||
if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
|
||||
priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
|
||||
iwl1000_set_ct_threshold(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
/* Set initial calibration set */
|
||||
@ -195,9 +194,7 @@ static struct iwl_lib_ops iwl1000_lib = {
|
||||
.update_chain_flags = iwl_update_chain_flags,
|
||||
.apm_ops = {
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl1000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
@ -209,7 +206,6 @@ static struct iwl_lib_ops iwl1000_lib = {
|
||||
EEPROM_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
.verify_signature = iwlcore_eeprom_verify_signature,
|
||||
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
|
||||
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
||||
.calib_version = iwlagn_eeprom_calib_version,
|
||||
@ -220,7 +216,6 @@ static struct iwl_lib_ops iwl1000_lib = {
|
||||
.config_ap = iwl_config_ap,
|
||||
.temp_ops = {
|
||||
.temperature = iwlagn_temperature,
|
||||
.set_ct_kill = iwl1000_set_ct_threshold,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
|
@ -87,6 +87,15 @@ const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = {
|
||||
IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */
|
||||
};
|
||||
|
||||
static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
|
||||
{
|
||||
u8 rate = iwl3945_rates[rate_index].prev_ieee;
|
||||
|
||||
if (rate == IWL_RATE_INVALID)
|
||||
rate = rate_index;
|
||||
return rate;
|
||||
}
|
||||
|
||||
/* 1 = enable the iwl3945_disable_events() function */
|
||||
#define IWL_EVT_DISABLE (0)
|
||||
#define IWL_EVT_DISABLE_SIZE (1532/32)
|
||||
@ -339,7 +348,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
|
||||
IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index);
|
||||
iwl3945_tx_queue_reclaim(priv, txq_id, index);
|
||||
|
||||
if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
|
||||
if (status & TX_ABORT_REQUIRED_MSK)
|
||||
IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n");
|
||||
}
|
||||
|
||||
@ -807,9 +816,12 @@ static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate)
|
||||
return sta_id;
|
||||
}
|
||||
|
||||
static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
|
||||
static void iwl3945_set_pwr_vmain(struct iwl_priv *priv)
|
||||
{
|
||||
if (src == IWL_PWR_SRC_VAUX) {
|
||||
/*
|
||||
* (for documentation purposes)
|
||||
* to set power to V_AUX, do
|
||||
|
||||
if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) {
|
||||
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
|
||||
@ -819,16 +831,14 @@ static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
|
||||
CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
|
||||
CSR_GPIO_IN_BIT_AUX_POWER, 5000);
|
||||
}
|
||||
} else {
|
||||
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
|
||||
~APMG_PS_CTRL_MSK_PWR_SRC);
|
||||
*/
|
||||
|
||||
iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
|
||||
CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */
|
||||
}
|
||||
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
|
||||
~APMG_PS_CTRL_MSK_PWR_SRC);
|
||||
|
||||
return 0;
|
||||
iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
|
||||
CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */
|
||||
}
|
||||
|
||||
static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
|
||||
@ -1022,9 +1032,7 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv)
|
||||
priv->cfg->ops->lib->apm_ops.init(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
|
||||
if (rc)
|
||||
return rc;
|
||||
iwl3945_set_pwr_vmain(priv);
|
||||
|
||||
priv->cfg->ops->lib->apm_ops.config(priv);
|
||||
|
||||
@ -1763,8 +1771,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv,
|
||||
* function correctly transitions out of the RXON_ASSOC_MSK state if
|
||||
* a HW tune is required based on the RXON structure changes.
|
||||
*/
|
||||
static int iwl3945_commit_rxon(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
/* cast away the const for active_rxon in this function */
|
||||
struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active;
|
||||
@ -2300,6 +2307,32 @@ static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
|
||||
return (u16)sizeof(struct iwl3945_addsta_cmd);
|
||||
}
|
||||
|
||||
static int iwl3945_add_bssid_station(struct iwl_priv *priv,
|
||||
const u8 *addr, u8 *sta_id_r)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
unsigned long flags;
|
||||
|
||||
if (sta_id_r)
|
||||
*sta_id_r = IWL_INVALID_STATION;
|
||||
|
||||
ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Unable to add station %pM\n", addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sta_id_r)
|
||||
*sta_id_r = sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].used |= IWL_STA_LOCAL;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add)
|
||||
{
|
||||
@ -2307,10 +2340,8 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
|
||||
int ret;
|
||||
|
||||
if (add) {
|
||||
ret = iwl_add_bssid_station(
|
||||
priv, &priv->contexts[IWL_RXON_CTX_BSS],
|
||||
vif->bss_conf.bssid, false,
|
||||
&vif_priv->ibss_bssid_sta_id);
|
||||
ret = iwl3945_add_bssid_station(priv, vif->bss_conf.bssid,
|
||||
&vif_priv->ibss_bssid_sta_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -2673,9 +2704,7 @@ static struct iwl_lib_ops iwl3945_lib = {
|
||||
.dump_nic_error_log = iwl3945_dump_nic_error_log,
|
||||
.apm_ops = {
|
||||
.init = iwl3945_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl3945_nic_config,
|
||||
.set_pwr_src = iwl3945_set_pwr_src,
|
||||
},
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
@ -2687,7 +2716,6 @@ static struct iwl_lib_ops iwl3945_lib = {
|
||||
EEPROM_REGULATORY_BAND_NO_HT40,
|
||||
EEPROM_REGULATORY_BAND_NO_HT40,
|
||||
},
|
||||
.verify_signature = iwlcore_eeprom_verify_signature,
|
||||
.acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
|
||||
.release_semaphore = iwl3945_eeprom_release_semaphore,
|
||||
.query_addr = iwlcore_eeprom_query_addr,
|
||||
@ -2713,6 +2741,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
|
||||
.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
|
||||
.tx_cmd_protection = iwlcore_tx_cmd_protection,
|
||||
.request_scan = iwl3945_request_scan,
|
||||
.post_scan = iwl3945_post_scan,
|
||||
};
|
||||
|
||||
static const struct iwl_ops iwl3945_ops = {
|
||||
@ -2724,6 +2753,7 @@ static const struct iwl_ops iwl3945_ops = {
|
||||
|
||||
static struct iwl_base_params iwl3945_base_params = {
|
||||
.eeprom_size = IWL3945_EEPROM_IMG_SIZE,
|
||||
.num_of_queues = IWL39_NUM_QUEUES,
|
||||
.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
|
||||
.set_l0s = false,
|
||||
.use_bsm = true,
|
||||
|
@ -138,8 +138,6 @@ enum iwl3945_antenna {
|
||||
#define DEFAULT_SHORT_RETRY_LIMIT 7U
|
||||
#define DEFAULT_LONG_RETRY_LIMIT 4U
|
||||
|
||||
#include "iwl-agn-rs.h"
|
||||
|
||||
#define IWL_TX_FIFO_AC0 0
|
||||
#define IWL_TX_FIFO_AC1 1
|
||||
#define IWL_TX_FIFO_AC2 2
|
||||
@ -271,6 +269,9 @@ extern void iwl3945_post_associate(struct iwl_priv *priv,
|
||||
extern void iwl3945_config_ap(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
extern int iwl3945_commit_rxon(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
|
||||
/**
|
||||
* iwl3945_hw_find_station - Find station id for a given BSSID
|
||||
* @bssid: MAC address of station ID to find
|
||||
@ -296,6 +297,10 @@ extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
|
||||
|
||||
/* scanning */
|
||||
int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
void iwl3945_post_scan(struct iwl_priv *priv);
|
||||
|
||||
/* rates */
|
||||
extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
|
||||
|
||||
/* Requires full declaration of iwl_priv before including */
|
||||
#include "iwl-io.h"
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-calib.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-agn-led.h"
|
||||
#include "iwl-agn.h"
|
||||
@ -669,8 +669,8 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
|
||||
priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
|
||||
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
|
||||
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
|
||||
if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
|
||||
priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
|
||||
|
||||
iwl4965_set_ct_threshold(priv);
|
||||
|
||||
priv->hw_params.sens = &iwl4965_sensitivity;
|
||||
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
@ -2216,11 +2216,23 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
|
||||
|
||||
static struct iwl_hcmd_ops iwl4965_hcmd = {
|
||||
.rxon_assoc = iwl4965_send_rxon_assoc,
|
||||
.commit_rxon = iwl_commit_rxon,
|
||||
.set_rxon_chain = iwl_set_rxon_chain,
|
||||
.commit_rxon = iwlagn_commit_rxon,
|
||||
.set_rxon_chain = iwlagn_set_rxon_chain,
|
||||
.send_bt_config = iwl_send_bt_config,
|
||||
};
|
||||
|
||||
static void iwl4965_post_scan(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
/*
|
||||
* Since setting the RXON may have been deferred while
|
||||
* performing the scan, fire one off if needed
|
||||
*/
|
||||
if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
|
||||
static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
|
||||
.get_hcmd_size = iwl4965_get_hcmd_size,
|
||||
.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
|
||||
@ -2229,6 +2241,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
|
||||
.tx_cmd_protection = iwlcore_tx_cmd_protection,
|
||||
.calc_rssi = iwl4965_calc_rssi,
|
||||
.request_scan = iwlagn_request_scan,
|
||||
.post_scan = iwl4965_post_scan,
|
||||
};
|
||||
|
||||
static struct iwl_lib_ops iwl4965_lib = {
|
||||
@ -2253,9 +2266,7 @@ static struct iwl_lib_ops iwl4965_lib = {
|
||||
.set_channel_switch = iwl4965_hw_channel_switch,
|
||||
.apm_ops = {
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl4965_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
@ -2267,7 +2278,6 @@ static struct iwl_lib_ops iwl4965_lib = {
|
||||
EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
.verify_signature = iwlcore_eeprom_verify_signature,
|
||||
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
|
||||
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
||||
.calib_version = iwl4965_eeprom_calib_version,
|
||||
@ -2280,7 +2290,6 @@ static struct iwl_lib_ops iwl4965_lib = {
|
||||
.isr = iwl_isr_legacy,
|
||||
.temp_ops = {
|
||||
.temperature = iwl4965_temperature_calib,
|
||||
.set_ct_kill = iwl4965_set_ct_threshold,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
|
@ -195,8 +195,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
|
||||
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
|
||||
|
||||
if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
|
||||
priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
|
||||
iwl5000_set_ct_threshold(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
/* Set initial calibration set */
|
||||
@ -242,8 +241,7 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
|
||||
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
|
||||
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
|
||||
|
||||
if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
|
||||
priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
|
||||
iwl5150_set_ct_threshold(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
/* Set initial calibration set */
|
||||
@ -370,9 +368,7 @@ static struct iwl_lib_ops iwl5000_lib = {
|
||||
.set_channel_switch = iwl5000_hw_channel_switch,
|
||||
.apm_ops = {
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl5000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
@ -384,7 +380,6 @@ static struct iwl_lib_ops iwl5000_lib = {
|
||||
EEPROM_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
.verify_signature = iwlcore_eeprom_verify_signature,
|
||||
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
|
||||
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
||||
.calib_version = iwlagn_eeprom_calib_version,
|
||||
@ -395,7 +390,6 @@ static struct iwl_lib_ops iwl5000_lib = {
|
||||
.config_ap = iwl_config_ap,
|
||||
.temp_ops = {
|
||||
.temperature = iwlagn_temperature,
|
||||
.set_ct_kill = iwl5000_set_ct_threshold,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
@ -442,9 +436,7 @@ static struct iwl_lib_ops iwl5150_lib = {
|
||||
.set_channel_switch = iwl5000_hw_channel_switch,
|
||||
.apm_ops = {
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl5000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
@ -456,7 +448,6 @@ static struct iwl_lib_ops iwl5150_lib = {
|
||||
EEPROM_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
.verify_signature = iwlcore_eeprom_verify_signature,
|
||||
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
|
||||
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
||||
.calib_version = iwlagn_eeprom_calib_version,
|
||||
@ -467,7 +458,6 @@ static struct iwl_lib_ops iwl5150_lib = {
|
||||
.config_ap = iwl_config_ap,
|
||||
.temp_ops = {
|
||||
.temperature = iwl5150_temperature,
|
||||
.set_ct_kill = iwl5150_set_ct_threshold,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
|
@ -192,8 +192,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
|
||||
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
|
||||
|
||||
if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
|
||||
priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
|
||||
iwl6000_set_ct_threshold(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
/* Set initial calibration set */
|
||||
@ -205,6 +204,8 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
if (priv->cfg->need_dc_calib)
|
||||
priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX);
|
||||
if (priv->cfg->need_temp_offset_calib)
|
||||
priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
|
||||
|
||||
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
@ -309,9 +310,7 @@ static struct iwl_lib_ops iwl6000_lib = {
|
||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||
.apm_ops = {
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl6000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
@ -323,7 +322,6 @@ static struct iwl_lib_ops iwl6000_lib = {
|
||||
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
.verify_signature = iwlcore_eeprom_verify_signature,
|
||||
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
|
||||
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
||||
.calib_version = iwlagn_eeprom_calib_version,
|
||||
@ -335,7 +333,6 @@ static struct iwl_lib_ops iwl6000_lib = {
|
||||
.config_ap = iwl_config_ap,
|
||||
.temp_ops = {
|
||||
.temperature = iwlagn_temperature,
|
||||
.set_ct_kill = iwl6000_set_ct_threshold,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
@ -384,9 +381,7 @@ static struct iwl_lib_ops iwl6000g2b_lib = {
|
||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||
.apm_ops = {
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl6000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
@ -398,7 +393,6 @@ static struct iwl_lib_ops iwl6000g2b_lib = {
|
||||
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
.verify_signature = iwlcore_eeprom_verify_signature,
|
||||
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
|
||||
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
||||
.calib_version = iwlagn_eeprom_calib_version,
|
||||
@ -410,7 +404,6 @@ static struct iwl_lib_ops iwl6000g2b_lib = {
|
||||
.config_ap = iwl_config_ap,
|
||||
.temp_ops = {
|
||||
.temperature = iwlagn_temperature,
|
||||
.set_ct_kill = iwl6000_set_ct_threshold,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
@ -516,6 +509,28 @@ static struct iwl_base_params iwl6050_base_params = {
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
static struct iwl_base_params iwl6000_coex_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
static struct iwl_ht_params iwl6000_ht_params = {
|
||||
.ht_greenfield_support = true,
|
||||
@ -545,6 +560,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = {
|
||||
.base_params = &iwl6000_base_params,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
.need_dc_calib = true,
|
||||
.need_temp_offset_calib = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000g2a_2abg_cfg = {
|
||||
@ -561,6 +577,7 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = {
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.base_params = &iwl6000_base_params,
|
||||
.need_dc_calib = true,
|
||||
.need_temp_offset_calib = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000g2a_2bg_cfg = {
|
||||
@ -577,6 +594,7 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = {
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.base_params = &iwl6000_base_params,
|
||||
.need_dc_calib = true,
|
||||
.need_temp_offset_calib = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000g2b_2agn_cfg = {
|
||||
@ -591,10 +609,11 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.base_params = &iwl6000_base_params,
|
||||
.base_params = &iwl6000_coex_base_params,
|
||||
.bt_params = &iwl6000_bt_params,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
.need_dc_calib = true,
|
||||
.need_temp_offset_calib = true,
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
|
||||
};
|
||||
@ -611,9 +630,10 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.base_params = &iwl6000_base_params,
|
||||
.base_params = &iwl6000_coex_base_params,
|
||||
.bt_params = &iwl6000_bt_params,
|
||||
.need_dc_calib = true,
|
||||
.need_temp_offset_calib = true,
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
|
||||
};
|
||||
@ -630,10 +650,11 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.base_params = &iwl6000_base_params,
|
||||
.base_params = &iwl6000_coex_base_params,
|
||||
.bt_params = &iwl6000_bt_params,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
.need_dc_calib = true,
|
||||
.need_temp_offset_calib = true,
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
|
||||
};
|
||||
@ -650,9 +671,10 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.base_params = &iwl6000_base_params,
|
||||
.base_params = &iwl6000_coex_base_params,
|
||||
.bt_params = &iwl6000_bt_params,
|
||||
.need_dc_calib = true,
|
||||
.need_temp_offset_calib = true,
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
|
||||
};
|
||||
@ -669,10 +691,11 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.base_params = &iwl6000_base_params,
|
||||
.base_params = &iwl6000_coex_base_params,
|
||||
.bt_params = &iwl6000_bt_params,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
.need_dc_calib = true,
|
||||
.need_temp_offset_calib = true,
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
|
||||
};
|
||||
@ -689,9 +712,10 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.base_params = &iwl6000_base_params,
|
||||
.base_params = &iwl6000_coex_base_params,
|
||||
.bt_params = &iwl6000_bt_params,
|
||||
.need_dc_calib = true,
|
||||
.need_temp_offset_calib = true,
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
|
||||
};
|
||||
@ -756,7 +780,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.ops = &iwl6000_ops,
|
||||
.ops = &iwl6050_ops,
|
||||
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
@ -827,7 +851,7 @@ struct iwl_cfg iwl130_bgn_cfg = {
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.base_params = &iwl6000_base_params,
|
||||
.base_params = &iwl6000_coex_base_params,
|
||||
.bt_params = &iwl6000_bt_params,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
.need_dc_calib = true,
|
||||
@ -847,7 +871,7 @@ struct iwl_cfg iwl130_bg_cfg = {
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.base_params = &iwl6000_base_params,
|
||||
.base_params = &iwl6000_coex_base_params,
|
||||
.bt_params = &iwl6000_bt_params,
|
||||
.need_dc_calib = true,
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
|
@ -65,7 +65,7 @@
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-calib.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* INIT calibrations framework
|
||||
|
@ -79,4 +79,8 @@ static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
|
||||
priv->cfg->ops->utils->chain_noise_reset(priv);
|
||||
}
|
||||
|
||||
int iwl_send_calib_results(struct iwl_priv *priv);
|
||||
int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
|
||||
void iwl_calib_free_results(struct iwl_priv *priv);
|
||||
|
||||
#endif /* __iwl_calib_h__ */
|
454
drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
Normal file
454
drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
Normal file
@ -0,0 +1,454 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-commands.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-io.h"
|
||||
|
||||
/************************** EEPROM BANDS ****************************
|
||||
*
|
||||
* The iwl_eeprom_band definitions below provide the mapping from the
|
||||
* EEPROM contents to the specific channel number supported for each
|
||||
* band.
|
||||
*
|
||||
* For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
|
||||
* definition below maps to physical channel 42 in the 5.2GHz spectrum.
|
||||
* The specific geography and calibration information for that channel
|
||||
* is contained in the eeprom map itself.
|
||||
*
|
||||
* During init, we copy the eeprom information and channel map
|
||||
* information into priv->channel_info_24/52 and priv->channel_map_24/52
|
||||
*
|
||||
* channel_map_24/52 provides the index in the channel_info array for a
|
||||
* given channel. We have to have two separate maps as there is channel
|
||||
* overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
|
||||
* band_2
|
||||
*
|
||||
* A value of 0xff stored in the channel_map indicates that the channel
|
||||
* is not supported by the hardware at all.
|
||||
*
|
||||
* A value of 0xfe in the channel_map indicates that the channel is not
|
||||
* valid for Tx with the current hardware. This means that
|
||||
* while the system can tune and receive on a given channel, it may not
|
||||
* be able to associate or transmit any frames on that
|
||||
* channel. There is no corresponding channel information for that
|
||||
* entry.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* struct iwl_txpwr_section: eeprom section information
|
||||
* @offset: indirect address into eeprom image
|
||||
* @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
|
||||
* @band: band type for the section
|
||||
* @is_common - true: common section, false: channel section
|
||||
* @is_cck - true: cck section, false: not cck section
|
||||
* @is_ht_40 - true: all channel in the section are HT40 channel,
|
||||
* false: legacy or HT 20 MHz
|
||||
* ignore if it is common section
|
||||
* @iwl_eeprom_section_channel: channel array in the section,
|
||||
* ignore if common section
|
||||
*/
|
||||
struct iwl_txpwr_section {
|
||||
u32 offset;
|
||||
u8 count;
|
||||
enum ieee80211_band band;
|
||||
bool is_common;
|
||||
bool is_cck;
|
||||
bool is_ht40;
|
||||
u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
|
||||
};
|
||||
|
||||
/**
|
||||
* section 1 - 3 are regulatory tx power apply to all channels based on
|
||||
* modulation: CCK, OFDM
|
||||
* Band: 2.4GHz, 5.2GHz
|
||||
* section 4 - 10 are regulatory tx power apply to specified channels
|
||||
* For example:
|
||||
* 1L - Channel 1 Legacy
|
||||
* 1HT - Channel 1 HT
|
||||
* (1,+1) - Channel 1 HT40 "_above_"
|
||||
*
|
||||
* Section 1: all CCK channels
|
||||
* Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
|
||||
* Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
|
||||
* Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
|
||||
* Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
|
||||
* Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
|
||||
* Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
|
||||
* Section 8: 2.4 GHz channel: 13L, 13HT
|
||||
* Section 9: 2.4 GHz channel: 140L, 140HT
|
||||
* Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1)
|
||||
*
|
||||
*/
|
||||
static const struct iwl_txpwr_section enhinfo[] = {
|
||||
{ EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
|
||||
{ EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
|
||||
{ EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
|
||||
{ EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
|
||||
false, false, false,
|
||||
{1, 1, 2, 2, 10, 10, 11, 11 } },
|
||||
{ EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
|
||||
false, false, true,
|
||||
{ 1, 2, 6, 7, 9 } },
|
||||
{ EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
|
||||
false, false, false,
|
||||
{ 36, 64, 100, 36, 64, 100 } },
|
||||
{ EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
|
||||
false, false, true,
|
||||
{ 36, 60, 100 } },
|
||||
{ EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
|
||||
false, false, false,
|
||||
{ 13, 13 } },
|
||||
{ EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
|
||||
false, false, false,
|
||||
{ 140, 140 } },
|
||||
{ EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
|
||||
false, false, true,
|
||||
{ 132, 44 } },
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM related functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* The device's EEPROM semaphore prevents conflicts between driver and uCode
|
||||
* when accessing the EEPROM; each access is a series of pulses to/from the
|
||||
* EEPROM chip, not a single event, so even reads could conflict if they
|
||||
* weren't arbitrated by the semaphore.
|
||||
*/
|
||||
int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
|
||||
{
|
||||
u16 count;
|
||||
int ret;
|
||||
|
||||
for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
|
||||
/* Request semaphore */
|
||||
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
|
||||
|
||||
/* See if we got it */
|
||||
ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
|
||||
EEPROM_SEM_TIMEOUT);
|
||||
if (ret >= 0) {
|
||||
IWL_DEBUG_IO(priv,
|
||||
"Acquired semaphore after %d tries.\n",
|
||||
count+1);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
|
||||
|
||||
}
|
||||
|
||||
int iwl_eeprom_check_version(struct iwl_priv *priv)
|
||||
{
|
||||
u16 eeprom_ver;
|
||||
u16 calib_ver;
|
||||
|
||||
eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
|
||||
calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv);
|
||||
|
||||
if (eeprom_ver < priv->cfg->eeprom_ver ||
|
||||
calib_ver < priv->cfg->eeprom_calib_ver)
|
||||
goto err;
|
||||
|
||||
IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
|
||||
eeprom_ver, calib_ver);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
|
||||
"CALIB=0x%x < 0x%x\n",
|
||||
eeprom_ver, priv->cfg->eeprom_ver,
|
||||
calib_ver, priv->cfg->eeprom_calib_ver);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
|
||||
{
|
||||
const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
|
||||
EEPROM_MAC_ADDRESS);
|
||||
memcpy(mac, addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_get_max_txpower_avg - get the highest tx power from all chains.
|
||||
* find the highest tx power from all chains for the channel
|
||||
*/
|
||||
static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||
int element, s8 *max_txpower_in_half_dbm)
|
||||
{
|
||||
s8 max_txpower_avg = 0; /* (dBm) */
|
||||
|
||||
IWL_DEBUG_INFO(priv, "%d - "
|
||||
"chain_a: %d dB chain_b: %d dB "
|
||||
"chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
|
||||
element,
|
||||
enhanced_txpower[element].chain_a_max >> 1,
|
||||
enhanced_txpower[element].chain_b_max >> 1,
|
||||
enhanced_txpower[element].chain_c_max >> 1,
|
||||
enhanced_txpower[element].mimo2_max >> 1,
|
||||
enhanced_txpower[element].mimo3_max >> 1);
|
||||
/* Take the highest tx power from any valid chains */
|
||||
if ((priv->cfg->valid_tx_ant & ANT_A) &&
|
||||
(enhanced_txpower[element].chain_a_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_a_max;
|
||||
if ((priv->cfg->valid_tx_ant & ANT_B) &&
|
||||
(enhanced_txpower[element].chain_b_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_b_max;
|
||||
if ((priv->cfg->valid_tx_ant & ANT_C) &&
|
||||
(enhanced_txpower[element].chain_c_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_c_max;
|
||||
if (((priv->cfg->valid_tx_ant == ANT_AB) |
|
||||
(priv->cfg->valid_tx_ant == ANT_BC) |
|
||||
(priv->cfg->valid_tx_ant == ANT_AC)) &&
|
||||
(enhanced_txpower[element].mimo2_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].mimo2_max;
|
||||
if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
|
||||
(enhanced_txpower[element].mimo3_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].mimo3_max;
|
||||
|
||||
/*
|
||||
* max. tx power in EEPROM is in 1/2 dBm format
|
||||
* convert from 1/2 dBm to dBm (round-up convert)
|
||||
* but we also do not want to loss 1/2 dBm resolution which
|
||||
* will impact performance
|
||||
*/
|
||||
*max_txpower_in_half_dbm = max_txpower_avg;
|
||||
return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_update_common_txpower: update channel tx power
|
||||
* update tx power per band based on EEPROM enhanced tx power info.
|
||||
*/
|
||||
static s8 iwl_update_common_txpower(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||
int section, int element, s8 *max_txpower_in_half_dbm)
|
||||
{
|
||||
struct iwl_channel_info *ch_info;
|
||||
int ch;
|
||||
bool is_ht40 = false;
|
||||
s8 max_txpower_avg; /* (dBm) */
|
||||
|
||||
/* it is common section, contain all type (Legacy, HT and HT40)
|
||||
* based on the element in the section to determine
|
||||
* is it HT 40 or not
|
||||
*/
|
||||
if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
|
||||
is_ht40 = true;
|
||||
max_txpower_avg =
|
||||
iwl_get_max_txpower_avg(priv, enhanced_txpower,
|
||||
element, max_txpower_in_half_dbm);
|
||||
|
||||
ch_info = priv->channel_info;
|
||||
|
||||
for (ch = 0; ch < priv->channel_count; ch++) {
|
||||
/* find matching band and update tx power if needed */
|
||||
if ((ch_info->band == enhinfo[section].band) &&
|
||||
(ch_info->max_power_avg < max_txpower_avg) &&
|
||||
(!is_ht40)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->max_power_avg = ch_info->curr_txpow =
|
||||
max_txpower_avg;
|
||||
ch_info->scan_power = max_txpower_avg;
|
||||
}
|
||||
if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
|
||||
(ch_info->ht40_max_power_avg < max_txpower_avg)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->ht40_max_power_avg = max_txpower_avg;
|
||||
}
|
||||
ch_info++;
|
||||
}
|
||||
return max_txpower_avg;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_update_channel_txpower: update channel tx power
|
||||
* update channel tx power based on EEPROM enhanced tx power info.
|
||||
*/
|
||||
static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||
int section, int element, s8 *max_txpower_in_half_dbm)
|
||||
{
|
||||
struct iwl_channel_info *ch_info;
|
||||
int ch;
|
||||
u8 channel;
|
||||
s8 max_txpower_avg; /* (dBm) */
|
||||
|
||||
channel = enhinfo[section].iwl_eeprom_section_channel[element];
|
||||
max_txpower_avg =
|
||||
iwl_get_max_txpower_avg(priv, enhanced_txpower,
|
||||
element, max_txpower_in_half_dbm);
|
||||
|
||||
ch_info = priv->channel_info;
|
||||
for (ch = 0; ch < priv->channel_count; ch++) {
|
||||
/* find matching channel and update tx power if needed */
|
||||
if (ch_info->channel == channel) {
|
||||
if ((ch_info->max_power_avg < max_txpower_avg) &&
|
||||
(!enhinfo[section].is_ht40)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->max_power_avg = max_txpower_avg;
|
||||
ch_info->curr_txpow = max_txpower_avg;
|
||||
ch_info->scan_power = max_txpower_avg;
|
||||
}
|
||||
if ((enhinfo[section].is_ht40) &&
|
||||
(ch_info->ht40_max_power_avg < max_txpower_avg)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->ht40_max_power_avg = max_txpower_avg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ch_info++;
|
||||
}
|
||||
return max_txpower_avg;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
|
||||
*/
|
||||
void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
|
||||
{
|
||||
int eeprom_section_count = 0;
|
||||
int section, element;
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
|
||||
u32 offset;
|
||||
s8 max_txpower_avg; /* (dBm) */
|
||||
s8 max_txpower_in_half_dbm; /* (half-dBm) */
|
||||
|
||||
/* Loop through all the sections
|
||||
* adjust bands and channel's max tx power
|
||||
* Set the tx_power_user_lmt to the highest power
|
||||
* supported by any channels and chains
|
||||
*/
|
||||
for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
|
||||
eeprom_section_count = enhinfo[section].count;
|
||||
offset = enhinfo[section].offset;
|
||||
enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
|
||||
iwl_eeprom_query_addr(priv, offset);
|
||||
|
||||
/*
|
||||
* check for valid entry -
|
||||
* different version of EEPROM might contain different set
|
||||
* of enhanced tx power table
|
||||
* always check for valid entry before process
|
||||
* the information
|
||||
*/
|
||||
if (!enhanced_txpower->common || enhanced_txpower->reserved)
|
||||
continue;
|
||||
|
||||
for (element = 0; element < eeprom_section_count; element++) {
|
||||
if (enhinfo[section].is_common)
|
||||
max_txpower_avg =
|
||||
iwl_update_common_txpower(priv,
|
||||
enhanced_txpower, section,
|
||||
element,
|
||||
&max_txpower_in_half_dbm);
|
||||
else
|
||||
max_txpower_avg =
|
||||
iwl_update_channel_txpower(priv,
|
||||
enhanced_txpower, section,
|
||||
element,
|
||||
&max_txpower_in_half_dbm);
|
||||
|
||||
/* Update the tx_power_user_lmt to the highest power
|
||||
* supported by any channel */
|
||||
if (max_txpower_avg > priv->tx_power_user_lmt)
|
||||
priv->tx_power_user_lmt = max_txpower_avg;
|
||||
|
||||
/*
|
||||
* Update the tx_power_lmt_in_half_dbm to
|
||||
* the highest power supported by any channel
|
||||
*/
|
||||
if (max_txpower_in_half_dbm >
|
||||
priv->tx_power_lmt_in_half_dbm)
|
||||
priv->tx_power_lmt_in_half_dbm =
|
||||
max_txpower_in_half_dbm;
|
||||
}
|
||||
}
|
||||
}
|
@ -360,8 +360,8 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv)
|
||||
|
||||
struct iwl_hcmd_ops iwlagn_hcmd = {
|
||||
.rxon_assoc = iwlagn_send_rxon_assoc,
|
||||
.commit_rxon = iwl_commit_rxon,
|
||||
.set_rxon_chain = iwl_set_rxon_chain,
|
||||
.commit_rxon = iwlagn_commit_rxon,
|
||||
.set_rxon_chain = iwlagn_set_rxon_chain,
|
||||
.set_tx_ant = iwlagn_send_tx_ant_config,
|
||||
.send_bt_config = iwl_send_bt_config,
|
||||
.set_pan_params = iwlagn_set_pan_params,
|
||||
@ -369,8 +369,8 @@ struct iwl_hcmd_ops iwlagn_hcmd = {
|
||||
|
||||
struct iwl_hcmd_ops iwlagn_bt_hcmd = {
|
||||
.rxon_assoc = iwlagn_send_rxon_assoc,
|
||||
.commit_rxon = iwl_commit_rxon,
|
||||
.set_rxon_chain = iwl_set_rxon_chain,
|
||||
.commit_rxon = iwlagn_commit_rxon,
|
||||
.set_rxon_chain = iwlagn_set_rxon_chain,
|
||||
.set_tx_ant = iwlagn_send_tx_ant_config,
|
||||
.send_bt_config = iwlagn_send_advance_bt_config,
|
||||
.set_pan_params = iwlagn_set_pan_params,
|
||||
@ -384,4 +384,5 @@ struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
|
||||
.tx_cmd_protection = iwlagn_tx_cmd_protection,
|
||||
.calc_rssi = iwlagn_calc_rssi,
|
||||
.request_scan = iwlagn_request_scan,
|
||||
.post_scan = iwlagn_post_scan,
|
||||
};
|
||||
|
@ -685,6 +685,23 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwlagn_set_pwr_vmain(struct iwl_priv *priv)
|
||||
{
|
||||
/*
|
||||
* (for documentation purposes)
|
||||
* to set power to V_AUX, do:
|
||||
|
||||
if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
|
||||
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
|
||||
~APMG_PS_CTRL_MSK_PWR_SRC);
|
||||
*/
|
||||
|
||||
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
|
||||
~APMG_PS_CTRL_MSK_PWR_SRC);
|
||||
}
|
||||
|
||||
int iwlagn_hw_nic_init(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
@ -700,7 +717,7 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
|
||||
iwlagn_set_pwr_vmain(priv);
|
||||
|
||||
priv->cfg->ops->lib->apm_ops.config(priv);
|
||||
|
||||
@ -1430,35 +1447,35 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist)
|
||||
scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
|
||||
scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED;
|
||||
break;
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
rate = IWL_RATE_6M_PLCP;
|
||||
/*
|
||||
* If active scanning is requested but a certain channel is
|
||||
* marked passive, we can do active scanning if we detect
|
||||
* transmissions.
|
||||
*
|
||||
* There is an issue with some firmware versions that triggers
|
||||
* a sysassert on a "good CRC threshold" of zero (== disabled),
|
||||
* on a radar channel even though this means that we should NOT
|
||||
* send probes.
|
||||
*
|
||||
* The "good CRC threshold" is the number of frames that we
|
||||
* need to receive during our dwell time on a channel before
|
||||
* sending out probes -- setting this to a huge value will
|
||||
* mean we never reach it, but at the same time work around
|
||||
* the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
|
||||
* here instead of IWL_GOOD_CRC_TH_DISABLED.
|
||||
*/
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
|
||||
IWL_GOOD_CRC_TH_NEVER;
|
||||
break;
|
||||
default:
|
||||
IWL_WARN(priv, "Invalid scan band\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* If active scanning is requested but a certain channel is
|
||||
* marked passive, we can do active scanning if we detect
|
||||
* transmissions.
|
||||
*
|
||||
* There is an issue with some firmware versions that triggers
|
||||
* a sysassert on a "good CRC threshold" of zero (== disabled),
|
||||
* on a radar channel even though this means that we should NOT
|
||||
* send probes.
|
||||
*
|
||||
* The "good CRC threshold" is the number of frames that we
|
||||
* need to receive during our dwell time on a channel before
|
||||
* sending out probes -- setting this to a huge value will
|
||||
* mean we never reach it, but at the same time work around
|
||||
* the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
|
||||
* here instead of IWL_GOOD_CRC_TH_DISABLED.
|
||||
*/
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
|
||||
IWL_GOOD_CRC_TH_NEVER;
|
||||
|
||||
band = priv->scan_band;
|
||||
|
||||
if (priv->cfg->scan_rx_antennas[band])
|
||||
@ -1548,13 +1565,15 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
cmd.data = scan;
|
||||
scan->len = cpu_to_le16(cmd.len);
|
||||
|
||||
/* set scan bit here for PAN params */
|
||||
set_bit(STATUS_SCAN_HW, &priv->status);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_pan_params) {
|
||||
ret = priv->cfg->ops->hcmd->set_pan_params(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
set_bit(STATUS_SCAN_HW, &priv->status);
|
||||
ret = iwl_send_cmd_sync(priv, &cmd);
|
||||
if (ret) {
|
||||
clear_bit(STATUS_SCAN_HW, &priv->status);
|
||||
@ -1565,15 +1584,31 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwlagn_post_scan(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
/*
|
||||
* Since setting the RXON may have been deferred while
|
||||
* performing the scan, fire one off if needed
|
||||
*/
|
||||
for_each_context(priv, ctx)
|
||||
if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
|
||||
iwlagn_commit_rxon(priv, ctx);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_pan_params)
|
||||
priv->cfg->ops->hcmd->set_pan_params(priv);
|
||||
}
|
||||
|
||||
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add)
|
||||
{
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
|
||||
if (add)
|
||||
return iwl_add_bssid_station(priv, vif_priv->ctx,
|
||||
vif->bss_conf.bssid, true,
|
||||
&vif_priv->ibss_bssid_sta_id);
|
||||
return iwlagn_add_bssid_station(priv, vif_priv->ctx,
|
||||
vif->bss_conf.bssid,
|
||||
&vif_priv->ibss_bssid_sta_id);
|
||||
return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
|
||||
vif->bss_conf.bssid);
|
||||
}
|
||||
@ -2049,3 +2084,290 @@ void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv)
|
||||
{
|
||||
cancel_work_sync(&priv->bt_traffic_change_work);
|
||||
}
|
||||
|
||||
static bool is_single_rx_stream(struct iwl_priv *priv)
|
||||
{
|
||||
return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
|
||||
priv->current_ht_config.single_chain_sufficient;
|
||||
}
|
||||
|
||||
#define IWL_NUM_RX_CHAINS_MULTIPLE 3
|
||||
#define IWL_NUM_RX_CHAINS_SINGLE 2
|
||||
#define IWL_NUM_IDLE_CHAINS_DUAL 2
|
||||
#define IWL_NUM_IDLE_CHAINS_SINGLE 1
|
||||
|
||||
/*
|
||||
* Determine how many receiver/antenna chains to use.
|
||||
*
|
||||
* More provides better reception via diversity. Fewer saves power
|
||||
* at the expense of throughput, but only when not in powersave to
|
||||
* start with.
|
||||
*
|
||||
* MIMO (dual stream) requires at least 2, but works better with 3.
|
||||
* This does not determine *which* chains to use, just how many.
|
||||
*/
|
||||
static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
(priv->bt_full_concurrent ||
|
||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
||||
/*
|
||||
* only use chain 'A' in bt high traffic load or
|
||||
* full concurrency mode
|
||||
*/
|
||||
return IWL_NUM_RX_CHAINS_SINGLE;
|
||||
}
|
||||
/* # of Rx chains to use when expecting MIMO. */
|
||||
if (is_single_rx_stream(priv))
|
||||
return IWL_NUM_RX_CHAINS_SINGLE;
|
||||
else
|
||||
return IWL_NUM_RX_CHAINS_MULTIPLE;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we are in power saving mode, unless device support spatial
|
||||
* multiplexing power save, use the active count for rx chain count.
|
||||
*/
|
||||
static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
|
||||
{
|
||||
/* # Rx chains when idling, depending on SMPS mode */
|
||||
switch (priv->current_ht_config.smps) {
|
||||
case IEEE80211_SMPS_STATIC:
|
||||
case IEEE80211_SMPS_DYNAMIC:
|
||||
return IWL_NUM_IDLE_CHAINS_SINGLE;
|
||||
case IEEE80211_SMPS_OFF:
|
||||
return active_cnt;
|
||||
default:
|
||||
WARN(1, "invalid SMPS mode %d",
|
||||
priv->current_ht_config.smps);
|
||||
return active_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
/* up to 4 chains */
|
||||
static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
|
||||
{
|
||||
u8 res;
|
||||
res = (chain_bitmap & BIT(0)) >> 0;
|
||||
res += (chain_bitmap & BIT(1)) >> 1;
|
||||
res += (chain_bitmap & BIT(2)) >> 2;
|
||||
res += (chain_bitmap & BIT(3)) >> 3;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwlagn_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
|
||||
*
|
||||
* Selects how many and which Rx receivers/antennas/chains to use.
|
||||
* This should not be used for scan command ... it puts data in wrong place.
|
||||
*/
|
||||
void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
bool is_single = is_single_rx_stream(priv);
|
||||
bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
|
||||
u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
|
||||
u32 active_chains;
|
||||
u16 rx_chain;
|
||||
|
||||
/* Tell uCode which antennas are actually connected.
|
||||
* Before first association, we assume all antennas are connected.
|
||||
* Just after first association, iwl_chain_noise_calibration()
|
||||
* checks which antennas actually *are* connected. */
|
||||
if (priv->chain_noise_data.active_chains)
|
||||
active_chains = priv->chain_noise_data.active_chains;
|
||||
else
|
||||
active_chains = priv->hw_params.valid_rx_ant;
|
||||
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
(priv->bt_full_concurrent ||
|
||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
||||
/*
|
||||
* only use chain 'A' in bt high traffic load or
|
||||
* full concurrency mode
|
||||
*/
|
||||
active_chains = first_antenna(active_chains);
|
||||
}
|
||||
|
||||
rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
|
||||
|
||||
/* How many receivers should we use? */
|
||||
active_rx_cnt = iwl_get_active_rx_chain_count(priv);
|
||||
idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
|
||||
|
||||
|
||||
/* correct rx chain count according hw settings
|
||||
* and chain noise calibration
|
||||
*/
|
||||
valid_rx_cnt = iwl_count_chain_bitmap(active_chains);
|
||||
if (valid_rx_cnt < active_rx_cnt)
|
||||
active_rx_cnt = valid_rx_cnt;
|
||||
|
||||
if (valid_rx_cnt < idle_rx_cnt)
|
||||
idle_rx_cnt = valid_rx_cnt;
|
||||
|
||||
rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
|
||||
rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
|
||||
|
||||
ctx->staging.rx_chain = cpu_to_le16(rx_chain);
|
||||
|
||||
if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
|
||||
ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
|
||||
else
|
||||
ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
|
||||
ctx->staging.rx_chain,
|
||||
active_rx_cnt, idle_rx_cnt);
|
||||
|
||||
WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
|
||||
active_rx_cnt < idle_rx_cnt);
|
||||
}
|
||||
|
||||
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
|
||||
{
|
||||
int i;
|
||||
u8 ind = ant;
|
||||
|
||||
if (priv->band == IEEE80211_BAND_2GHZ &&
|
||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < RATE_ANT_NUM - 1; i++) {
|
||||
ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
|
||||
if (valid & BIT(ind))
|
||||
return ind;
|
||||
}
|
||||
return ant;
|
||||
}
|
||||
|
||||
static const char *get_csr_string(int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
IWL_CMD(CSR_HW_IF_CONFIG_REG);
|
||||
IWL_CMD(CSR_INT_COALESCING);
|
||||
IWL_CMD(CSR_INT);
|
||||
IWL_CMD(CSR_INT_MASK);
|
||||
IWL_CMD(CSR_FH_INT_STATUS);
|
||||
IWL_CMD(CSR_GPIO_IN);
|
||||
IWL_CMD(CSR_RESET);
|
||||
IWL_CMD(CSR_GP_CNTRL);
|
||||
IWL_CMD(CSR_HW_REV);
|
||||
IWL_CMD(CSR_EEPROM_REG);
|
||||
IWL_CMD(CSR_EEPROM_GP);
|
||||
IWL_CMD(CSR_OTP_GP_REG);
|
||||
IWL_CMD(CSR_GIO_REG);
|
||||
IWL_CMD(CSR_GP_UCODE_REG);
|
||||
IWL_CMD(CSR_GP_DRIVER_REG);
|
||||
IWL_CMD(CSR_UCODE_DRV_GP1);
|
||||
IWL_CMD(CSR_UCODE_DRV_GP2);
|
||||
IWL_CMD(CSR_LED_REG);
|
||||
IWL_CMD(CSR_DRAM_INT_TBL_REG);
|
||||
IWL_CMD(CSR_GIO_CHICKEN_BITS);
|
||||
IWL_CMD(CSR_ANA_PLL_CFG);
|
||||
IWL_CMD(CSR_HW_REV_WA_REG);
|
||||
IWL_CMD(CSR_DBG_HPET_MEM_REG);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_dump_csr(struct iwl_priv *priv)
|
||||
{
|
||||
int i;
|
||||
u32 csr_tbl[] = {
|
||||
CSR_HW_IF_CONFIG_REG,
|
||||
CSR_INT_COALESCING,
|
||||
CSR_INT,
|
||||
CSR_INT_MASK,
|
||||
CSR_FH_INT_STATUS,
|
||||
CSR_GPIO_IN,
|
||||
CSR_RESET,
|
||||
CSR_GP_CNTRL,
|
||||
CSR_HW_REV,
|
||||
CSR_EEPROM_REG,
|
||||
CSR_EEPROM_GP,
|
||||
CSR_OTP_GP_REG,
|
||||
CSR_GIO_REG,
|
||||
CSR_GP_UCODE_REG,
|
||||
CSR_GP_DRIVER_REG,
|
||||
CSR_UCODE_DRV_GP1,
|
||||
CSR_UCODE_DRV_GP2,
|
||||
CSR_LED_REG,
|
||||
CSR_DRAM_INT_TBL_REG,
|
||||
CSR_GIO_CHICKEN_BITS,
|
||||
CSR_ANA_PLL_CFG,
|
||||
CSR_HW_REV_WA_REG,
|
||||
CSR_DBG_HPET_MEM_REG
|
||||
};
|
||||
IWL_ERR(priv, "CSR values:\n");
|
||||
IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is "
|
||||
"CSR_INT_PERIODIC_REG)\n");
|
||||
for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) {
|
||||
IWL_ERR(priv, " %25s: 0X%08x\n",
|
||||
get_csr_string(csr_tbl[i]),
|
||||
iwl_read32(priv, csr_tbl[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_fh_string(int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
|
||||
IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
|
||||
IWL_CMD(FH_RSCSR_CHNL0_WPTR);
|
||||
IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
|
||||
IWL_CMD(FH_TSSR_TX_STATUS_REG);
|
||||
IWL_CMD(FH_TSSR_TX_ERROR_REG);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
|
||||
{
|
||||
int i;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
int pos = 0;
|
||||
size_t bufsz = 0;
|
||||
#endif
|
||||
u32 fh_tbl[] = {
|
||||
FH_RSCSR_CHNL0_STTS_WPTR_REG,
|
||||
FH_RSCSR_CHNL0_RBDCB_BASE_REG,
|
||||
FH_RSCSR_CHNL0_WPTR,
|
||||
FH_MEM_RCSR_CHNL0_CONFIG_REG,
|
||||
FH_MEM_RSSR_SHARED_CTRL_REG,
|
||||
FH_MEM_RSSR_RX_STATUS_REG,
|
||||
FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
|
||||
FH_TSSR_TX_STATUS_REG,
|
||||
FH_TSSR_TX_ERROR_REG
|
||||
};
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (display) {
|
||||
bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
|
||||
*buf = kmalloc(bufsz, GFP_KERNEL);
|
||||
if (!*buf)
|
||||
return -ENOMEM;
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
"FH register values:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
" %34s: 0X%08x\n",
|
||||
get_fh_string(fh_tbl[i]),
|
||||
iwl_read_direct32(priv, fh_tbl[i]));
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
#endif
|
||||
IWL_ERR(priv, "FH register values:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
|
||||
IWL_ERR(priv, " %34s: 0X%08x\n",
|
||||
get_fh_string(fh_tbl[i]),
|
||||
iwl_read_direct32(priv, fh_tbl[i]));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-agn.h"
|
||||
|
||||
#define RS_NAME "iwl-agn-rs"
|
||||
|
||||
@ -76,6 +77,74 @@ static const u8 ant_toggle_lookup[] = {
|
||||
/*ANT_ABC -> */ ANT_ABC,
|
||||
};
|
||||
|
||||
#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \
|
||||
[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
|
||||
IWL_RATE_SISO_##s##M_PLCP, \
|
||||
IWL_RATE_MIMO2_##s##M_PLCP,\
|
||||
IWL_RATE_MIMO3_##s##M_PLCP,\
|
||||
IWL_RATE_##r##M_IEEE, \
|
||||
IWL_RATE_##ip##M_INDEX, \
|
||||
IWL_RATE_##in##M_INDEX, \
|
||||
IWL_RATE_##rp##M_INDEX, \
|
||||
IWL_RATE_##rn##M_INDEX, \
|
||||
IWL_RATE_##pp##M_INDEX, \
|
||||
IWL_RATE_##np##M_INDEX }
|
||||
|
||||
/*
|
||||
* Parameter order:
|
||||
* rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
|
||||
*
|
||||
* If there isn't a valid next or previous rate then INV is used which
|
||||
* maps to IWL_RATE_INVALID
|
||||
*
|
||||
*/
|
||||
const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
|
||||
IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2), /* 1mbps */
|
||||
IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5), /* 2mbps */
|
||||
IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11), /*5.5mbps */
|
||||
IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18), /* 11mbps */
|
||||
IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11), /* 6mbps */
|
||||
IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11), /* 9mbps */
|
||||
IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18), /* 12mbps */
|
||||
IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24), /* 18mbps */
|
||||
IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36), /* 24mbps */
|
||||
IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48), /* 36mbps */
|
||||
IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54), /* 48mbps */
|
||||
IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */
|
||||
IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
|
||||
/* FIXME:RS: ^^ should be INV (legacy) */
|
||||
};
|
||||
|
||||
static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
/* HT rate format */
|
||||
if (rate_n_flags & RATE_MCS_HT_MSK) {
|
||||
idx = (rate_n_flags & 0xff);
|
||||
|
||||
if (idx >= IWL_RATE_MIMO3_6M_PLCP)
|
||||
idx = idx - IWL_RATE_MIMO3_6M_PLCP;
|
||||
else if (idx >= IWL_RATE_MIMO2_6M_PLCP)
|
||||
idx = idx - IWL_RATE_MIMO2_6M_PLCP;
|
||||
|
||||
idx += IWL_FIRST_OFDM_RATE;
|
||||
/* skip 9M not supported in ht*/
|
||||
if (idx >= IWL_RATE_9M_INDEX)
|
||||
idx += 1;
|
||||
if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE))
|
||||
return idx;
|
||||
|
||||
/* legacy rate format, search for match in table */
|
||||
} else {
|
||||
for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++)
|
||||
if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
|
||||
return idx;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void rs_rate_scale_perform(struct iwl_priv *priv,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta,
|
||||
|
@ -299,7 +299,6 @@ enum {
|
||||
#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
|
||||
|
||||
extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
|
||||
extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
|
||||
|
||||
enum iwl_table_type {
|
||||
LQ_NONE,
|
||||
@ -453,15 +452,6 @@ static inline u8 first_antenna(u8 mask)
|
||||
}
|
||||
|
||||
|
||||
static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
|
||||
{
|
||||
u8 rate = iwl3945_rates[rate_index].prev_ieee;
|
||||
|
||||
if (rate == IWL_RATE_INVALID)
|
||||
rate = rate_index;
|
||||
return rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info
|
||||
*
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-calib.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-helpers.h"
|
||||
|
716
drivers/net/wireless/iwlwifi/iwl-agn-sta.c
Normal file
716
drivers/net/wireless/iwlwifi/iwl-agn-sta.c
Normal file
@ -0,0 +1,716 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-agn.h"
|
||||
|
||||
static struct iwl_link_quality_cmd *
|
||||
iwl_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id)
|
||||
{
|
||||
int i, r;
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
u32 rate_flags = 0;
|
||||
__le32 rate_n_flags;
|
||||
|
||||
link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
|
||||
if (!link_cmd) {
|
||||
IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
|
||||
return NULL;
|
||||
}
|
||||
/* Set up the rate scaling to start at selected rate, fall back
|
||||
* all the way down to 1M in IEEE order, and then spin on 1M */
|
||||
if (priv->band == IEEE80211_BAND_5GHZ)
|
||||
r = IWL_RATE_6M_INDEX;
|
||||
else
|
||||
r = IWL_RATE_1M_INDEX;
|
||||
|
||||
if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
|
||||
rate_flags |= RATE_MCS_CCK_MSK;
|
||||
|
||||
rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
|
||||
RATE_MCS_ANT_POS;
|
||||
rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
|
||||
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
|
||||
link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
|
||||
|
||||
link_cmd->general_params.single_stream_ant_msk =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
|
||||
link_cmd->general_params.dual_stream_ant_msk =
|
||||
priv->hw_params.valid_tx_ant &
|
||||
~first_antenna(priv->hw_params.valid_tx_ant);
|
||||
if (!link_cmd->general_params.dual_stream_ant_msk) {
|
||||
link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
|
||||
} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
|
||||
link_cmd->general_params.dual_stream_ant_msk =
|
||||
priv->hw_params.valid_tx_ant;
|
||||
}
|
||||
|
||||
link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
|
||||
link_cmd->agg_params.agg_time_limit =
|
||||
cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
|
||||
|
||||
link_cmd->sta_id = sta_id;
|
||||
|
||||
return link_cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* iwlagn_add_bssid_station - Add the special IBSS BSSID station
|
||||
*
|
||||
* Function sleeps.
|
||||
*/
|
||||
int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, u8 *sta_id_r)
|
||||
{
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
unsigned long flags;
|
||||
|
||||
if (sta_id_r)
|
||||
*sta_id_r = IWL_INVALID_STATION;
|
||||
|
||||
ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Unable to add station %pM\n", addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sta_id_r)
|
||||
*sta_id_r = sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].used |= IWL_STA_LOCAL;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
/* Set up default rate scaling table in device's station table */
|
||||
link_cmd = iwl_sta_alloc_lq(priv, sta_id);
|
||||
if (!link_cmd) {
|
||||
IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",
|
||||
addr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = iwl_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].lq = link_cmd;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
bool send_if_empty)
|
||||
{
|
||||
int i, not_empty = 0;
|
||||
u8 buff[sizeof(struct iwl_wep_cmd) +
|
||||
sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
|
||||
struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
|
||||
size_t cmd_size = sizeof(struct iwl_wep_cmd);
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = ctx->wep_key_cmd,
|
||||
.data = wep_cmd,
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
|
||||
might_sleep();
|
||||
|
||||
memset(wep_cmd, 0, cmd_size +
|
||||
(sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
|
||||
|
||||
for (i = 0; i < WEP_KEYS_MAX ; i++) {
|
||||
wep_cmd->key[i].key_index = i;
|
||||
if (ctx->wep_keys[i].key_size) {
|
||||
wep_cmd->key[i].key_offset = i;
|
||||
not_empty = 1;
|
||||
} else {
|
||||
wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
|
||||
}
|
||||
|
||||
wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
|
||||
memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
|
||||
ctx->wep_keys[i].key_size);
|
||||
}
|
||||
|
||||
wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
|
||||
wep_cmd->num_keys = WEP_KEYS_MAX;
|
||||
|
||||
cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
|
||||
|
||||
cmd.len = cmd_size;
|
||||
|
||||
if (not_empty || send_if_empty)
|
||||
return iwl_send_cmd(priv, &cmd);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_restore_default_wep_keys(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
return iwl_send_static_wepkey_cmd(priv, ctx, false);
|
||||
}
|
||||
|
||||
int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
|
||||
keyconf->keyidx);
|
||||
|
||||
memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
|
||||
/* but keys in device are clear anyway so return success */
|
||||
return 0;
|
||||
}
|
||||
ret = iwl_send_static_wepkey_cmd(priv, ctx, 1);
|
||||
IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
|
||||
keyconf->keyidx, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_set_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (keyconf->keylen != WEP_KEY_LEN_128 &&
|
||||
keyconf->keylen != WEP_KEY_LEN_64) {
|
||||
IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
keyconf->hw_key_idx = HW_KEY_DEFAULT;
|
||||
priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
|
||||
|
||||
ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
|
||||
memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
|
||||
keyconf->keylen);
|
||||
|
||||
ret = iwl_send_static_wepkey_cmd(priv, ctx, false);
|
||||
IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
|
||||
keyconf->keylen, keyconf->keyidx, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
__le16 key_flags = 0;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
|
||||
key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
|
||||
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
key_flags &= ~STA_KEY_FLG_INVALID;
|
||||
|
||||
if (keyconf->keylen == WEP_KEY_LEN_128)
|
||||
key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
|
||||
|
||||
if (sta_id == ctx->bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
|
||||
priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
|
||||
priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
|
||||
|
||||
memcpy(priv->stations[sta_id].keyinfo.key,
|
||||
keyconf->key, keyconf->keylen);
|
||||
|
||||
memcpy(&priv->stations[sta_id].sta.key.key[3],
|
||||
keyconf->key, keyconf->keylen);
|
||||
|
||||
if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
|
||||
== STA_KEY_FLG_NO_ENC)
|
||||
priv->stations[sta_id].sta.key.key_offset =
|
||||
iwl_get_free_ucode_key_index(priv);
|
||||
/* else, we are overriding an existing key => no need to allocated room
|
||||
* in uCode. */
|
||||
|
||||
WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
|
||||
"no space for a new key");
|
||||
|
||||
priv->stations[sta_id].sta.key.key_flags = key_flags;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
|
||||
static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
__le16 key_flags = 0;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
|
||||
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
key_flags &= ~STA_KEY_FLG_INVALID;
|
||||
|
||||
if (sta_id == ctx->bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
|
||||
priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
|
||||
|
||||
memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
|
||||
keyconf->keylen);
|
||||
|
||||
memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
|
||||
keyconf->keylen);
|
||||
|
||||
if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
|
||||
== STA_KEY_FLG_NO_ENC)
|
||||
priv->stations[sta_id].sta.key.key_offset =
|
||||
iwl_get_free_ucode_key_index(priv);
|
||||
/* else, we are overriding an existing key => no need to allocated room
|
||||
* in uCode. */
|
||||
|
||||
WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
|
||||
"no space for a new key");
|
||||
|
||||
priv->stations[sta_id].sta.key.key_flags = key_flags;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
|
||||
static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
__le16 key_flags = 0;
|
||||
|
||||
key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
|
||||
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
key_flags &= ~STA_KEY_FLG_INVALID;
|
||||
|
||||
if (sta_id == ctx->bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
|
||||
priv->stations[sta_id].keyinfo.keylen = 16;
|
||||
|
||||
if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
|
||||
== STA_KEY_FLG_NO_ENC)
|
||||
priv->stations[sta_id].sta.key.key_offset =
|
||||
iwl_get_free_ucode_key_index(priv);
|
||||
/* else, we are overriding an existing key => no need to allocated room
|
||||
* in uCode. */
|
||||
|
||||
WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
|
||||
"no space for a new key");
|
||||
|
||||
priv->stations[sta_id].sta.key.key_flags = key_flags;
|
||||
|
||||
|
||||
/* This copy is acutally not needed: we get the key with each TX */
|
||||
memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
|
||||
|
||||
memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_update_tkip_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
|
||||
{
|
||||
u8 sta_id;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
if (iwl_scan_cancel(priv)) {
|
||||
/* cancel scan failed, just live w/ bad key and rely
|
||||
briefly on SW decryption */
|
||||
return;
|
||||
}
|
||||
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
|
||||
cpu_to_le16(phase1key[i]);
|
||||
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
}
|
||||
|
||||
int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
u16 key_flags;
|
||||
u8 keyidx;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
ctx->key_mapping_keys--;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
|
||||
keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
|
||||
|
||||
IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
|
||||
keyconf->keyidx, sta_id);
|
||||
|
||||
if (keyconf->keyidx != keyidx) {
|
||||
/* We need to remove a key with index different that the one
|
||||
* in the uCode. This means that the key we need to remove has
|
||||
* been replaced by another one with different index.
|
||||
* Don't do anything and return ok
|
||||
*/
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
|
||||
IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
|
||||
keyconf->keyidx, key_flags);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
|
||||
&priv->ucode_key_table))
|
||||
IWL_ERR(priv, "index %d not used in uCode key table.\n",
|
||||
priv->stations[sta_id].sta.key.key_offset);
|
||||
memset(&priv->stations[sta_id].keyinfo, 0,
|
||||
sizeof(struct iwl_hw_key));
|
||||
memset(&priv->stations[sta_id].sta.key, 0,
|
||||
sizeof(struct iwl4965_keyinfo));
|
||||
priv->stations[sta_id].sta.key.key_flags =
|
||||
STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
|
||||
priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
|
||||
int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf, u8 sta_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
ctx->key_mapping_keys++;
|
||||
keyconf->hw_key_idx = HW_KEY_DYNAMIC;
|
||||
|
||||
switch (keyconf->cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id);
|
||||
break;
|
||||
default:
|
||||
IWL_ERR(priv,
|
||||
"Unknown alg: %s cipher = %x\n", __func__,
|
||||
keyconf->cipher);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
|
||||
keyconf->cipher, keyconf->keylen, keyconf->keyidx,
|
||||
sta_id, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwlagn_alloc_bcast_station - add broadcast station into driver's station table.
|
||||
*
|
||||
* This adds the broadcast station into the driver's station table
|
||||
* and marks it driver active, so that it will be restored to the
|
||||
* device at the next best time.
|
||||
*/
|
||||
int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
unsigned long flags;
|
||||
u8 sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Unable to prepare broadcast station\n");
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
|
||||
priv->stations[sta_id].used |= IWL_STA_BCAST;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
link_cmd = iwl_sta_alloc_lq(priv, sta_id);
|
||||
if (!link_cmd) {
|
||||
IWL_ERR(priv,
|
||||
"Unable to initialize rate scaling for bcast station.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].lq = link_cmd;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_update_bcast_station - update broadcast station's LQ command
|
||||
*
|
||||
* Only used by iwlagn. Placed here to have all bcast station management
|
||||
* code together.
|
||||
*/
|
||||
static int iwl_update_bcast_station(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
u8 sta_id = ctx->bcast_sta_id;
|
||||
|
||||
link_cmd = iwl_sta_alloc_lq(priv, sta_id);
|
||||
if (!link_cmd) {
|
||||
IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
if (priv->stations[sta_id].lq)
|
||||
kfree(priv->stations[sta_id].lq);
|
||||
else
|
||||
IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
|
||||
priv->stations[sta_id].lq = link_cmd;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_update_bcast_stations(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
int ret = 0;
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
ret = iwl_update_bcast_station(priv, ctx);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
|
||||
*/
|
||||
int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
/* Remove "disable" flag, to enable Tx for this TID */
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
|
||||
priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
|
||||
int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -ENXIO;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags_msk = 0;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
|
||||
priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
|
||||
priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags_msk = 0;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
|
||||
priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
|
||||
void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = 0;
|
||||
priv->stations[sta_id].sta.sleep_tx_count = 0;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
}
|
||||
|
||||
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.sta.modify_mask =
|
||||
STA_MODIFY_SLEEP_TX_COUNT_MSK;
|
||||
priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
}
|
@ -571,7 +571,6 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
|
||||
IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
|
||||
queue_work(priv->workqueue, &priv->ct_enter);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
|
||||
|
||||
void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
|
||||
{
|
||||
@ -581,7 +580,6 @@ void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
|
||||
IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
|
||||
queue_work(priv->workqueue, &priv->ct_exit);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_tt_exit_ct_kill);
|
||||
|
||||
static void iwl_bg_tt_work(struct work_struct *work)
|
||||
{
|
||||
@ -608,7 +606,6 @@ void iwl_tt_handler(struct iwl_priv *priv)
|
||||
IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
|
||||
queue_work(priv->workqueue, &priv->tt_work);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_tt_handler);
|
||||
|
||||
/* Thermal throttling initialization
|
||||
* For advance thermal throttling:
|
||||
@ -678,7 +675,6 @@ void iwl_tt_initialize(struct iwl_priv *priv)
|
||||
priv->thermal_throttle.advanced_tt = false;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_tt_initialize);
|
||||
|
||||
/* cleanup thermal throttling management related memory and timer */
|
||||
void iwl_tt_exit(struct iwl_priv *priv)
|
||||
@ -701,4 +697,3 @@ void iwl_tt_exit(struct iwl_priv *priv)
|
||||
tt->transaction = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_tt_exit);
|
||||
|
@ -1391,3 +1391,43 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
const char *iwl_get_tx_fail_reason(u32 status)
|
||||
{
|
||||
#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
|
||||
#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
|
||||
|
||||
switch (status & TX_STATUS_MSK) {
|
||||
case TX_STATUS_SUCCESS:
|
||||
return "SUCCESS";
|
||||
TX_STATUS_POSTPONE(DELAY);
|
||||
TX_STATUS_POSTPONE(FEW_BYTES);
|
||||
TX_STATUS_POSTPONE(BT_PRIO);
|
||||
TX_STATUS_POSTPONE(QUIET_PERIOD);
|
||||
TX_STATUS_POSTPONE(CALC_TTAK);
|
||||
TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
|
||||
TX_STATUS_FAIL(SHORT_LIMIT);
|
||||
TX_STATUS_FAIL(LONG_LIMIT);
|
||||
TX_STATUS_FAIL(FIFO_UNDERRUN);
|
||||
TX_STATUS_FAIL(DRAIN_FLOW);
|
||||
TX_STATUS_FAIL(RFKILL_FLUSH);
|
||||
TX_STATUS_FAIL(LIFE_EXPIRE);
|
||||
TX_STATUS_FAIL(DEST_PS);
|
||||
TX_STATUS_FAIL(HOST_ABORTED);
|
||||
TX_STATUS_FAIL(BT_RETRY);
|
||||
TX_STATUS_FAIL(STA_INVALID);
|
||||
TX_STATUS_FAIL(FRAG_DROPPED);
|
||||
TX_STATUS_FAIL(TID_DISABLE);
|
||||
TX_STATUS_FAIL(FIFO_FLUSHED);
|
||||
TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
|
||||
TX_STATUS_FAIL(PASSIVE_NO_RX);
|
||||
TX_STATUS_FAIL(NO_BEACON_ON_RADAR);
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
|
||||
#undef TX_STATUS_FAIL
|
||||
#undef TX_STATUS_POSTPONE
|
||||
}
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
|
||||
static const s8 iwlagn_default_queue_to_tx_fifo[] = {
|
||||
IWL_TX_FIFO_VO,
|
||||
@ -214,6 +215,25 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv)
|
||||
(u8 *)&cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_calib_temperature_offset_cmd cmd;
|
||||
__le16 *offset_calib =
|
||||
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE);
|
||||
cmd.hdr.op_code = IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD;
|
||||
cmd.hdr.first_group = 0;
|
||||
cmd.hdr.groups_num = 1;
|
||||
cmd.hdr.data_valid = 1;
|
||||
cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]);
|
||||
if (!(cmd.radio_sensor_offset))
|
||||
cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
|
||||
cmd.reserved = 0;
|
||||
IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
|
||||
cmd.radio_sensor_offset);
|
||||
return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET],
|
||||
(u8 *)&cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_calib_cfg_cmd calib_cfg_cmd;
|
||||
@ -320,6 +340,14 @@ void iwlagn_init_alive_start(struct iwl_priv *priv)
|
||||
|
||||
}
|
||||
iwlagn_send_calib_cfg(priv);
|
||||
|
||||
/**
|
||||
* temperature offset calibration is only needed for runtime ucode,
|
||||
* so prepare the value now.
|
||||
*/
|
||||
if (priv->cfg->need_temp_offset_calib)
|
||||
iwlagn_set_temperature_offset_calib(priv);
|
||||
|
||||
return;
|
||||
|
||||
restart:
|
||||
|
@ -57,7 +57,7 @@
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-calib.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
#include "iwl-agn.h"
|
||||
|
||||
|
||||
@ -91,14 +91,14 @@ static int iwlagn_ant_coupling;
|
||||
static bool iwlagn_bt_ch_announce = 1;
|
||||
|
||||
/**
|
||||
* iwl_commit_rxon - commit staging_rxon to hardware
|
||||
* iwlagn_commit_rxon - commit staging_rxon to hardware
|
||||
*
|
||||
* The RXON command in staging_rxon is committed to the hardware and
|
||||
* the active_rxon structure is updated with the new data. This
|
||||
* function correctly transitions out of the RXON_ASSOC_MSK state if
|
||||
* a HW tune is required based on the RXON structure changes.
|
||||
*/
|
||||
int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
/* cast away the const for active_rxon in this function */
|
||||
struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
|
||||
@ -314,24 +314,26 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
|
||||
}
|
||||
|
||||
static u32 iwl_fill_beacon_frame(struct iwl_priv *priv,
|
||||
struct ieee80211_hdr *hdr,
|
||||
int left)
|
||||
struct ieee80211_hdr *hdr,
|
||||
int left)
|
||||
{
|
||||
if (!priv->ibss_beacon)
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (!priv->beacon_skb)
|
||||
return 0;
|
||||
|
||||
if (priv->ibss_beacon->len > left)
|
||||
if (priv->beacon_skb->len > left)
|
||||
return 0;
|
||||
|
||||
memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
|
||||
memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
|
||||
|
||||
return priv->ibss_beacon->len;
|
||||
return priv->beacon_skb->len;
|
||||
}
|
||||
|
||||
/* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
|
||||
static void iwl_set_beacon_tim(struct iwl_priv *priv,
|
||||
struct iwl_tx_beacon_cmd *tx_beacon_cmd,
|
||||
u8 *beacon, u32 frame_size)
|
||||
struct iwl_tx_beacon_cmd *tx_beacon_cmd,
|
||||
u8 *beacon, u32 frame_size)
|
||||
{
|
||||
u16 tim_idx;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
|
||||
@ -383,6 +385,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
|
||||
sizeof(frame->u) - sizeof(*tx_beacon_cmd));
|
||||
if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
|
||||
return 0;
|
||||
if (!frame_size)
|
||||
return 0;
|
||||
|
||||
/* Set up TX command fields */
|
||||
tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
|
||||
@ -393,7 +397,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
|
||||
|
||||
/* Set up TX beacon command fields */
|
||||
iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame,
|
||||
frame_size);
|
||||
frame_size);
|
||||
|
||||
/* Set up packet rate and flags */
|
||||
rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx);
|
||||
@ -648,15 +652,14 @@ static void iwl_bg_beacon_update(struct work_struct *work)
|
||||
/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
|
||||
beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif);
|
||||
if (!beacon) {
|
||||
IWL_ERR(priv, "update beacon failed\n");
|
||||
IWL_ERR(priv, "update beacon failed -- keeping old\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* new beacon skb is allocated every time; dispose previous.*/
|
||||
if (priv->ibss_beacon)
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
|
||||
priv->ibss_beacon = beacon;
|
||||
priv->beacon_skb = beacon;
|
||||
|
||||
iwl_send_beacon_cmd(priv);
|
||||
out:
|
||||
@ -935,22 +938,6 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
}
|
||||
|
||||
int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
|
||||
{
|
||||
if (src == IWL_PWR_SRC_VAUX) {
|
||||
if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
|
||||
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
|
||||
~APMG_PS_CTRL_MSK_PWR_SRC);
|
||||
} else {
|
||||
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
|
||||
~APMG_PS_CTRL_MSK_PWR_SRC);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_bg_tx_flush(struct work_struct *work)
|
||||
{
|
||||
struct iwl_priv *priv =
|
||||
@ -2078,7 +2065,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
struct iwlagn_ucode_capabilities ucode_capa = {
|
||||
.max_probe_length = 200,
|
||||
.standard_phy_calibration_size =
|
||||
IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE,
|
||||
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE,
|
||||
};
|
||||
|
||||
memset(&pieces, 0, sizeof(pieces));
|
||||
@ -2120,18 +2107,23 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
* firmware filename ... but we don't check for that and only rely
|
||||
* on the API version read from firmware header from here on forward
|
||||
*/
|
||||
if (api_ver < api_min || api_ver > api_max) {
|
||||
IWL_ERR(priv, "Driver unable to support your firmware API. "
|
||||
"Driver supports v%u, firmware is v%u.\n",
|
||||
api_max, api_ver);
|
||||
goto try_again;
|
||||
}
|
||||
/* no api version check required for experimental uCode */
|
||||
if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) {
|
||||
if (api_ver < api_min || api_ver > api_max) {
|
||||
IWL_ERR(priv,
|
||||
"Driver unable to support your firmware API. "
|
||||
"Driver supports v%u, firmware is v%u.\n",
|
||||
api_max, api_ver);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (api_ver != api_max)
|
||||
IWL_ERR(priv, "Firmware has old API version. Expected v%u, "
|
||||
"got v%u. New firmware can be obtained "
|
||||
"from http://www.intellinuxwireless.org.\n",
|
||||
api_max, api_ver);
|
||||
if (api_ver != api_max)
|
||||
IWL_ERR(priv,
|
||||
"Firmware has old API version. Expected v%u, "
|
||||
"got v%u. New firmware can be obtained "
|
||||
"from http://www.intellinuxwireless.org.\n",
|
||||
api_max, api_ver);
|
||||
}
|
||||
|
||||
if (build)
|
||||
sprintf(buildstr, " build %u%s", build,
|
||||
@ -2820,9 +2812,6 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
||||
goto restart;
|
||||
}
|
||||
|
||||
if (priv->hw_params.calib_rt_cfg)
|
||||
iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
|
||||
|
||||
|
||||
/* After the ALIVE response, we can send host commands to the uCode */
|
||||
set_bit(STATUS_ALIVE, &priv->status);
|
||||
@ -2838,6 +2827,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
||||
if (iwl_is_rfkill(priv))
|
||||
return;
|
||||
|
||||
/* download priority table before any calibration request */
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
/* Configure Bluetooth device coexistence support */
|
||||
@ -2846,8 +2836,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
||||
priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
|
||||
priv->cfg->ops->hcmd->send_bt_config(priv);
|
||||
priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
|
||||
if (bt_coex_active && priv->iw_mode != NL80211_IFTYPE_ADHOC)
|
||||
iwlagn_send_prio_tbl(priv);
|
||||
iwlagn_send_prio_tbl(priv);
|
||||
|
||||
/* FIXME: w/a to force change uCode BT state machine */
|
||||
iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
|
||||
@ -2855,6 +2844,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
||||
iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
||||
}
|
||||
if (priv->hw_params.calib_rt_cfg)
|
||||
iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
|
||||
|
||||
ieee80211_wake_queues(priv->hw);
|
||||
|
||||
priv->active_rate = IWL_RATES_MASK;
|
||||
@ -2999,14 +2991,13 @@ static void __iwl_down(struct iwl_priv *priv)
|
||||
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
|
||||
/* Stop the device, and put it in low power state */
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
iwl_apm_stop(priv);
|
||||
|
||||
exit:
|
||||
memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
|
||||
|
||||
if (priv->ibss_beacon)
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
priv->ibss_beacon = NULL;
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
priv->beacon_skb = NULL;
|
||||
|
||||
/* clear out any free frames */
|
||||
iwl_clear_free_frames(priv);
|
||||
@ -3089,7 +3080,7 @@ static int __iwl_up(struct iwl_priv *priv)
|
||||
}
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
ret = iwl_alloc_bcast_station(priv, ctx, true);
|
||||
ret = iwlagn_alloc_bcast_station(priv, ctx);
|
||||
if (ret) {
|
||||
iwl_dealloc_bcast_stations(priv);
|
||||
return ret;
|
||||
@ -4142,8 +4133,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
priv->ibss_beacon = NULL;
|
||||
|
||||
spin_lock_init(&priv->sta_lock);
|
||||
spin_lock_init(&priv->hcmd_lock);
|
||||
|
||||
@ -4613,7 +4602,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
|
||||
* paths to avoid running iwl_down() at all before leaving driver.
|
||||
* This (inexpensive) call *makes sure* device is reset.
|
||||
*/
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
iwl_apm_stop(priv);
|
||||
|
||||
iwl_tt_exit(priv);
|
||||
|
||||
@ -4656,8 +4645,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
iwl_free_isr_ict(priv);
|
||||
|
||||
if (priv->ibss_beacon)
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
|
||||
ieee80211_free_hw(priv->hw);
|
||||
}
|
||||
|
@ -129,6 +129,10 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask);
|
||||
void iwl_free_tfds_in_queue(struct iwl_priv *priv,
|
||||
int sta_id, int tid, int freed);
|
||||
|
||||
/* RXON */
|
||||
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
|
||||
/* uCode */
|
||||
int iwlagn_load_ucode(struct iwl_priv *priv);
|
||||
void iwlagn_rx_calib_result(struct iwl_priv *priv,
|
||||
@ -158,6 +162,8 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv);
|
||||
int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
|
||||
int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
|
||||
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
|
||||
void iwl_dump_csr(struct iwl_priv *priv);
|
||||
int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
|
||||
|
||||
/* rx */
|
||||
void iwlagn_rx_queue_restock(struct iwl_priv *priv);
|
||||
@ -171,8 +177,15 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwl_rx_handle(struct iwl_priv *priv);
|
||||
|
||||
/* tx */
|
||||
void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
|
||||
int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
|
||||
struct iwl_tx_queue *txq,
|
||||
dma_addr_t addr, u16 len, u8 reset, u8 pad);
|
||||
int iwl_hw_tx_queue_init(struct iwl_priv *priv,
|
||||
struct iwl_tx_queue *txq);
|
||||
void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
|
||||
struct ieee80211_tx_info *info);
|
||||
int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
|
||||
@ -212,6 +225,8 @@ static inline bool iwl_is_tx_success(u32 status)
|
||||
(status == TX_STATUS_DIRECT_DONE);
|
||||
}
|
||||
|
||||
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
|
||||
|
||||
/* rx */
|
||||
void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
@ -224,6 +239,7 @@ void iwl_reply_statistics(struct iwl_priv *priv,
|
||||
|
||||
/* scan */
|
||||
int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
void iwlagn_post_scan(struct iwl_priv *priv);
|
||||
|
||||
/* station mgmt */
|
||||
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
||||
@ -243,8 +259,63 @@ void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);
|
||||
void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
const char *iwl_get_tx_fail_reason(u32 status);
|
||||
const char *iwl_get_agg_tx_fail_reason(u16 status);
|
||||
#else
|
||||
static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; }
|
||||
static inline const char *iwl_get_agg_tx_fail_reason(u16 status) { return ""; }
|
||||
#endif
|
||||
|
||||
/* station management */
|
||||
int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, u8 *sta_id_r);
|
||||
int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key);
|
||||
int iwl_set_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key);
|
||||
int iwl_restore_default_wep_keys(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key, u8 sta_id);
|
||||
int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key, u8 sta_id);
|
||||
void iwl_update_tkip_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
|
||||
int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
|
||||
int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn);
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid);
|
||||
void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id);
|
||||
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
|
||||
int iwl_update_bcast_stations(struct iwl_priv *priv);
|
||||
|
||||
/* rate */
|
||||
static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
|
||||
{
|
||||
return BIT(ant_idx) << RATE_MCS_ANT_POS;
|
||||
}
|
||||
|
||||
static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
|
||||
{
|
||||
return le32_to_cpu(rate_n_flags) & 0xFF;
|
||||
}
|
||||
|
||||
static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
|
||||
{
|
||||
return cpu_to_le32(flags|(u32)rate);
|
||||
}
|
||||
|
||||
/* eeprom */
|
||||
void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv);
|
||||
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
|
||||
int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
|
||||
void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
|
||||
|
||||
#endif /* __iwl_agn_h__ */
|
||||
|
@ -3784,7 +3784,8 @@ struct iwl_enhance_sensitivity_cmd {
|
||||
*/
|
||||
|
||||
/* Phy calibration command for series */
|
||||
|
||||
/* The default calibrate table size if not specified by firmware */
|
||||
#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18
|
||||
enum {
|
||||
IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
|
||||
IWL_PHY_CALIBRATE_DC_CMD = 8,
|
||||
@ -3793,7 +3794,8 @@ enum {
|
||||
IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
|
||||
IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
|
||||
IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
|
||||
IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 18,
|
||||
IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD = 18,
|
||||
IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 19,
|
||||
};
|
||||
|
||||
#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE (253)
|
||||
@ -3863,6 +3865,13 @@ struct iwl_calib_xtal_freq_cmd {
|
||||
u8 pad[2];
|
||||
} __packed;
|
||||
|
||||
#define DEFAULT_RADIO_SENSOR_OFFSET 2700
|
||||
struct iwl_calib_temperature_offset_cmd {
|
||||
struct iwl_calib_hdr hdr;
|
||||
s16 radio_sensor_offset;
|
||||
s16 reserved;
|
||||
} __packed;
|
||||
|
||||
/* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
|
||||
struct iwl_calib_chain_noise_reset_cmd {
|
||||
struct iwl_calib_hdr hdr;
|
||||
|
@ -69,97 +69,9 @@ EXPORT_SYMBOL_GPL(bt_coex_active);
|
||||
module_param(bt_coex_active, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
|
||||
|
||||
#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \
|
||||
[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
|
||||
IWL_RATE_SISO_##s##M_PLCP, \
|
||||
IWL_RATE_MIMO2_##s##M_PLCP,\
|
||||
IWL_RATE_MIMO3_##s##M_PLCP,\
|
||||
IWL_RATE_##r##M_IEEE, \
|
||||
IWL_RATE_##ip##M_INDEX, \
|
||||
IWL_RATE_##in##M_INDEX, \
|
||||
IWL_RATE_##rp##M_INDEX, \
|
||||
IWL_RATE_##rn##M_INDEX, \
|
||||
IWL_RATE_##pp##M_INDEX, \
|
||||
IWL_RATE_##np##M_INDEX }
|
||||
|
||||
u32 iwl_debug_level;
|
||||
EXPORT_SYMBOL(iwl_debug_level);
|
||||
|
||||
/*
|
||||
* Parameter order:
|
||||
* rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
|
||||
*
|
||||
* If there isn't a valid next or previous rate then INV is used which
|
||||
* maps to IWL_RATE_INVALID
|
||||
*
|
||||
*/
|
||||
const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
|
||||
IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2), /* 1mbps */
|
||||
IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5), /* 2mbps */
|
||||
IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11), /*5.5mbps */
|
||||
IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18), /* 11mbps */
|
||||
IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11), /* 6mbps */
|
||||
IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11), /* 9mbps */
|
||||
IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18), /* 12mbps */
|
||||
IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24), /* 18mbps */
|
||||
IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36), /* 24mbps */
|
||||
IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48), /* 36mbps */
|
||||
IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54), /* 48mbps */
|
||||
IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */
|
||||
IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
|
||||
/* FIXME:RS: ^^ should be INV (legacy) */
|
||||
};
|
||||
EXPORT_SYMBOL(iwl_rates);
|
||||
|
||||
int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
/* HT rate format */
|
||||
if (rate_n_flags & RATE_MCS_HT_MSK) {
|
||||
idx = (rate_n_flags & 0xff);
|
||||
|
||||
if (idx >= IWL_RATE_MIMO3_6M_PLCP)
|
||||
idx = idx - IWL_RATE_MIMO3_6M_PLCP;
|
||||
else if (idx >= IWL_RATE_MIMO2_6M_PLCP)
|
||||
idx = idx - IWL_RATE_MIMO2_6M_PLCP;
|
||||
|
||||
idx += IWL_FIRST_OFDM_RATE;
|
||||
/* skip 9M not supported in ht*/
|
||||
if (idx >= IWL_RATE_9M_INDEX)
|
||||
idx += 1;
|
||||
if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE))
|
||||
return idx;
|
||||
|
||||
/* legacy rate format, search for match in table */
|
||||
} else {
|
||||
for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++)
|
||||
if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
|
||||
return idx;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx);
|
||||
|
||||
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
|
||||
{
|
||||
int i;
|
||||
u8 ind = ant;
|
||||
|
||||
if (priv->band == IEEE80211_BAND_2GHZ &&
|
||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < RATE_ANT_NUM - 1; i++) {
|
||||
ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
|
||||
if (valid & BIT(ind))
|
||||
return ind;
|
||||
}
|
||||
return ant;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_toggle_tx_ant);
|
||||
|
||||
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
EXPORT_SYMBOL(iwl_bcast_addr);
|
||||
|
||||
@ -439,12 +351,6 @@ void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
|
||||
EXPORT_SYMBOL(iwlcore_tx_cmd_protection);
|
||||
|
||||
|
||||
static bool is_single_rx_stream(struct iwl_priv *priv)
|
||||
{
|
||||
return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
|
||||
priv->current_ht_config.single_chain_sufficient;
|
||||
}
|
||||
|
||||
static bool iwl_is_channel_extension(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
u16 channel, u8 extension_chan_offset)
|
||||
@ -604,76 +510,74 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_rxon_hwcrypto);
|
||||
|
||||
/**
|
||||
* iwl_check_rxon_cmd - validate RXON structure is valid
|
||||
*
|
||||
* NOTE: This is really only useful during development and can eventually
|
||||
* be #ifdef'd out once the driver is stable and folks aren't actively
|
||||
* making changes
|
||||
*/
|
||||
/* validate RXON structure is valid */
|
||||
int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
int error = 0;
|
||||
int counter = 1;
|
||||
struct iwl_rxon_cmd *rxon = &ctx->staging;
|
||||
bool error = false;
|
||||
|
||||
if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
|
||||
error |= le32_to_cpu(rxon->flags &
|
||||
(RXON_FLG_TGJ_NARROW_BAND_MSK |
|
||||
RXON_FLG_RADAR_DETECT_MSK));
|
||||
if (error)
|
||||
IWL_WARN(priv, "check 24G fields %d | %d\n",
|
||||
counter++, error);
|
||||
if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) {
|
||||
IWL_WARN(priv, "check 2.4G: wrong narrow\n");
|
||||
error = true;
|
||||
}
|
||||
if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) {
|
||||
IWL_WARN(priv, "check 2.4G: wrong radar\n");
|
||||
error = true;
|
||||
}
|
||||
} else {
|
||||
error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ?
|
||||
0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK);
|
||||
if (error)
|
||||
IWL_WARN(priv, "check 52 fields %d | %d\n",
|
||||
counter++, error);
|
||||
error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK);
|
||||
if (error)
|
||||
IWL_WARN(priv, "check 52 CCK %d | %d\n",
|
||||
counter++, error);
|
||||
if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) {
|
||||
IWL_WARN(priv, "check 5.2G: not short slot!\n");
|
||||
error = true;
|
||||
}
|
||||
if (rxon->flags & RXON_FLG_CCK_MSK) {
|
||||
IWL_WARN(priv, "check 5.2G: CCK!\n");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) {
|
||||
IWL_WARN(priv, "mac/bssid mcast!\n");
|
||||
error = true;
|
||||
}
|
||||
error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1;
|
||||
if (error)
|
||||
IWL_WARN(priv, "check mac addr %d | %d\n", counter++, error);
|
||||
|
||||
/* make sure basic rates 6Mbps and 1Mbps are supported */
|
||||
error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) &&
|
||||
((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0));
|
||||
if (error)
|
||||
IWL_WARN(priv, "check basic rate %d | %d\n", counter++, error);
|
||||
if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 &&
|
||||
(rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) {
|
||||
IWL_WARN(priv, "neither 1 nor 6 are basic\n");
|
||||
error = true;
|
||||
}
|
||||
|
||||
error |= (le16_to_cpu(rxon->assoc_id) > 2007);
|
||||
if (error)
|
||||
IWL_WARN(priv, "check assoc id %d | %d\n", counter++, error);
|
||||
if (le16_to_cpu(rxon->assoc_id) > 2007) {
|
||||
IWL_WARN(priv, "aid > 2007\n");
|
||||
error = true;
|
||||
}
|
||||
|
||||
error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
|
||||
== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK));
|
||||
if (error)
|
||||
IWL_WARN(priv, "check CCK and short slot %d | %d\n",
|
||||
counter++, error);
|
||||
if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
|
||||
== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) {
|
||||
IWL_WARN(priv, "CCK and short slot\n");
|
||||
error = true;
|
||||
}
|
||||
|
||||
error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
|
||||
== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK));
|
||||
if (error)
|
||||
IWL_WARN(priv, "check CCK & auto detect %d | %d\n",
|
||||
counter++, error);
|
||||
if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
|
||||
== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) {
|
||||
IWL_WARN(priv, "CCK and auto detect");
|
||||
error = true;
|
||||
}
|
||||
|
||||
error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
|
||||
RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK);
|
||||
if (error)
|
||||
IWL_WARN(priv, "check TGG and auto detect %d | %d\n",
|
||||
counter++, error);
|
||||
if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
|
||||
RXON_FLG_TGG_PROTECT_MSK)) ==
|
||||
RXON_FLG_TGG_PROTECT_MSK) {
|
||||
IWL_WARN(priv, "TGg but no auto-detect\n");
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (error)
|
||||
IWL_WARN(priv, "Tuning to channel %d\n",
|
||||
le16_to_cpu(rxon->channel));
|
||||
|
||||
if (error) {
|
||||
IWL_ERR(priv, "Not a valid iwl_rxon_assoc_cmd field values\n");
|
||||
return -1;
|
||||
IWL_ERR(priv, "Invalid RXON\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -834,141 +738,6 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_rxon_ht);
|
||||
|
||||
#define IWL_NUM_RX_CHAINS_MULTIPLE 3
|
||||
#define IWL_NUM_RX_CHAINS_SINGLE 2
|
||||
#define IWL_NUM_IDLE_CHAINS_DUAL 2
|
||||
#define IWL_NUM_IDLE_CHAINS_SINGLE 1
|
||||
|
||||
/*
|
||||
* Determine how many receiver/antenna chains to use.
|
||||
*
|
||||
* More provides better reception via diversity. Fewer saves power
|
||||
* at the expense of throughput, but only when not in powersave to
|
||||
* start with.
|
||||
*
|
||||
* MIMO (dual stream) requires at least 2, but works better with 3.
|
||||
* This does not determine *which* chains to use, just how many.
|
||||
*/
|
||||
static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
(priv->bt_full_concurrent ||
|
||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
||||
/*
|
||||
* only use chain 'A' in bt high traffic load or
|
||||
* full concurrency mode
|
||||
*/
|
||||
return IWL_NUM_RX_CHAINS_SINGLE;
|
||||
}
|
||||
/* # of Rx chains to use when expecting MIMO. */
|
||||
if (is_single_rx_stream(priv))
|
||||
return IWL_NUM_RX_CHAINS_SINGLE;
|
||||
else
|
||||
return IWL_NUM_RX_CHAINS_MULTIPLE;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we are in power saving mode, unless device support spatial
|
||||
* multiplexing power save, use the active count for rx chain count.
|
||||
*/
|
||||
static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
|
||||
{
|
||||
/* # Rx chains when idling, depending on SMPS mode */
|
||||
switch (priv->current_ht_config.smps) {
|
||||
case IEEE80211_SMPS_STATIC:
|
||||
case IEEE80211_SMPS_DYNAMIC:
|
||||
return IWL_NUM_IDLE_CHAINS_SINGLE;
|
||||
case IEEE80211_SMPS_OFF:
|
||||
return active_cnt;
|
||||
default:
|
||||
WARN(1, "invalid SMPS mode %d",
|
||||
priv->current_ht_config.smps);
|
||||
return active_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
/* up to 4 chains */
|
||||
static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
|
||||
{
|
||||
u8 res;
|
||||
res = (chain_bitmap & BIT(0)) >> 0;
|
||||
res += (chain_bitmap & BIT(1)) >> 1;
|
||||
res += (chain_bitmap & BIT(2)) >> 2;
|
||||
res += (chain_bitmap & BIT(3)) >> 3;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
|
||||
*
|
||||
* Selects how many and which Rx receivers/antennas/chains to use.
|
||||
* This should not be used for scan command ... it puts data in wrong place.
|
||||
*/
|
||||
void iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
bool is_single = is_single_rx_stream(priv);
|
||||
bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
|
||||
u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
|
||||
u32 active_chains;
|
||||
u16 rx_chain;
|
||||
|
||||
/* Tell uCode which antennas are actually connected.
|
||||
* Before first association, we assume all antennas are connected.
|
||||
* Just after first association, iwl_chain_noise_calibration()
|
||||
* checks which antennas actually *are* connected. */
|
||||
if (priv->chain_noise_data.active_chains)
|
||||
active_chains = priv->chain_noise_data.active_chains;
|
||||
else
|
||||
active_chains = priv->hw_params.valid_rx_ant;
|
||||
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
(priv->bt_full_concurrent ||
|
||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
||||
/*
|
||||
* only use chain 'A' in bt high traffic load or
|
||||
* full concurrency mode
|
||||
*/
|
||||
active_chains = first_antenna(active_chains);
|
||||
}
|
||||
|
||||
rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
|
||||
|
||||
/* How many receivers should we use? */
|
||||
active_rx_cnt = iwl_get_active_rx_chain_count(priv);
|
||||
idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
|
||||
|
||||
|
||||
/* correct rx chain count according hw settings
|
||||
* and chain noise calibration
|
||||
*/
|
||||
valid_rx_cnt = iwl_count_chain_bitmap(active_chains);
|
||||
if (valid_rx_cnt < active_rx_cnt)
|
||||
active_rx_cnt = valid_rx_cnt;
|
||||
|
||||
if (valid_rx_cnt < idle_rx_cnt)
|
||||
idle_rx_cnt = valid_rx_cnt;
|
||||
|
||||
rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
|
||||
rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
|
||||
|
||||
ctx->staging.rx_chain = cpu_to_le16(rx_chain);
|
||||
|
||||
if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
|
||||
ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
|
||||
else
|
||||
ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
|
||||
ctx->staging.rx_chain,
|
||||
active_rx_cnt, idle_rx_cnt);
|
||||
|
||||
WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
|
||||
active_rx_cnt < idle_rx_cnt);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_rxon_chain);
|
||||
|
||||
/* Return valid, unused, channel for a passive scan to reset the RF */
|
||||
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
|
||||
enum ieee80211_band band)
|
||||
@ -1758,43 +1527,47 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv,
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
|
||||
static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
static void iwlcore_beacon_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
unsigned long flags;
|
||||
__le64 timestamp;
|
||||
struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "enter\n");
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (!priv->beacon_ctx) {
|
||||
IWL_ERR(priv, "update beacon but no beacon context!\n");
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!iwl_is_ready_rf(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
|
||||
return -EIO;
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
if (priv->ibss_beacon)
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
if (priv->beacon_skb)
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
|
||||
priv->ibss_beacon = skb;
|
||||
priv->beacon_skb = skb;
|
||||
|
||||
timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
|
||||
priv->timestamp = le64_to_cpu(timestamp);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
IWL_DEBUG_ASSOC(priv, "leave\n");
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif);
|
||||
if (!iwl_is_ready_rf(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
|
||||
return;
|
||||
}
|
||||
|
||||
return 0;
|
||||
priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif);
|
||||
}
|
||||
|
||||
void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
||||
@ -1835,8 +1608,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
priv->beacon_skb = ieee80211_beacon_get(hw, vif);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
|
||||
@ -1876,13 +1649,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
||||
* mac80211 decides to do both changes at once because
|
||||
* it will invoke post_associate.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC &&
|
||||
changes & BSS_CHANGED_BEACON) {
|
||||
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
|
||||
|
||||
if (beacon)
|
||||
iwl_mac_beacon_update(hw, beacon);
|
||||
}
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
|
||||
iwlcore_beacon_update(hw, vif);
|
||||
|
||||
if (changes & BSS_CHANGED_ERP_PREAMBLE) {
|
||||
IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
|
||||
@ -1959,6 +1727,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
||||
memcpy(ctx->staging.bssid_addr,
|
||||
bss_conf->bssid, ETH_ALEN);
|
||||
memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
|
||||
iwl_led_associate(priv);
|
||||
iwlcore_config_ap(priv, vif);
|
||||
} else
|
||||
iwl_set_no_assoc(priv, vif);
|
||||
@ -2290,10 +2059,10 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* new association get rid of ibss beacon skb */
|
||||
if (priv->ibss_beacon)
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
if (priv->beacon_skb)
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
|
||||
priv->ibss_beacon = NULL;
|
||||
priv->beacon_skb = NULL;
|
||||
|
||||
priv->timestamp = 0;
|
||||
|
||||
@ -2581,140 +2350,6 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
|
||||
EXPORT_SYMBOL(iwl_update_stats);
|
||||
#endif
|
||||
|
||||
static const char *get_csr_string(int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
IWL_CMD(CSR_HW_IF_CONFIG_REG);
|
||||
IWL_CMD(CSR_INT_COALESCING);
|
||||
IWL_CMD(CSR_INT);
|
||||
IWL_CMD(CSR_INT_MASK);
|
||||
IWL_CMD(CSR_FH_INT_STATUS);
|
||||
IWL_CMD(CSR_GPIO_IN);
|
||||
IWL_CMD(CSR_RESET);
|
||||
IWL_CMD(CSR_GP_CNTRL);
|
||||
IWL_CMD(CSR_HW_REV);
|
||||
IWL_CMD(CSR_EEPROM_REG);
|
||||
IWL_CMD(CSR_EEPROM_GP);
|
||||
IWL_CMD(CSR_OTP_GP_REG);
|
||||
IWL_CMD(CSR_GIO_REG);
|
||||
IWL_CMD(CSR_GP_UCODE_REG);
|
||||
IWL_CMD(CSR_GP_DRIVER_REG);
|
||||
IWL_CMD(CSR_UCODE_DRV_GP1);
|
||||
IWL_CMD(CSR_UCODE_DRV_GP2);
|
||||
IWL_CMD(CSR_LED_REG);
|
||||
IWL_CMD(CSR_DRAM_INT_TBL_REG);
|
||||
IWL_CMD(CSR_GIO_CHICKEN_BITS);
|
||||
IWL_CMD(CSR_ANA_PLL_CFG);
|
||||
IWL_CMD(CSR_HW_REV_WA_REG);
|
||||
IWL_CMD(CSR_DBG_HPET_MEM_REG);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_dump_csr(struct iwl_priv *priv)
|
||||
{
|
||||
int i;
|
||||
u32 csr_tbl[] = {
|
||||
CSR_HW_IF_CONFIG_REG,
|
||||
CSR_INT_COALESCING,
|
||||
CSR_INT,
|
||||
CSR_INT_MASK,
|
||||
CSR_FH_INT_STATUS,
|
||||
CSR_GPIO_IN,
|
||||
CSR_RESET,
|
||||
CSR_GP_CNTRL,
|
||||
CSR_HW_REV,
|
||||
CSR_EEPROM_REG,
|
||||
CSR_EEPROM_GP,
|
||||
CSR_OTP_GP_REG,
|
||||
CSR_GIO_REG,
|
||||
CSR_GP_UCODE_REG,
|
||||
CSR_GP_DRIVER_REG,
|
||||
CSR_UCODE_DRV_GP1,
|
||||
CSR_UCODE_DRV_GP2,
|
||||
CSR_LED_REG,
|
||||
CSR_DRAM_INT_TBL_REG,
|
||||
CSR_GIO_CHICKEN_BITS,
|
||||
CSR_ANA_PLL_CFG,
|
||||
CSR_HW_REV_WA_REG,
|
||||
CSR_DBG_HPET_MEM_REG
|
||||
};
|
||||
IWL_ERR(priv, "CSR values:\n");
|
||||
IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is "
|
||||
"CSR_INT_PERIODIC_REG)\n");
|
||||
for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) {
|
||||
IWL_ERR(priv, " %25s: 0X%08x\n",
|
||||
get_csr_string(csr_tbl[i]),
|
||||
iwl_read32(priv, csr_tbl[i]));
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_dump_csr);
|
||||
|
||||
static const char *get_fh_string(int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
|
||||
IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
|
||||
IWL_CMD(FH_RSCSR_CHNL0_WPTR);
|
||||
IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
|
||||
IWL_CMD(FH_TSSR_TX_STATUS_REG);
|
||||
IWL_CMD(FH_TSSR_TX_ERROR_REG);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
|
||||
{
|
||||
int i;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
int pos = 0;
|
||||
size_t bufsz = 0;
|
||||
#endif
|
||||
u32 fh_tbl[] = {
|
||||
FH_RSCSR_CHNL0_STTS_WPTR_REG,
|
||||
FH_RSCSR_CHNL0_RBDCB_BASE_REG,
|
||||
FH_RSCSR_CHNL0_WPTR,
|
||||
FH_MEM_RCSR_CHNL0_CONFIG_REG,
|
||||
FH_MEM_RSSR_SHARED_CTRL_REG,
|
||||
FH_MEM_RSSR_RX_STATUS_REG,
|
||||
FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
|
||||
FH_TSSR_TX_STATUS_REG,
|
||||
FH_TSSR_TX_ERROR_REG
|
||||
};
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (display) {
|
||||
bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
|
||||
*buf = kmalloc(bufsz, GFP_KERNEL);
|
||||
if (!*buf)
|
||||
return -ENOMEM;
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
"FH register values:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
" %34s: 0X%08x\n",
|
||||
get_fh_string(fh_tbl[i]),
|
||||
iwl_read_direct32(priv, fh_tbl[i]));
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
#endif
|
||||
IWL_ERR(priv, "FH register values:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
|
||||
IWL_ERR(priv, " %34s: 0X%08x\n",
|
||||
get_fh_string(fh_tbl[i]),
|
||||
iwl_read_direct32(priv, fh_tbl[i]));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_dump_fh);
|
||||
|
||||
static void iwl_force_rf_reset(struct iwl_priv *priv)
|
||||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
@ -2795,7 +2430,6 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_force_reset);
|
||||
|
||||
/**
|
||||
* iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover
|
||||
@ -2848,13 +2482,10 @@ static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt)
|
||||
"queue %d, not read %d time\n",
|
||||
q->id,
|
||||
q->repeat_same_read_ptr);
|
||||
if (priv->cfg->bt_params &&
|
||||
!priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
mod_timer(&priv->monitor_recover,
|
||||
jiffies + msecs_to_jiffies(
|
||||
IWL_ONE_HUNDRED_MSECS));
|
||||
return 1;
|
||||
}
|
||||
mod_timer(&priv->monitor_recover,
|
||||
jiffies + msecs_to_jiffies(
|
||||
IWL_ONE_HUNDRED_MSECS));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
q->last_read_ptr = q->read_ptr;
|
||||
@ -2964,7 +2595,7 @@ int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
* it will not call apm_ops.stop() to stop the DMA operation.
|
||||
* Calling apm_ops.stop here to make sure we stop the DMA.
|
||||
*/
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
iwl_apm_stop(priv);
|
||||
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
|
@ -112,13 +112,12 @@ struct iwl_hcmd_utils_ops {
|
||||
int (*calc_rssi)(struct iwl_priv *priv,
|
||||
struct iwl_rx_phy_res *rx_resp);
|
||||
int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
void (*post_scan)(struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
struct iwl_apm_ops {
|
||||
int (*init)(struct iwl_priv *priv);
|
||||
void (*stop)(struct iwl_priv *priv);
|
||||
void (*config)(struct iwl_priv *priv);
|
||||
int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
|
||||
};
|
||||
|
||||
struct iwl_debugfs_ops {
|
||||
@ -136,7 +135,6 @@ struct iwl_debugfs_ops {
|
||||
|
||||
struct iwl_temp_ops {
|
||||
void (*temperature)(struct iwl_priv *priv);
|
||||
void (*set_ct_kill)(struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
struct iwl_tt_ops {
|
||||
@ -344,6 +342,7 @@ struct iwl_ht_params {
|
||||
* @ucode_api_min: Lowest version of uCode API supported by driver.
|
||||
* @pa_type: used by 6000 series only to identify the type of Power Amplifier
|
||||
* @need_dc_calib: need to perform init dc calibration
|
||||
* @need_temp_offset_calib: need to perform temperature offset calibration
|
||||
* @scan_antennas: available antenna for scan operation
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt API version. The
|
||||
@ -388,6 +387,7 @@ struct iwl_cfg {
|
||||
struct iwl_bt_params *bt_params;
|
||||
enum iwl_pa_type pa_type; /* if used set to IWL_PA_SYSTEM */
|
||||
const bool need_dc_calib; /* if used set to true */
|
||||
const bool need_temp_offset_calib; /* if used set to true */
|
||||
u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
|
||||
u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
|
||||
};
|
||||
@ -398,7 +398,6 @@ struct iwl_cfg {
|
||||
|
||||
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
|
||||
struct ieee80211_ops *hw_ops);
|
||||
void iwl_activate_qos(struct iwl_priv *priv);
|
||||
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params);
|
||||
int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
|
||||
@ -406,7 +405,6 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
int hw_decrypt);
|
||||
int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
void iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
|
||||
struct iwl_rxon_context *ctx);
|
||||
void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||
@ -432,7 +430,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
u32 changes);
|
||||
int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
@ -509,7 +506,6 @@ void iwl_rx_reply_error(struct iwl_priv *priv,
|
||||
******************************************************/
|
||||
void iwl_cmd_queue_free(struct iwl_priv *priv);
|
||||
int iwl_rx_queue_alloc(struct iwl_priv *priv);
|
||||
void iwl_rx_handle(struct iwl_priv *priv);
|
||||
void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
|
||||
struct iwl_rx_queue *q);
|
||||
int iwl_rx_queue_space(const struct iwl_rx_queue *q);
|
||||
@ -527,12 +523,6 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
|
||||
/*****************************************************
|
||||
* TX
|
||||
******************************************************/
|
||||
void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
|
||||
int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
|
||||
struct iwl_tx_queue *txq,
|
||||
dma_addr_t addr, u16 len, u8 reset, u8 pad);
|
||||
int iwl_hw_tx_queue_init(struct iwl_priv *priv,
|
||||
struct iwl_tx_queue *txq);
|
||||
void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
|
||||
int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
|
||||
int slots_num, u32 txq_id);
|
||||
@ -548,31 +538,9 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
|
||||
* Rate
|
||||
******************************************************************************/
|
||||
|
||||
int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
|
||||
|
||||
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
|
||||
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
|
||||
|
||||
static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
|
||||
{
|
||||
return BIT(ant_idx) << RATE_MCS_ANT_POS;
|
||||
}
|
||||
|
||||
static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
|
||||
{
|
||||
return le32_to_cpu(rate_n_flags) & 0xFF;
|
||||
}
|
||||
static inline u32 iwl_hw_get_rate_n_flags(__le32 rate_n_flags)
|
||||
{
|
||||
return le32_to_cpu(rate_n_flags) & 0x1FFFF;
|
||||
}
|
||||
static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
|
||||
{
|
||||
return cpu_to_le32(flags|(u32)rate);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Scanning
|
||||
******************************************************************************/
|
||||
@ -608,13 +576,6 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
|
||||
|
||||
#define IWL_SCAN_CHECK_WATCHDOG (HZ * 7)
|
||||
|
||||
/*******************************************************************************
|
||||
* Calibrations - implemented in iwl-calib.c
|
||||
******************************************************************************/
|
||||
int iwl_send_calib_results(struct iwl_priv *priv);
|
||||
int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
|
||||
void iwl_calib_free_results(struct iwl_priv *priv);
|
||||
|
||||
/*****************************************************
|
||||
* S e n d i n g H o s t C o m m a n d s *
|
||||
*****************************************************/
|
||||
@ -664,8 +625,6 @@ int iwl_pci_resume(struct pci_dev *pdev);
|
||||
void iwl_dump_nic_error_log(struct iwl_priv *priv);
|
||||
int iwl_dump_nic_event_log(struct iwl_priv *priv,
|
||||
bool full_log, char **buf, bool display);
|
||||
void iwl_dump_csr(struct iwl_priv *priv);
|
||||
int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
@ -751,8 +710,6 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv)
|
||||
extern void iwl_send_bt_config(struct iwl_priv *priv);
|
||||
extern int iwl_send_statistics_request(struct iwl_priv *priv,
|
||||
u8 flags, bool clear);
|
||||
extern int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct iwl_link_quality_cmd *lq, u8 flags, bool init);
|
||||
void iwl_apm_stop(struct iwl_priv *priv);
|
||||
int iwl_apm_init(struct iwl_priv *priv);
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-calib.h"
|
||||
|
||||
/* create and remove of files */
|
||||
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
|
||||
|
@ -282,13 +282,6 @@ struct iwl_channel_info {
|
||||
*/
|
||||
#define IWL_IPAN_MCAST_QUEUE 8
|
||||
|
||||
/* Power management (not Tx power) structures */
|
||||
|
||||
enum iwl_pwr_src {
|
||||
IWL_PWR_SRC_VMAIN,
|
||||
IWL_PWR_SRC_VAUX,
|
||||
};
|
||||
|
||||
#define IEEE80211_DATA_LEN 2304
|
||||
#define IEEE80211_4ADDR_LEN 30
|
||||
#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
|
||||
@ -732,7 +725,6 @@ struct iwl_hw_params {
|
||||
*
|
||||
****************************************************************************/
|
||||
extern void iwl_update_chain_flags(struct iwl_priv *priv);
|
||||
extern int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
|
||||
extern const u8 iwl_bcast_addr[ETH_ALEN];
|
||||
extern int iwl_rxq_stop(struct iwl_priv *priv);
|
||||
extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
|
||||
@ -843,6 +835,7 @@ enum iwl_calib {
|
||||
IWL_CALIB_TX_IQ,
|
||||
IWL_CALIB_TX_IQ_PERD,
|
||||
IWL_CALIB_BASE_BAND,
|
||||
IWL_CALIB_TEMP_OFFSET,
|
||||
IWL_CALIB_MAX
|
||||
};
|
||||
|
||||
@ -1390,8 +1383,6 @@ struct iwl_priv {
|
||||
|
||||
enum nl80211_iftype iw_mode;
|
||||
|
||||
struct sk_buff *ibss_beacon;
|
||||
|
||||
/* Last Rx'd beacon timestamp */
|
||||
u64 timestamp;
|
||||
|
||||
@ -1503,8 +1494,10 @@ struct iwl_priv {
|
||||
struct work_struct scan_completed;
|
||||
struct work_struct rx_replenish;
|
||||
struct work_struct abort_scan;
|
||||
|
||||
struct work_struct beacon_update;
|
||||
struct iwl_rxon_context *beacon_ctx;
|
||||
struct sk_buff *beacon_skb;
|
||||
|
||||
struct work_struct tt_work;
|
||||
struct work_struct ct_enter;
|
||||
@ -1566,7 +1559,6 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
const char *iwl_get_tx_fail_reason(u32 status);
|
||||
/*
|
||||
* iwl_get_debug_level: Return active debug level for device
|
||||
*
|
||||
@ -1582,8 +1574,6 @@ static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
|
||||
return iwl_debug_level;
|
||||
}
|
||||
#else
|
||||
static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; }
|
||||
|
||||
static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
|
||||
{
|
||||
return iwl_debug_level;
|
||||
|
@ -136,85 +136,13 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
|
||||
36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_txpwr_section: eeprom section information
|
||||
* @offset: indirect address into eeprom image
|
||||
* @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
|
||||
* @band: band type for the section
|
||||
* @is_common - true: common section, false: channel section
|
||||
* @is_cck - true: cck section, false: not cck section
|
||||
* @is_ht_40 - true: all channel in the section are HT40 channel,
|
||||
* false: legacy or HT 20 MHz
|
||||
* ignore if it is common section
|
||||
* @iwl_eeprom_section_channel: channel array in the section,
|
||||
* ignore if common section
|
||||
*/
|
||||
struct iwl_txpwr_section {
|
||||
u32 offset;
|
||||
u8 count;
|
||||
enum ieee80211_band band;
|
||||
bool is_common;
|
||||
bool is_cck;
|
||||
bool is_ht40;
|
||||
u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
|
||||
};
|
||||
|
||||
/**
|
||||
* section 1 - 3 are regulatory tx power apply to all channels based on
|
||||
* modulation: CCK, OFDM
|
||||
* Band: 2.4GHz, 5.2GHz
|
||||
* section 4 - 10 are regulatory tx power apply to specified channels
|
||||
* For example:
|
||||
* 1L - Channel 1 Legacy
|
||||
* 1HT - Channel 1 HT
|
||||
* (1,+1) - Channel 1 HT40 "_above_"
|
||||
*
|
||||
* Section 1: all CCK channels
|
||||
* Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
|
||||
* Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
|
||||
* Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
|
||||
* Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
|
||||
* Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
|
||||
* Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
|
||||
* Section 8: 2.4 GHz channel: 13L, 13HT
|
||||
* Section 9: 2.4 GHz channel: 140L, 140HT
|
||||
* Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1)
|
||||
*
|
||||
*/
|
||||
static const struct iwl_txpwr_section enhinfo[] = {
|
||||
{ EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
|
||||
{ EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
|
||||
{ EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
|
||||
{ EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
|
||||
false, false, false,
|
||||
{1, 1, 2, 2, 10, 10, 11, 11 } },
|
||||
{ EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
|
||||
false, false, true,
|
||||
{ 1, 2, 6, 7, 9 } },
|
||||
{ EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
|
||||
false, false, false,
|
||||
{ 36, 64, 100, 36, 64, 100 } },
|
||||
{ EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
|
||||
false, false, true,
|
||||
{ 36, 60, 100 } },
|
||||
{ EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
|
||||
false, false, false,
|
||||
{ 13, 13 } },
|
||||
{ EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
|
||||
false, false, false,
|
||||
{ 140, 140 } },
|
||||
{ EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
|
||||
false, false, true,
|
||||
{ 132, 44 } },
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM related functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
|
||||
static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
|
||||
{
|
||||
u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
|
||||
int ret = 0;
|
||||
@ -246,7 +174,6 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
|
||||
|
||||
static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
|
||||
{
|
||||
@ -290,46 +217,6 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv)
|
||||
return nvm_type;
|
||||
}
|
||||
|
||||
/*
|
||||
* The device's EEPROM semaphore prevents conflicts between driver and uCode
|
||||
* when accessing the EEPROM; each access is a series of pulses to/from the
|
||||
* EEPROM chip, not a single event, so even reads could conflict if they
|
||||
* weren't arbitrated by the semaphore.
|
||||
*/
|
||||
int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
|
||||
{
|
||||
u16 count;
|
||||
int ret;
|
||||
|
||||
for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
|
||||
/* Request semaphore */
|
||||
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
|
||||
|
||||
/* See if we got it */
|
||||
ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
|
||||
EEPROM_SEM_TIMEOUT);
|
||||
if (ret >= 0) {
|
||||
IWL_DEBUG_IO(priv, "Acquired semaphore after %d tries.\n",
|
||||
count+1);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore);
|
||||
|
||||
void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore);
|
||||
|
||||
const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
|
||||
{
|
||||
BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
|
||||
@ -491,6 +378,20 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
|
||||
{
|
||||
return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_eeprom_query_addr);
|
||||
|
||||
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
|
||||
{
|
||||
if (!priv->eeprom)
|
||||
return 0;
|
||||
return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_eeprom_query16);
|
||||
|
||||
/**
|
||||
* iwl_eeprom_init - read EEPROM contents
|
||||
*
|
||||
@ -523,7 +424,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
|
||||
|
||||
priv->cfg->ops->lib->apm_ops.init(priv);
|
||||
|
||||
ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv);
|
||||
ret = iwl_eeprom_verify_signature(priv);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
|
||||
ret = -ENOENT;
|
||||
@ -604,7 +505,7 @@ err:
|
||||
if (ret)
|
||||
iwl_eeprom_free(priv);
|
||||
/* Reset chip to save power until we load uCode during "up". */
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
iwl_apm_stop(priv);
|
||||
alloc_err:
|
||||
return ret;
|
||||
}
|
||||
@ -617,53 +518,6 @@ void iwl_eeprom_free(struct iwl_priv *priv)
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_eeprom_free);
|
||||
|
||||
int iwl_eeprom_check_version(struct iwl_priv *priv)
|
||||
{
|
||||
u16 eeprom_ver;
|
||||
u16 calib_ver;
|
||||
|
||||
eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
|
||||
calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv);
|
||||
|
||||
if (eeprom_ver < priv->cfg->eeprom_ver ||
|
||||
calib_ver < priv->cfg->eeprom_calib_ver)
|
||||
goto err;
|
||||
|
||||
IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
|
||||
eeprom_ver, calib_ver);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
|
||||
eeprom_ver, priv->cfg->eeprom_ver,
|
||||
calib_ver, priv->cfg->eeprom_calib_ver);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_eeprom_check_version);
|
||||
|
||||
const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
|
||||
{
|
||||
return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_eeprom_query_addr);
|
||||
|
||||
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
|
||||
{
|
||||
if (!priv->eeprom)
|
||||
return 0;
|
||||
return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_eeprom_query16);
|
||||
|
||||
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
|
||||
{
|
||||
const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
|
||||
EEPROM_MAC_ADDRESS);
|
||||
memcpy(mac, addr, ETH_ALEN);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_eeprom_get_mac);
|
||||
|
||||
static void iwl_init_band_reference(const struct iwl_priv *priv,
|
||||
int eep_band, int *eeprom_ch_count,
|
||||
const struct iwl_eeprom_channel **eeprom_ch_info,
|
||||
@ -722,7 +576,6 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
|
||||
|
||||
#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
|
||||
? # x " " : "")
|
||||
|
||||
/**
|
||||
* iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv.
|
||||
*
|
||||
@ -766,205 +619,6 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_get_max_txpower_avg - get the highest tx power from all chains.
|
||||
* find the highest tx power from all chains for the channel
|
||||
*/
|
||||
static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||
int element, s8 *max_txpower_in_half_dbm)
|
||||
{
|
||||
s8 max_txpower_avg = 0; /* (dBm) */
|
||||
|
||||
IWL_DEBUG_INFO(priv, "%d - "
|
||||
"chain_a: %d dB chain_b: %d dB "
|
||||
"chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
|
||||
element,
|
||||
enhanced_txpower[element].chain_a_max >> 1,
|
||||
enhanced_txpower[element].chain_b_max >> 1,
|
||||
enhanced_txpower[element].chain_c_max >> 1,
|
||||
enhanced_txpower[element].mimo2_max >> 1,
|
||||
enhanced_txpower[element].mimo3_max >> 1);
|
||||
/* Take the highest tx power from any valid chains */
|
||||
if ((priv->cfg->valid_tx_ant & ANT_A) &&
|
||||
(enhanced_txpower[element].chain_a_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_a_max;
|
||||
if ((priv->cfg->valid_tx_ant & ANT_B) &&
|
||||
(enhanced_txpower[element].chain_b_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_b_max;
|
||||
if ((priv->cfg->valid_tx_ant & ANT_C) &&
|
||||
(enhanced_txpower[element].chain_c_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_c_max;
|
||||
if (((priv->cfg->valid_tx_ant == ANT_AB) |
|
||||
(priv->cfg->valid_tx_ant == ANT_BC) |
|
||||
(priv->cfg->valid_tx_ant == ANT_AC)) &&
|
||||
(enhanced_txpower[element].mimo2_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].mimo2_max;
|
||||
if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
|
||||
(enhanced_txpower[element].mimo3_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].mimo3_max;
|
||||
|
||||
/*
|
||||
* max. tx power in EEPROM is in 1/2 dBm format
|
||||
* convert from 1/2 dBm to dBm (round-up convert)
|
||||
* but we also do not want to loss 1/2 dBm resolution which
|
||||
* will impact performance
|
||||
*/
|
||||
*max_txpower_in_half_dbm = max_txpower_avg;
|
||||
return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_update_common_txpower: update channel tx power
|
||||
* update tx power per band based on EEPROM enhanced tx power info.
|
||||
*/
|
||||
static s8 iwl_update_common_txpower(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||
int section, int element, s8 *max_txpower_in_half_dbm)
|
||||
{
|
||||
struct iwl_channel_info *ch_info;
|
||||
int ch;
|
||||
bool is_ht40 = false;
|
||||
s8 max_txpower_avg; /* (dBm) */
|
||||
|
||||
/* it is common section, contain all type (Legacy, HT and HT40)
|
||||
* based on the element in the section to determine
|
||||
* is it HT 40 or not
|
||||
*/
|
||||
if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
|
||||
is_ht40 = true;
|
||||
max_txpower_avg =
|
||||
iwl_get_max_txpower_avg(priv, enhanced_txpower,
|
||||
element, max_txpower_in_half_dbm);
|
||||
|
||||
ch_info = priv->channel_info;
|
||||
|
||||
for (ch = 0; ch < priv->channel_count; ch++) {
|
||||
/* find matching band and update tx power if needed */
|
||||
if ((ch_info->band == enhinfo[section].band) &&
|
||||
(ch_info->max_power_avg < max_txpower_avg) &&
|
||||
(!is_ht40)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->max_power_avg = ch_info->curr_txpow =
|
||||
max_txpower_avg;
|
||||
ch_info->scan_power = max_txpower_avg;
|
||||
}
|
||||
if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
|
||||
(ch_info->ht40_max_power_avg < max_txpower_avg)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->ht40_max_power_avg = max_txpower_avg;
|
||||
}
|
||||
ch_info++;
|
||||
}
|
||||
return max_txpower_avg;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_update_channel_txpower: update channel tx power
|
||||
* update channel tx power based on EEPROM enhanced tx power info.
|
||||
*/
|
||||
static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||
int section, int element, s8 *max_txpower_in_half_dbm)
|
||||
{
|
||||
struct iwl_channel_info *ch_info;
|
||||
int ch;
|
||||
u8 channel;
|
||||
s8 max_txpower_avg; /* (dBm) */
|
||||
|
||||
channel = enhinfo[section].iwl_eeprom_section_channel[element];
|
||||
max_txpower_avg =
|
||||
iwl_get_max_txpower_avg(priv, enhanced_txpower,
|
||||
element, max_txpower_in_half_dbm);
|
||||
|
||||
ch_info = priv->channel_info;
|
||||
for (ch = 0; ch < priv->channel_count; ch++) {
|
||||
/* find matching channel and update tx power if needed */
|
||||
if (ch_info->channel == channel) {
|
||||
if ((ch_info->max_power_avg < max_txpower_avg) &&
|
||||
(!enhinfo[section].is_ht40)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->max_power_avg = max_txpower_avg;
|
||||
ch_info->curr_txpow = max_txpower_avg;
|
||||
ch_info->scan_power = max_txpower_avg;
|
||||
}
|
||||
if ((enhinfo[section].is_ht40) &&
|
||||
(ch_info->ht40_max_power_avg < max_txpower_avg)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->ht40_max_power_avg = max_txpower_avg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ch_info++;
|
||||
}
|
||||
return max_txpower_avg;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
|
||||
*/
|
||||
void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
|
||||
{
|
||||
int eeprom_section_count = 0;
|
||||
int section, element;
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
|
||||
u32 offset;
|
||||
s8 max_txpower_avg; /* (dBm) */
|
||||
s8 max_txpower_in_half_dbm; /* (half-dBm) */
|
||||
|
||||
/* Loop through all the sections
|
||||
* adjust bands and channel's max tx power
|
||||
* Set the tx_power_user_lmt to the highest power
|
||||
* supported by any channels and chains
|
||||
*/
|
||||
for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
|
||||
eeprom_section_count = enhinfo[section].count;
|
||||
offset = enhinfo[section].offset;
|
||||
enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
|
||||
iwl_eeprom_query_addr(priv, offset);
|
||||
|
||||
/*
|
||||
* check for valid entry -
|
||||
* different version of EEPROM might contain different set
|
||||
* of enhanced tx power table
|
||||
* always check for valid entry before process
|
||||
* the information
|
||||
*/
|
||||
if (!enhanced_txpower->common || enhanced_txpower->reserved)
|
||||
continue;
|
||||
|
||||
for (element = 0; element < eeprom_section_count; element++) {
|
||||
if (enhinfo[section].is_common)
|
||||
max_txpower_avg =
|
||||
iwl_update_common_txpower(priv,
|
||||
enhanced_txpower, section,
|
||||
element,
|
||||
&max_txpower_in_half_dbm);
|
||||
else
|
||||
max_txpower_avg =
|
||||
iwl_update_channel_txpower(priv,
|
||||
enhanced_txpower, section,
|
||||
element,
|
||||
&max_txpower_in_half_dbm);
|
||||
|
||||
/* Update the tx_power_user_lmt to the highest power
|
||||
* supported by any channel */
|
||||
if (max_txpower_avg > priv->tx_power_user_lmt)
|
||||
priv->tx_power_user_lmt = max_txpower_avg;
|
||||
|
||||
/*
|
||||
* Update the tx_power_lmt_in_half_dbm to
|
||||
* the highest power supported by any channel
|
||||
*/
|
||||
if (max_txpower_in_half_dbm >
|
||||
priv->tx_power_lmt_in_half_dbm)
|
||||
priv->tx_power_lmt_in_half_dbm =
|
||||
max_txpower_in_half_dbm;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwlcore_eeprom_enhanced_txpower);
|
||||
|
||||
#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
|
||||
? # x " " : "")
|
||||
|
||||
@ -1162,4 +816,3 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_get_channel_info);
|
||||
|
||||
|
@ -493,7 +493,6 @@ struct iwl_eeprom_calib_info {
|
||||
|
||||
struct iwl_eeprom_ops {
|
||||
const u32 regulatory_bands[7];
|
||||
int (*verify_signature) (struct iwl_priv *priv);
|
||||
int (*acquire_semaphore) (struct iwl_priv *priv);
|
||||
void (*release_semaphore) (struct iwl_priv *priv);
|
||||
u16 (*calib_version) (struct iwl_priv *priv);
|
||||
@ -502,18 +501,13 @@ struct iwl_eeprom_ops {
|
||||
};
|
||||
|
||||
|
||||
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
|
||||
int iwl_eeprom_init(struct iwl_priv *priv);
|
||||
void iwl_eeprom_free(struct iwl_priv *priv);
|
||||
int iwl_eeprom_check_version(struct iwl_priv *priv);
|
||||
const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
|
||||
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
|
||||
|
||||
int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
|
||||
int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
|
||||
void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
|
||||
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
|
||||
const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
|
||||
void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv);
|
||||
int iwl_init_channel_map(struct iwl_priv *priv);
|
||||
void iwl_free_channel_map(struct iwl_priv *priv);
|
||||
const struct iwl_channel_info *iwl_get_channel_info(
|
||||
|
@ -44,11 +44,6 @@ static inline struct ieee80211_conf *ieee80211_get_hw_conf(
|
||||
return &hw->conf;
|
||||
}
|
||||
|
||||
static inline int iwl_check_bits(unsigned long field, unsigned long mask)
|
||||
{
|
||||
return ((field & mask) == mask) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline unsigned long elapsed_jiffies(unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-calib.h"
|
||||
#include "iwl-helpers.h"
|
||||
/************************** RX-FUNCTIONS ****************************/
|
||||
/*
|
||||
|
@ -121,7 +121,6 @@ void iwl_force_scan_end(struct iwl_priv *priv)
|
||||
clear_bit(STATUS_SCAN_ABORTING, &priv->status);
|
||||
iwl_complete_scan(priv, true);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_force_scan_end);
|
||||
|
||||
static void iwl_do_scan_abort(struct iwl_priv *priv)
|
||||
{
|
||||
@ -559,7 +558,6 @@ static void iwl_bg_scan_completed(struct work_struct *work)
|
||||
struct iwl_priv *priv =
|
||||
container_of(work, struct iwl_priv, scan_completed);
|
||||
bool aborted;
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
|
||||
priv->is_internal_short_scan ? "internal short " : "");
|
||||
@ -609,15 +607,7 @@ out_settings:
|
||||
* performing the scan, fire one off */
|
||||
iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
|
||||
|
||||
/*
|
||||
* Since setting the RXON may have been deferred while
|
||||
* performing the scan, fire one off if needed
|
||||
*/
|
||||
for_each_context(priv, ctx)
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_pan_params)
|
||||
priv->cfg->ops->hcmd->set_pan_params(priv);
|
||||
priv->cfg->ops->utils->post_scan(priv);
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
@ -228,9 +228,8 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
|
||||
*
|
||||
* should be called with sta_lock held
|
||||
*/
|
||||
static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool is_ap,
|
||||
struct ieee80211_sta *sta)
|
||||
u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool is_ap, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_station_entry *station;
|
||||
int i;
|
||||
@ -317,6 +316,7 @@ static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
return sta_id;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_prep_station);
|
||||
|
||||
#define STA_WAIT_TIMEOUT (HZ/2)
|
||||
|
||||
@ -381,108 +381,6 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_add_station_common);
|
||||
|
||||
static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv,
|
||||
u8 sta_id)
|
||||
{
|
||||
int i, r;
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
u32 rate_flags = 0;
|
||||
__le32 rate_n_flags;
|
||||
|
||||
link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
|
||||
if (!link_cmd) {
|
||||
IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
|
||||
return NULL;
|
||||
}
|
||||
/* Set up the rate scaling to start at selected rate, fall back
|
||||
* all the way down to 1M in IEEE order, and then spin on 1M */
|
||||
if (priv->band == IEEE80211_BAND_5GHZ)
|
||||
r = IWL_RATE_6M_INDEX;
|
||||
else
|
||||
r = IWL_RATE_1M_INDEX;
|
||||
|
||||
if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
|
||||
rate_flags |= RATE_MCS_CCK_MSK;
|
||||
|
||||
rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
|
||||
RATE_MCS_ANT_POS;
|
||||
rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
|
||||
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
|
||||
link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
|
||||
|
||||
link_cmd->general_params.single_stream_ant_msk =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
|
||||
link_cmd->general_params.dual_stream_ant_msk =
|
||||
priv->hw_params.valid_tx_ant &
|
||||
~first_antenna(priv->hw_params.valid_tx_ant);
|
||||
if (!link_cmd->general_params.dual_stream_ant_msk) {
|
||||
link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
|
||||
} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
|
||||
link_cmd->general_params.dual_stream_ant_msk =
|
||||
priv->hw_params.valid_tx_ant;
|
||||
}
|
||||
|
||||
link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
|
||||
link_cmd->agg_params.agg_time_limit =
|
||||
cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
|
||||
|
||||
link_cmd->sta_id = sta_id;
|
||||
|
||||
return link_cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_add_bssid_station - Add the special IBSS BSSID station
|
||||
*
|
||||
* Function sleeps.
|
||||
*/
|
||||
int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool init_rs, u8 *sta_id_r)
|
||||
{
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
unsigned long flags;
|
||||
|
||||
if (sta_id_r)
|
||||
*sta_id_r = IWL_INVALID_STATION;
|
||||
|
||||
ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Unable to add station %pM\n", addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sta_id_r)
|
||||
*sta_id_r = sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].used |= IWL_STA_LOCAL;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
if (init_rs) {
|
||||
/* Set up default rate scaling table in device's station table */
|
||||
link_cmd = iwl_sta_alloc_lq(priv, sta_id);
|
||||
if (!link_cmd) {
|
||||
IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",
|
||||
addr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = iwl_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].lq = link_cmd;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_add_bssid_station);
|
||||
|
||||
/**
|
||||
* iwl_sta_ucode_deactivate - deactivate ucode status for a station
|
||||
*
|
||||
@ -738,405 +636,25 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_get_free_ucode_key_index);
|
||||
|
||||
static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
bool send_if_empty)
|
||||
void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
|
||||
{
|
||||
int i, not_empty = 0;
|
||||
u8 buff[sizeof(struct iwl_wep_cmd) +
|
||||
sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
|
||||
struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
|
||||
size_t cmd_size = sizeof(struct iwl_wep_cmd);
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = ctx->wep_key_cmd,
|
||||
.data = wep_cmd,
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
|
||||
might_sleep();
|
||||
|
||||
memset(wep_cmd, 0, cmd_size +
|
||||
(sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
|
||||
|
||||
for (i = 0; i < WEP_KEYS_MAX ; i++) {
|
||||
wep_cmd->key[i].key_index = i;
|
||||
if (ctx->wep_keys[i].key_size) {
|
||||
wep_cmd->key[i].key_offset = i;
|
||||
not_empty = 1;
|
||||
} else {
|
||||
wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
|
||||
}
|
||||
|
||||
wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
|
||||
memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
|
||||
ctx->wep_keys[i].key_size);
|
||||
}
|
||||
|
||||
wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
|
||||
wep_cmd->num_keys = WEP_KEYS_MAX;
|
||||
|
||||
cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
|
||||
|
||||
cmd.len = cmd_size;
|
||||
|
||||
if (not_empty || send_if_empty)
|
||||
return iwl_send_cmd(priv, &cmd);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_restore_default_wep_keys(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
return iwl_send_static_wepkey_cmd(priv, ctx, false);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_restore_default_wep_keys);
|
||||
|
||||
int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
|
||||
keyconf->keyidx);
|
||||
|
||||
memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
|
||||
/* but keys in device are clear anyway so return success */
|
||||
return 0;
|
||||
}
|
||||
ret = iwl_send_static_wepkey_cmd(priv, ctx, 1);
|
||||
IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
|
||||
keyconf->keyidx, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_remove_default_wep_key);
|
||||
|
||||
int iwl_set_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (keyconf->keylen != WEP_KEY_LEN_128 &&
|
||||
keyconf->keylen != WEP_KEY_LEN_64) {
|
||||
IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
keyconf->hw_key_idx = HW_KEY_DEFAULT;
|
||||
priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
|
||||
|
||||
ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
|
||||
memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
|
||||
keyconf->keylen);
|
||||
|
||||
ret = iwl_send_static_wepkey_cmd(priv, ctx, false);
|
||||
IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
|
||||
keyconf->keylen, keyconf->keyidx, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_default_wep_key);
|
||||
|
||||
static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
__le16 key_flags = 0;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
|
||||
key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
|
||||
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
key_flags &= ~STA_KEY_FLG_INVALID;
|
||||
|
||||
if (keyconf->keylen == WEP_KEY_LEN_128)
|
||||
key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
|
||||
|
||||
if (sta_id == ctx->bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
|
||||
priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
|
||||
priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
|
||||
|
||||
memcpy(priv->stations[sta_id].keyinfo.key,
|
||||
keyconf->key, keyconf->keylen);
|
||||
|
||||
memcpy(&priv->stations[sta_id].sta.key.key[3],
|
||||
keyconf->key, keyconf->keylen);
|
||||
|
||||
if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
|
||||
== STA_KEY_FLG_NO_ENC)
|
||||
priv->stations[sta_id].sta.key.key_offset =
|
||||
iwl_get_free_ucode_key_index(priv);
|
||||
/* else, we are overriding an existing key => no need to allocated room
|
||||
* in uCode. */
|
||||
|
||||
WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
|
||||
"no space for a new key");
|
||||
|
||||
priv->stations[sta_id].sta.key.key_flags = key_flags;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
|
||||
static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
__le16 key_flags = 0;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
|
||||
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
key_flags &= ~STA_KEY_FLG_INVALID;
|
||||
|
||||
if (sta_id == ctx->bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
|
||||
priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
|
||||
|
||||
memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
|
||||
keyconf->keylen);
|
||||
|
||||
memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
|
||||
keyconf->keylen);
|
||||
|
||||
if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
|
||||
== STA_KEY_FLG_NO_ENC)
|
||||
priv->stations[sta_id].sta.key.key_offset =
|
||||
iwl_get_free_ucode_key_index(priv);
|
||||
/* else, we are overriding an existing key => no need to allocated room
|
||||
* in uCode. */
|
||||
|
||||
WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
|
||||
"no space for a new key");
|
||||
|
||||
priv->stations[sta_id].sta.key.key_flags = key_flags;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
|
||||
static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
__le16 key_flags = 0;
|
||||
|
||||
key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
|
||||
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
key_flags &= ~STA_KEY_FLG_INVALID;
|
||||
|
||||
if (sta_id == ctx->bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
|
||||
priv->stations[sta_id].keyinfo.keylen = 16;
|
||||
|
||||
if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
|
||||
== STA_KEY_FLG_NO_ENC)
|
||||
priv->stations[sta_id].sta.key.key_offset =
|
||||
iwl_get_free_ucode_key_index(priv);
|
||||
/* else, we are overriding an existing key => no need to allocated room
|
||||
* in uCode. */
|
||||
|
||||
WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
|
||||
"no space for a new key");
|
||||
|
||||
priv->stations[sta_id].sta.key.key_flags = key_flags;
|
||||
|
||||
|
||||
/* This copy is acutally not needed: we get the key with each TX */
|
||||
memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
|
||||
|
||||
memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_update_tkip_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
|
||||
{
|
||||
u8 sta_id;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
if (iwl_scan_cancel(priv)) {
|
||||
/* cancel scan failed, just live w/ bad key and rely
|
||||
briefly on SW decryption */
|
||||
return;
|
||||
}
|
||||
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
for (i = 0; i < priv->hw_params.max_stations; i++) {
|
||||
if (!(priv->stations[i].used & IWL_STA_BCAST))
|
||||
continue;
|
||||
|
||||
priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
|
||||
cpu_to_le16(phase1key[i]);
|
||||
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
|
||||
priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
|
||||
priv->num_stations--;
|
||||
BUG_ON(priv->num_stations < 0);
|
||||
kfree(priv->stations[i].lq);
|
||||
priv->stations[i].lq = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_update_tkip_key);
|
||||
|
||||
int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
u16 key_flags;
|
||||
u8 keyidx;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
ctx->key_mapping_keys--;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
|
||||
keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
|
||||
|
||||
IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
|
||||
keyconf->keyidx, sta_id);
|
||||
|
||||
if (keyconf->keyidx != keyidx) {
|
||||
/* We need to remove a key with index different that the one
|
||||
* in the uCode. This means that the key we need to remove has
|
||||
* been replaced by another one with different index.
|
||||
* Don't do anything and return ok
|
||||
*/
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
|
||||
IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
|
||||
keyconf->keyidx, key_flags);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
|
||||
&priv->ucode_key_table))
|
||||
IWL_ERR(priv, "index %d not used in uCode key table.\n",
|
||||
priv->stations[sta_id].sta.key.key_offset);
|
||||
memset(&priv->stations[sta_id].keyinfo, 0,
|
||||
sizeof(struct iwl_hw_key));
|
||||
memset(&priv->stations[sta_id].sta.key, 0,
|
||||
sizeof(struct iwl4965_keyinfo));
|
||||
priv->stations[sta_id].sta.key.key_flags =
|
||||
STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
|
||||
priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_remove_dynamic_key);
|
||||
|
||||
int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf, u8 sta_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
ctx->key_mapping_keys++;
|
||||
keyconf->hw_key_idx = HW_KEY_DYNAMIC;
|
||||
|
||||
switch (keyconf->cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id);
|
||||
break;
|
||||
default:
|
||||
IWL_ERR(priv,
|
||||
"Unknown alg: %s cipher = %x\n", __func__,
|
||||
keyconf->cipher);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
|
||||
keyconf->cipher, keyconf->keylen, keyconf->keyidx,
|
||||
sta_id, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_dynamic_key);
|
||||
EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
static void iwl_dump_lq_cmd(struct iwl_priv *priv,
|
||||
@ -1240,223 +758,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_send_lq_cmd);
|
||||
|
||||
/**
|
||||
* iwl_alloc_bcast_station - add broadcast station into driver's station table.
|
||||
*
|
||||
* This adds the broadcast station into the driver's station table
|
||||
* and marks it driver active, so that it will be restored to the
|
||||
* device at the next best time.
|
||||
*/
|
||||
int iwl_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
bool init_lq)
|
||||
{
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
unsigned long flags;
|
||||
u8 sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Unable to prepare broadcast station\n");
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
|
||||
priv->stations[sta_id].used |= IWL_STA_BCAST;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
if (init_lq) {
|
||||
link_cmd = iwl_sta_alloc_lq(priv, sta_id);
|
||||
if (!link_cmd) {
|
||||
IWL_ERR(priv,
|
||||
"Unable to initialize rate scaling for bcast station.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].lq = link_cmd;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station);
|
||||
|
||||
/**
|
||||
* iwl_update_bcast_station - update broadcast station's LQ command
|
||||
*
|
||||
* Only used by iwlagn. Placed here to have all bcast station management
|
||||
* code together.
|
||||
*/
|
||||
static int iwl_update_bcast_station(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
u8 sta_id = ctx->bcast_sta_id;
|
||||
|
||||
link_cmd = iwl_sta_alloc_lq(priv, sta_id);
|
||||
if (!link_cmd) {
|
||||
IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
if (priv->stations[sta_id].lq)
|
||||
kfree(priv->stations[sta_id].lq);
|
||||
else
|
||||
IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
|
||||
priv->stations[sta_id].lq = link_cmd;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_update_bcast_stations(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
int ret = 0;
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
ret = iwl_update_bcast_station(priv, ctx);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_update_bcast_stations);
|
||||
|
||||
void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
for (i = 0; i < priv->hw_params.max_stations; i++) {
|
||||
if (!(priv->stations[i].used & IWL_STA_BCAST))
|
||||
continue;
|
||||
|
||||
priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
|
||||
priv->num_stations--;
|
||||
BUG_ON(priv->num_stations < 0);
|
||||
kfree(priv->stations[i].lq);
|
||||
priv->stations[i].lq = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations);
|
||||
|
||||
/**
|
||||
* iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
|
||||
*/
|
||||
int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
/* Remove "disable" flag, to enable Tx for this TID */
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
|
||||
priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
|
||||
|
||||
int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -ENXIO;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags_msk = 0;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
|
||||
priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
|
||||
priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_rx_agg_start);
|
||||
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags_msk = 0;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
|
||||
priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_rx_agg_stop);
|
||||
|
||||
void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = 0;
|
||||
priv->stations[sta_id].sta.sleep_tx_count = 0;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_modify_ps_wake);
|
||||
|
||||
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.sta.modify_mask =
|
||||
STA_MODIFY_SLEEP_TX_COUNT_MSK;
|
||||
priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count);
|
||||
|
||||
int iwl_mac_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
|
@ -43,35 +43,13 @@
|
||||
#define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */
|
||||
|
||||
|
||||
int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key);
|
||||
int iwl_set_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key);
|
||||
int iwl_restore_default_wep_keys(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key, u8 sta_id);
|
||||
int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key, u8 sta_id);
|
||||
void iwl_update_tkip_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
|
||||
|
||||
void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
void iwl_clear_ucode_stations(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
int iwl_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
bool init_lq);
|
||||
void iwl_dealloc_bcast_stations(struct iwl_priv *priv);
|
||||
int iwl_update_bcast_stations(struct iwl_priv *priv);
|
||||
int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
|
||||
int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
struct iwl_addsta_cmd *sta, u8 flags);
|
||||
int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool init_rs, u8 *sta_id_r);
|
||||
int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool is_ap,
|
||||
struct ieee80211_sta *sta, u8 *sta_id_r);
|
||||
@ -79,13 +57,12 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
const u8 *addr);
|
||||
int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
|
||||
int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn);
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid);
|
||||
void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id);
|
||||
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
|
||||
|
||||
u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool is_ap, struct ieee80211_sta *sta);
|
||||
|
||||
int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct iwl_link_quality_cmd *lq, u8 flags, bool init);
|
||||
|
||||
/**
|
||||
* iwl_clear_driver_stations - clear knowledge of all stations from driver
|
||||
|
@ -636,41 +636,3 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
meta->flags = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_tx_cmd_complete);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
|
||||
#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
|
||||
|
||||
const char *iwl_get_tx_fail_reason(u32 status)
|
||||
{
|
||||
switch (status & TX_STATUS_MSK) {
|
||||
case TX_STATUS_SUCCESS:
|
||||
return "SUCCESS";
|
||||
TX_STATUS_POSTPONE(DELAY);
|
||||
TX_STATUS_POSTPONE(FEW_BYTES);
|
||||
TX_STATUS_POSTPONE(BT_PRIO);
|
||||
TX_STATUS_POSTPONE(QUIET_PERIOD);
|
||||
TX_STATUS_POSTPONE(CALC_TTAK);
|
||||
TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
|
||||
TX_STATUS_FAIL(SHORT_LIMIT);
|
||||
TX_STATUS_FAIL(LONG_LIMIT);
|
||||
TX_STATUS_FAIL(FIFO_UNDERRUN);
|
||||
TX_STATUS_FAIL(DRAIN_FLOW);
|
||||
TX_STATUS_FAIL(RFKILL_FLUSH);
|
||||
TX_STATUS_FAIL(LIFE_EXPIRE);
|
||||
TX_STATUS_FAIL(DEST_PS);
|
||||
TX_STATUS_FAIL(HOST_ABORTED);
|
||||
TX_STATUS_FAIL(BT_RETRY);
|
||||
TX_STATUS_FAIL(STA_INVALID);
|
||||
TX_STATUS_FAIL(FRAG_DROPPED);
|
||||
TX_STATUS_FAIL(TID_DISABLE);
|
||||
TX_STATUS_FAIL(FIFO_FLUSHED);
|
||||
TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
|
||||
TX_STATUS_FAIL(PASSIVE_NO_RX);
|
||||
TX_STATUS_FAIL(NO_BEACON_ON_RADAR);
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_get_tx_fail_reason);
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
@ -317,15 +317,15 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
|
||||
int left)
|
||||
{
|
||||
|
||||
if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->ibss_beacon)
|
||||
if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb)
|
||||
return 0;
|
||||
|
||||
if (priv->ibss_beacon->len > left)
|
||||
if (priv->beacon_skb->len > left)
|
||||
return 0;
|
||||
|
||||
memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
|
||||
memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
|
||||
|
||||
return priv->ibss_beacon->len;
|
||||
return priv->beacon_skb->len;
|
||||
}
|
||||
|
||||
static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
|
||||
@ -813,10 +813,10 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
/* new beacon skb is allocated every time; dispose previous.*/
|
||||
if (priv->ibss_beacon)
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
if (priv->beacon_skb)
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
|
||||
priv->ibss_beacon = beacon;
|
||||
priv->beacon_skb = beacon;
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
iwl3945_send_beacon_cmd(priv);
|
||||
@ -2547,7 +2547,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
|
||||
priv->cfg->ops->hcmd->send_bt_config(priv);
|
||||
|
||||
/* Configure the adapter for unassociated operation */
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
iwl3945_commit_rxon(priv, ctx);
|
||||
|
||||
iwl3945_reg_txpower_periodic(priv);
|
||||
|
||||
@ -2637,14 +2637,14 @@ static void __iwl3945_down(struct iwl_priv *priv)
|
||||
udelay(5);
|
||||
|
||||
/* Stop the device, and put it in low power state */
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
iwl_apm_stop(priv);
|
||||
|
||||
exit:
|
||||
memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
|
||||
|
||||
if (priv->ibss_beacon)
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
priv->ibss_beacon = NULL;
|
||||
if (priv->beacon_skb)
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
priv->beacon_skb = NULL;
|
||||
|
||||
/* clear out any free frames */
|
||||
iwl3945_clear_free_frames(priv);
|
||||
@ -2661,12 +2661,33 @@ static void iwl3945_down(struct iwl_priv *priv)
|
||||
|
||||
#define MAX_HW_RESTARTS 5
|
||||
|
||||
static int iwl3945_alloc_bcast_station(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
unsigned long flags;
|
||||
u8 sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Unable to prepare broadcast station\n");
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
|
||||
priv->stations[sta_id].used |= IWL_STA_BCAST;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __iwl3945_up(struct iwl_priv *priv)
|
||||
{
|
||||
int rc, i;
|
||||
|
||||
rc = iwl_alloc_bcast_station(priv, &priv->contexts[IWL_RXON_CTX_BSS],
|
||||
false);
|
||||
rc = iwl3945_alloc_bcast_station(priv);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -2917,18 +2938,10 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
|
||||
scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
|
||||
scan->good_CRC_th = 0;
|
||||
band = IEEE80211_BAND_2GHZ;
|
||||
break;
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
|
||||
/*
|
||||
* If active scaning is requested but a certain channel
|
||||
* is marked passive, we can do active scanning if we
|
||||
* detect transmissions.
|
||||
*/
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
|
||||
IWL_GOOD_CRC_TH_DISABLED;
|
||||
band = IEEE80211_BAND_5GHZ;
|
||||
break;
|
||||
default:
|
||||
@ -2936,6 +2949,14 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* If active scaning is requested but a certain channel
|
||||
* is marked passive, we can do active scanning if we
|
||||
* detect transmissions.
|
||||
*/
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
|
||||
IWL_GOOD_CRC_TH_DISABLED;
|
||||
|
||||
if (!priv->is_internal_short_scan) {
|
||||
scan->tx_cmd.len = cpu_to_le16(
|
||||
iwl_fill_probe_req(priv,
|
||||
@ -2983,6 +3004,18 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl3945_post_scan(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
/*
|
||||
* Since setting the RXON may have been deferred while
|
||||
* performing the scan, fire one off if needed
|
||||
*/
|
||||
if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
|
||||
iwl3945_commit_rxon(priv, ctx);
|
||||
}
|
||||
|
||||
static void iwl3945_bg_restart(struct work_struct *data)
|
||||
{
|
||||
struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
|
||||
@ -3049,7 +3082,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
conf = ieee80211_get_hw_conf(priv->hw);
|
||||
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
iwl3945_commit_rxon(priv, ctx);
|
||||
|
||||
rc = iwl_send_rxon_timing(priv, ctx);
|
||||
if (rc)
|
||||
@ -3075,7 +3108,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
iwl3945_commit_rxon(priv, ctx);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
@ -3214,7 +3247,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
|
||||
/* RXON - unassoc (to set timing command) */
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
iwl3945_commit_rxon(priv, ctx);
|
||||
|
||||
/* RXON Timing */
|
||||
rc = iwl_send_rxon_timing(priv, ctx);
|
||||
@ -3241,7 +3274,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
}
|
||||
/* restore RXON assoc */
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
iwl3945_commit_rxon(priv, ctx);
|
||||
}
|
||||
iwl3945_send_beacon_cmd(priv);
|
||||
|
||||
@ -3507,7 +3540,7 @@ static ssize_t store_flags(struct device *d,
|
||||
IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
|
||||
flags);
|
||||
ctx->staging.flags = cpu_to_le32(flags);
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
iwl3945_commit_rxon(priv, ctx);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
@ -3545,7 +3578,7 @@ static ssize_t store_filter_flags(struct device *d,
|
||||
"0x%04X\n", filter_flags);
|
||||
ctx->staging.filter_flags =
|
||||
cpu_to_le32(filter_flags);
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
iwl3945_commit_rxon(priv, ctx);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
@ -3815,7 +3848,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
|
||||
struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
|
||||
|
||||
priv->retry_rate = 1;
|
||||
priv->ibss_beacon = NULL;
|
||||
priv->beacon_skb = NULL;
|
||||
|
||||
spin_lock_init(&priv->sta_lock);
|
||||
spin_lock_init(&priv->hcmd_lock);
|
||||
@ -4179,7 +4212,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
|
||||
* paths to avoid running iwl_down() at all before leaving driver.
|
||||
* This (inexpensive) call *makes sure* device is reset.
|
||||
*/
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
iwl_apm_stop(priv);
|
||||
|
||||
/* make sure we flush any pending irq or
|
||||
* tasklet for the driver
|
||||
@ -4223,8 +4256,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
|
||||
iwl_free_channel_map(priv);
|
||||
iwlcore_free_geos(priv);
|
||||
kfree(priv->scan_cmd);
|
||||
if (priv->ibss_beacon)
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
if (priv->beacon_skb)
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
|
||||
ieee80211_free_hw(priv->hw);
|
||||
}
|
||||
|
@ -487,11 +487,12 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
|
||||
*/
|
||||
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret;
|
||||
|
||||
/* check if device is removed */
|
||||
if (cardp->surprise_removed) {
|
||||
lbs_deb_usbd(&cardp->udev->dev, "Device removed\n");
|
||||
ret = -ENODEV;
|
||||
goto tx_ret;
|
||||
}
|
||||
|
||||
@ -504,7 +505,6 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb
|
||||
|
||||
if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
|
||||
lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
|
||||
ret = -1;
|
||||
} else {
|
||||
lbs_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
|
||||
ret = 0;
|
||||
|
@ -261,8 +261,10 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
|
||||
list->max_entries = max_channel_num;
|
||||
list->channels = kzalloc(sizeof(struct p54_channel_entry) *
|
||||
max_channel_num, GFP_KERNEL);
|
||||
if (!list->channels)
|
||||
if (!list->channels) {
|
||||
ret = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
|
||||
for (i = 0; i < max_channel_num; i++) {
|
||||
if (i < priv->iq_autocal_len) {
|
||||
|
@ -1104,7 +1104,7 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
|
||||
rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
|
||||
|
||||
rt2x00queue_map_txskb(rt2x00dev, entry->skb);
|
||||
rt2x00queue_map_txskb(entry);
|
||||
|
||||
/*
|
||||
* Write the TX descriptor for the beacon.
|
||||
|
@ -1258,7 +1258,7 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
|
||||
rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
|
||||
|
||||
rt2x00queue_map_txskb(rt2x00dev, entry->skb);
|
||||
rt2x00queue_map_txskb(entry);
|
||||
|
||||
/*
|
||||
* Write the TX descriptor for the beacon.
|
||||
|
@ -499,7 +499,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_write_tx_data);
|
||||
|
||||
static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2)
|
||||
static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
|
||||
{
|
||||
int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
|
||||
int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
|
||||
|
@ -573,7 +573,7 @@ static void rt2800pci_kick_tx_queue(struct data_queue *queue)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
|
||||
struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
|
||||
unsigned int qidx = 0;
|
||||
unsigned int qidx;
|
||||
|
||||
if (queue->qid == QID_MGMT)
|
||||
qidx = 5;
|
||||
@ -676,7 +676,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
|
||||
break;
|
||||
}
|
||||
|
||||
qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_TYPE) - 1;
|
||||
qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
|
||||
if (qid >= QID_RX) {
|
||||
/*
|
||||
* Unknown queue, this shouldn't happen. Just drop
|
||||
|
@ -338,6 +338,11 @@ struct link {
|
||||
|
||||
/*
|
||||
* Work structure for scheduling periodic watchdog monitoring.
|
||||
* This work must be scheduled on the kernel workqueue, while
|
||||
* all other work structures must be queued on the mac80211
|
||||
* workqueue. This guarantees that the watchdog can schedule
|
||||
* other work structures and wait for their completion in order
|
||||
* to bring the device/driver back into the desired state.
|
||||
*/
|
||||
struct delayed_work watchdog_work;
|
||||
};
|
||||
@ -1036,17 +1041,15 @@ static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
/**
|
||||
* rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
|
||||
* @rt2x00dev: Pointer to &struct rt2x00_dev.
|
||||
* @skb: The skb to map.
|
||||
* @entry: Pointer to &struct queue_entry
|
||||
*/
|
||||
void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
|
||||
void rt2x00queue_map_txskb(struct queue_entry *entry);
|
||||
|
||||
/**
|
||||
* rt2x00queue_unmap_skb - Unmap a skb from DMA.
|
||||
* @rt2x00dev: Pointer to &struct rt2x00_dev.
|
||||
* @skb: The skb to unmap.
|
||||
* @entry: Pointer to &struct queue_entry
|
||||
*/
|
||||
void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
|
||||
void rt2x00queue_unmap_skb(struct queue_entry *entry);
|
||||
|
||||
/**
|
||||
* rt2x00queue_get_queue - Convert queue index to queue pointer
|
||||
@ -1093,8 +1096,7 @@ void rt2x00lib_dmadone(struct queue_entry *entry);
|
||||
void rt2x00lib_txdone(struct queue_entry *entry,
|
||||
struct txdone_entry_desc *txdesc);
|
||||
void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status);
|
||||
void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
|
||||
struct queue_entry *entry);
|
||||
void rt2x00lib_rxdone(struct queue_entry *entry);
|
||||
|
||||
/*
|
||||
* mac80211 handlers.
|
||||
|
@ -253,6 +253,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
|
||||
|
||||
void rt2x00lib_dmadone(struct queue_entry *entry)
|
||||
{
|
||||
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
||||
rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
|
||||
@ -273,7 +274,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
|
||||
/*
|
||||
* Unmap the skb.
|
||||
*/
|
||||
rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
|
||||
rt2x00queue_unmap_skb(entry);
|
||||
|
||||
/*
|
||||
* Remove the extra tx headroom from the skb.
|
||||
@ -432,42 +433,50 @@ static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
|
||||
struct ieee80211_supported_band *sband;
|
||||
const struct rt2x00_rate *rate;
|
||||
unsigned int i;
|
||||
int signal;
|
||||
int type;
|
||||
int signal = rxdesc->signal;
|
||||
int type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK);
|
||||
|
||||
/*
|
||||
* For non-HT rates the MCS value needs to contain the
|
||||
* actually used rate modulation (CCK or OFDM).
|
||||
*/
|
||||
if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS)
|
||||
signal = RATE_MCS(rxdesc->rate_mode, rxdesc->signal);
|
||||
else
|
||||
signal = rxdesc->signal;
|
||||
switch (rxdesc->rate_mode) {
|
||||
case RATE_MODE_CCK:
|
||||
case RATE_MODE_OFDM:
|
||||
/*
|
||||
* For non-HT rates the MCS value needs to contain the
|
||||
* actually used rate modulation (CCK or OFDM).
|
||||
*/
|
||||
if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS)
|
||||
signal = RATE_MCS(rxdesc->rate_mode, signal);
|
||||
|
||||
type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK);
|
||||
|
||||
sband = &rt2x00dev->bands[rt2x00dev->curr_band];
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
|
||||
|
||||
if (((type == RXDONE_SIGNAL_PLCP) &&
|
||||
(rate->plcp == signal)) ||
|
||||
((type == RXDONE_SIGNAL_BITRATE) &&
|
||||
(rate->bitrate == signal)) ||
|
||||
((type == RXDONE_SIGNAL_MCS) &&
|
||||
(rate->mcs == signal))) {
|
||||
return i;
|
||||
sband = &rt2x00dev->bands[rt2x00dev->curr_band];
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
|
||||
if (((type == RXDONE_SIGNAL_PLCP) &&
|
||||
(rate->plcp == signal)) ||
|
||||
((type == RXDONE_SIGNAL_BITRATE) &&
|
||||
(rate->bitrate == signal)) ||
|
||||
((type == RXDONE_SIGNAL_MCS) &&
|
||||
(rate->mcs == signal))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RATE_MODE_HT_MIX:
|
||||
case RATE_MODE_HT_GREENFIELD:
|
||||
if (signal >= 0 && signal <= 76)
|
||||
return signal;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
WARNING(rt2x00dev, "Frame received with unrecognized signal, "
|
||||
"signal=0x%.4x, type=%d.\n", signal, type);
|
||||
"mode=0x%.4x, signal=0x%.4x, type=%d.\n",
|
||||
rxdesc->rate_mode, signal, type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
|
||||
struct queue_entry *entry)
|
||||
void rt2x00lib_rxdone(struct queue_entry *entry)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
struct rxdone_entry_desc rxdesc;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_rx_status *rx_status;
|
||||
@ -481,14 +490,14 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
|
||||
* Allocate a new sk_buffer. If no new buffer available, drop the
|
||||
* received frame and reuse the existing buffer.
|
||||
*/
|
||||
skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry);
|
||||
skb = rt2x00queue_alloc_rxskb(entry);
|
||||
if (!skb)
|
||||
return;
|
||||
goto submit_entry;
|
||||
|
||||
/*
|
||||
* Unmap the skb.
|
||||
*/
|
||||
rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
|
||||
rt2x00queue_unmap_skb(entry);
|
||||
|
||||
/*
|
||||
* Extract the RXD details.
|
||||
@ -523,18 +532,12 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
|
||||
skb_trim(entry->skb, rxdesc.size);
|
||||
|
||||
/*
|
||||
* Check if the frame was received using HT. In that case,
|
||||
* the rate is the MCS index and should be passed to mac80211
|
||||
* directly. Otherwise we need to translate the signal to
|
||||
* the correct bitrate index.
|
||||
* Translate the signal to the correct bitrate index.
|
||||
*/
|
||||
if (rxdesc.rate_mode == RATE_MODE_CCK ||
|
||||
rxdesc.rate_mode == RATE_MODE_OFDM) {
|
||||
rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
|
||||
} else {
|
||||
rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
|
||||
if (rxdesc.rate_mode == RATE_MODE_HT_MIX ||
|
||||
rxdesc.rate_mode == RATE_MODE_HT_GREENFIELD)
|
||||
rxdesc.flags |= RX_FLAG_HT;
|
||||
rate_idx = rxdesc.signal;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update extra components
|
||||
|
@ -100,18 +100,15 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
/**
|
||||
* rt2x00queue_alloc_rxskb - allocate a skb for RX purposes.
|
||||
* @rt2x00dev: Pointer to &struct rt2x00_dev.
|
||||
* @queue: The queue for which the skb will be applicable.
|
||||
* @entry: The entry for which the skb will be applicable.
|
||||
*/
|
||||
struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
|
||||
struct queue_entry *entry);
|
||||
struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry);
|
||||
|
||||
/**
|
||||
* rt2x00queue_free_skb - free a skb
|
||||
* @rt2x00dev: Pointer to &struct rt2x00_dev.
|
||||
* @skb: The skb to free.
|
||||
* @entry: The entry for which the skb will be applicable.
|
||||
*/
|
||||
void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
|
||||
void rt2x00queue_free_skb(struct queue_entry *entry);
|
||||
|
||||
/**
|
||||
* rt2x00queue_align_frame - Align 802.11 frame to 4-byte boundary
|
||||
|
@ -235,6 +235,12 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
|
||||
struct link_ant *ant = &rt2x00dev->link.ant;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
/*
|
||||
* No need to update the stats for !=STA interfaces
|
||||
*/
|
||||
if (!rt2x00dev->intf_sta_count)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Frame was received successfully since non-succesfull
|
||||
* frames would have been dropped by the hardware.
|
||||
@ -411,8 +417,7 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
|
||||
!test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
ieee80211_queue_delayed_work(rt2x00dev->hw,
|
||||
&link->watchdog_work, WATCHDOG_INTERVAL);
|
||||
schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL);
|
||||
}
|
||||
|
||||
void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
|
||||
@ -436,8 +441,7 @@ static void rt2x00link_watchdog(struct work_struct *work)
|
||||
rt2x00dev->ops->lib->watchdog(rt2x00dev);
|
||||
|
||||
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||
ieee80211_queue_delayed_work(rt2x00dev->hw,
|
||||
&link->watchdog_work, WATCHDOG_INTERVAL);
|
||||
schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL);
|
||||
}
|
||||
|
||||
void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
|
||||
|
@ -84,7 +84,7 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* Send the frame to rt2x00lib for further processing.
|
||||
*/
|
||||
rt2x00lib_rxdone(rt2x00dev, entry);
|
||||
rt2x00lib_rxdone(entry);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user