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

Conflicts:
	drivers/net/wireless/libertas/host.h
This commit is contained in:
David S. Miller 2010-07-01 17:34:14 -07:00
commit 05318bc905
111 changed files with 3633 additions and 7660 deletions

View File

@ -7,6 +7,7 @@
* Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com>
* Copyright (c) 2007 Guido Guenther <agx@sigxcpu.org>
* Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi>
* Copyright (c) 2010 Sebastian Smolorz <sesmo@gmx.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -1649,6 +1650,58 @@ exit:
return NULL;
}
static int at76_join(struct at76_priv *priv)
{
struct at76_req_join join;
int ret;
memset(&join, 0, sizeof(struct at76_req_join));
memcpy(join.essid, priv->essid, priv->essid_size);
join.essid_size = priv->essid_size;
memcpy(join.bssid, priv->bssid, ETH_ALEN);
join.bss_type = INFRASTRUCTURE_MODE;
join.channel = priv->channel;
join.timeout = cpu_to_le16(2000);
at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__);
ret = at76_set_card_command(priv->udev, CMD_JOIN, &join,
sizeof(struct at76_req_join));
if (ret < 0) {
printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
wiphy_name(priv->hw->wiphy), ret);
return 0;
}
ret = at76_wait_completion(priv, CMD_JOIN);
at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret);
if (ret != CMD_STATUS_COMPLETE) {
printk(KERN_ERR "%s: at76_wait_completion failed: %d\n",
wiphy_name(priv->hw->wiphy), ret);
return 0;
}
at76_set_pm_mode(priv);
return 0;
}
static void at76_work_join_bssid(struct work_struct *work)
{
struct at76_priv *priv = container_of(work, struct at76_priv,
work_join_bssid);
if (priv->device_unplugged)
return;
mutex_lock(&priv->mtx);
if (is_valid_ether_addr(priv->bssid))
at76_join(priv);
mutex_unlock(&priv->mtx);
}
static void at76_mac80211_tx_callback(struct urb *urb)
{
struct at76_priv *priv = urb->context;
@ -1686,6 +1739,7 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
struct at76_priv *priv = hw->priv;
struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
int padding, submit_len, ret;
at76_dbg(DBG_MAC80211, "%s()", __func__);
@ -1696,6 +1750,21 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return NETDEV_TX_BUSY;
}
/* The following code lines are important when the device is going to
* authenticate with a new bssid. The driver must send CMD_JOIN before
* an authentication frame is transmitted. For this to succeed, the
* correct bssid of the AP must be known. As mac80211 does not inform
* drivers about the bssid prior to the authentication process the
* following workaround is necessary. If the TX frame is an
* authentication frame extract the bssid and send the CMD_JOIN. */
if (mgmt->frame_control & cpu_to_le16(IEEE80211_STYPE_AUTH)) {
if (compare_ether_addr(priv->bssid, mgmt->bssid)) {
memcpy(priv->bssid, mgmt->bssid, ETH_ALEN);
ieee80211_queue_work(hw, &priv->work_join_bssid);
return NETDEV_TX_BUSY;
}
}
ieee80211_stop_queues(hw);
at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */
@ -1770,6 +1839,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw)
at76_dbg(DBG_MAC80211, "%s()", __func__);
cancel_delayed_work(&priv->dwork_hw_scan);
cancel_work_sync(&priv->work_join_bssid);
cancel_work_sync(&priv->work_set_promisc);
mutex_lock(&priv->mtx);
@ -1818,42 +1888,6 @@ static void at76_remove_interface(struct ieee80211_hw *hw,
at76_dbg(DBG_MAC80211, "%s()", __func__);
}
static int at76_join(struct at76_priv *priv)
{
struct at76_req_join join;
int ret;
memset(&join, 0, sizeof(struct at76_req_join));
memcpy(join.essid, priv->essid, priv->essid_size);
join.essid_size = priv->essid_size;
memcpy(join.bssid, priv->bssid, ETH_ALEN);
join.bss_type = INFRASTRUCTURE_MODE;
join.channel = priv->channel;
join.timeout = cpu_to_le16(2000);
at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__);
ret = at76_set_card_command(priv->udev, CMD_JOIN, &join,
sizeof(struct at76_req_join));
if (ret < 0) {
printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
wiphy_name(priv->hw->wiphy), ret);
return 0;
}
ret = at76_wait_completion(priv, CMD_JOIN);
at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret);
if (ret != CMD_STATUS_COMPLETE) {
printk(KERN_ERR "%s: at76_wait_completion failed: %d\n",
wiphy_name(priv->hw->wiphy), ret);
return 0;
}
at76_set_pm_mode(priv);
return 0;
}
static void at76_dwork_hw_scan(struct work_struct *work)
{
struct at76_priv *priv = container_of(work, struct at76_priv,
@ -2107,6 +2141,7 @@ static struct at76_priv *at76_alloc_new_device(struct usb_device *udev)
mutex_init(&priv->mtx);
INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc);
INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx);
INIT_WORK(&priv->work_join_bssid, at76_work_join_bssid);
INIT_DELAYED_WORK(&priv->dwork_hw_scan, at76_dwork_hw_scan);
tasklet_init(&priv->rx_tasklet, at76_rx_tasklet, 0);
@ -2508,5 +2543,6 @@ MODULE_AUTHOR("Balint Seeber <n0_5p4m_p13453@hotmail.com>");
MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>");
MODULE_AUTHOR("Kalle Valo <kalle.valo@iki.fi>");
MODULE_AUTHOR("Sebastian Smolorz <sesmo@gmx.net>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

View File

@ -387,6 +387,7 @@ struct at76_priv {
/* work queues */
struct work_struct work_set_promisc;
struct work_struct work_submit_rx;
struct work_struct work_join_bssid;
struct delayed_work dwork_hw_scan;
struct tasklet_struct rx_tasklet;

View File

@ -1768,7 +1768,7 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable)
if (enable) {
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
AR5K_PHY_RESTART_DIV_GC, 1);
AR5K_PHY_RESTART_DIV_GC, 4);
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
AR5K_PHY_FAST_ANT_DIV_EN);

View File

@ -295,6 +295,26 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
/* Several PCIe massages to ensure proper behaviour */
if (ah->config.pcie_waen)
REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
else
REG_WRITE(ah, AR_WA, ah->WARegVal);
}
/*
* Configire PCIE after Ini init. SERDES values now come from ini file
* This enables PCIe low power mode.
*/
if (ah->config.pcieSerDesWrite) {
unsigned int i;
struct ar5416IniArray *array;
array = power_off ? &ah->iniPcieSerdes :
&ah->iniPcieSerdesLowPower;
for (i = 0; i < array->ia_rows; i++) {
REG_WRITE(ah,
INI_RA(array, i, 0),
INI_RA(array, i, 1));
}
}
}

View File

@ -226,6 +226,7 @@ struct ath_buf_state {
int bfs_retries;
u8 bf_type;
u8 bfs_paprd;
unsigned long bfs_paprd_timestamp;
u32 bfs_keyix;
enum ath9k_key_type bfs_keytype;
};
@ -425,6 +426,8 @@ int ath_beaconq_config(struct ath_softc *sc);
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
void ath_paprd_calibrate(struct work_struct *work);
void ath_ani_calibrate(unsigned long data);
@ -516,6 +519,7 @@ void ath_deinit_leds(struct ath_softc *sc);
#define SC_OP_TSF_RESET BIT(11)
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)
#define SC_OP_ANI_RUN BIT(14)
/* Powersave flags */
#define PS_WAIT_FOR_BEACON BIT(0)
@ -559,7 +563,6 @@ struct ath_softc {
struct mutex mutex;
struct work_struct paprd_work;
struct completion paprd_complete;
int paprd_txok;
u32 intrstatus;
u32 sc_flags; /* SC_OP_* */
@ -628,6 +631,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
extern struct ieee80211_ops ath9k_ops;
extern int modparam_nohwcrypt;
extern int led_blink;
irqreturn_t ath_isr(int irq, void *dev);
int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,

View File

@ -76,7 +76,8 @@ static void ath_led_brightness(struct led_classdev *led_cdev,
case LED_FULL:
if (led->led_type == ATH_LED_ASSOC) {
sc->sc_flags |= SC_OP_LED_ASSOCIATED;
ieee80211_queue_delayed_work(sc->hw,
if (led_blink)
ieee80211_queue_delayed_work(sc->hw,
&sc->ath_led_blink_work, 0);
} else if (led->led_type == ATH_LED_RADIO) {
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
@ -143,7 +144,8 @@ void ath_init_leds(struct ath_softc *sc)
/* LED off, active low */
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
if (led_blink)
INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
trigger = ieee80211_get_radio_led_name(sc->hw);
snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
@ -180,7 +182,8 @@ void ath_init_leds(struct ath_softc *sc)
return;
fail:
cancel_delayed_work_sync(&sc->ath_led_blink_work);
if (led_blink)
cancel_delayed_work_sync(&sc->ath_led_blink_work);
ath_deinit_leds(sc);
}

View File

@ -16,10 +16,27 @@
#include "htc.h"
/* identify firmware images */
#define FIRMWARE_AR7010 "ar7010.fw"
#define FIRMWARE_AR7010_1_1 "ar7010_1_1.fw"
#define FIRMWARE_AR9271 "ar9271.fw"
MODULE_FIRMWARE(FIRMWARE_AR7010);
MODULE_FIRMWARE(FIRMWARE_AR7010_1_1);
MODULE_FIRMWARE(FIRMWARE_AR9271);
static struct usb_device_id ath9k_hif_usb_ids[] = {
{ USB_DEVICE(0x0cf3, 0x9271) },
{ USB_DEVICE(0x0cf3, 0x1006) },
{ USB_DEVICE(0x0cf3, 0x7010) },
{ USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */
{ USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */
{ USB_DEVICE(0x0cf3, 0x7010) }, /* Atheros */
{ USB_DEVICE(0x0cf3, 0x7015) }, /* Atheros */
{ USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */
{ USB_DEVICE(0x0846, 0x9018) }, /* Netgear WNDA3200 */
{ USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */
{ USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */
{ USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */
{ USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
{ USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */
{ },
};
@ -879,17 +896,15 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
/* Find out which firmware to load */
switch(hif_dev->device_id) {
case 0x9271:
case 0x1006:
hif_dev->fw_name = "ar9271.fw";
break;
case 0x7010:
case 0x9018:
if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202)
hif_dev->fw_name = "ar7010_1_1.fw";
hif_dev->fw_name = FIRMWARE_AR7010_1_1;
else
hif_dev->fw_name = "ar7010.fw";
hif_dev->fw_name = FIRMWARE_AR7010;
break;
default:
hif_dev->fw_name = FIRMWARE_AR9271;
break;
}

View File

@ -287,6 +287,7 @@ struct ath9k_debug {
#define ATH_LED_PIN_DEF 1
#define ATH_LED_PIN_9287 8
#define ATH_LED_PIN_9271 15
#define ATH_LED_PIN_7010 12
#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */
#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */

View File

@ -244,17 +244,12 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid)
*/
switch(devid) {
case 0x9271:
case 0x1006:
priv->htc->credits = 33;
break;
case 0x7010:
case 0x9018:
priv->htc->credits = 45;
break;
default:
dev_err(priv->dev, "ath9k_htc: Unsupported device id: 0x%x\n",
devid);
goto err;
priv->htc->credits = 33;
}
ret = htc_init(priv->htc);

View File

@ -931,6 +931,8 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv)
priv->ah->led_pin = ATH_LED_PIN_9287;
else if (AR_SREV_9271(priv->ah))
priv->ah->led_pin = ATH_LED_PIN_9271;
else if (AR_DEVID_7010(priv->ah))
priv->ah->led_pin = ATH_LED_PIN_7010;
else
priv->ah->led_pin = ATH_LED_PIN_DEF;

View File

@ -388,6 +388,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
ah->config.ht_enable = 0;
ah->config.rx_intr_mitigation = true;
ah->config.pcieSerDesWrite = true;
/*
* We need this for PCI devices only (Cardbus, PCI, miniPCI)
@ -571,24 +572,13 @@ static int __ath9k_hw_init(struct ath_hw *ah)
ath9k_hw_init_mode_regs(ah);
/*
* Configire PCIE after Ini init. SERDES values now come from ini file
* This enables PCIe low power mode.
* Read back AR_WA into a permanent copy and set bits 14 and 17.
* We need to do this to avoid RMW of this register. We cannot
* read the reg when chip is asleep.
*/
if (AR_SREV_9300_20_OR_LATER(ah)) {
u32 regval;
unsigned int i;
/* Set Bits 16 and 17 in the AR_WA register. */
regval = REG_READ(ah, AR_WA);
regval |= 0x00030000;
REG_WRITE(ah, AR_WA, regval);
for (i = 0; i < ah->iniPcieSerdesLowPower.ia_rows; i++) {
REG_WRITE(ah,
INI_RA(&ah->iniPcieSerdesLowPower, i, 0),
INI_RA(&ah->iniPcieSerdesLowPower, i, 1));
}
}
ah->WARegVal = REG_READ(ah, AR_WA);
ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
AR_WA_ASPM_TIMER_BASED_DISABLE);
if (ah->is_pciexpress)
ath9k_hw_configpcipowersave(ah, 0, 0);
@ -1009,6 +999,11 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
ENABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10);
}
REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
AR_RTC_FORCE_WAKE_ON_INT);
@ -1063,6 +1058,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
{
ENABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10);
}
REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
AR_RTC_FORCE_WAKE_ON_INT);
@ -1070,6 +1070,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
REG_WRITE(ah, AR_RC, AR_RC_AHB);
REG_WRITE(ah, AR_RTC_RESET, 0);
udelay(2);
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
@ -1099,6 +1100,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
{
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10);
}
REG_WRITE(ah, AR_RTC_FORCE_WAKE,
AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
@ -1262,7 +1268,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
/* For chips on which RTC reset is done, save TSF before it gets cleared */
if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
if (AR_SREV_9100(ah) ||
(AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)))
tsf = ath9k_hw_gettsf64(ah);
saveLedState = REG_READ(ah, AR_CFG_LED) &
@ -1294,7 +1301,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
}
/* Restore TSF */
if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
if (tsf)
ath9k_hw_settsf64(ah, tsf);
if (AR_SREV_9280_10_OR_LATER(ah))
@ -1307,6 +1314,17 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (r)
return r;
/*
* Some AR91xx SoC devices frequently fail to accept TSF writes
* right after the chip reset. When that happens, write a new
* value after the initvals have been applied, with an offset
* based on measured time difference
*/
if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) {
tsf += 1500;
ath9k_hw_settsf64(ah, tsf);
}
/* Setup MFP options for CCMP */
if (AR_SREV_9280_20_OR_LATER(ah)) {
/* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
@ -1492,7 +1510,7 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
}
EXPORT_SYMBOL(ath9k_hw_keyreset);
bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
static bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
{
u32 macHi, macLo;
u32 unicast_flag = AR_KEYTABLE_VALID;
@ -1530,7 +1548,6 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
return true;
}
EXPORT_SYMBOL(ath9k_hw_keysetmac);
bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
const struct ath9k_keyval *k,
@ -1731,17 +1748,6 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
}
EXPORT_SYMBOL(ath9k_hw_set_keycache_entry);
bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry)
{
if (entry < ah->caps.keycache_size) {
u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
if (val & AR_KEYTABLE_VALID)
return true;
}
return false;
}
EXPORT_SYMBOL(ath9k_hw_keyisvalid);
/******************************/
/* Power Management (Chipset) */
/******************************/
@ -1768,6 +1774,11 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
REG_CLR_BIT(ah, (AR_RTC_RESET),
AR_RTC_RESET_EN);
}
/* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
if (AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_WA,
ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
}
/*
@ -1794,6 +1805,10 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
AR_RTC_FORCE_WAKE_EN);
}
}
/* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */
if (AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
}
static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
@ -1801,6 +1816,12 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
u32 val;
int i;
/* Set Bits 14 and 17 of AR_WA before powering on the chip. */
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10);
}
if (setChip) {
if ((REG_READ(ah, AR_RTC_STATUS) &
AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
@ -2155,6 +2176,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (AR_SREV_9271(ah))
pCap->num_gpio_pins = AR9271_NUM_GPIO;
else if (AR_DEVID_7010(ah))
pCap->num_gpio_pins = AR7010_NUM_GPIO;
else if (AR_SREV_9285_10_OR_LATER(ah))
pCap->num_gpio_pins = AR9285_NUM_GPIO;
else if (AR_SREV_9280_10_OR_LATER(ah))
@ -2295,8 +2318,15 @@ void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio)
BUG_ON(gpio >= ah->caps.num_gpio_pins);
gpio_shift = gpio << 1;
if (AR_DEVID_7010(ah)) {
gpio_shift = gpio;
REG_RMW(ah, AR7010_GPIO_OE,
(AR7010_GPIO_OE_AS_INPUT << gpio_shift),
(AR7010_GPIO_OE_MASK << gpio_shift));
return;
}
gpio_shift = gpio << 1;
REG_RMW(ah,
AR_GPIO_OE_OUT,
(AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
@ -2312,7 +2342,11 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
if (gpio >= ah->caps.num_gpio_pins)
return 0xffffffff;
if (AR_SREV_9300_20_OR_LATER(ah))
if (AR_DEVID_7010(ah)) {
u32 val;
val = REG_READ(ah, AR7010_GPIO_IN);
return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0;
} else if (AR_SREV_9300_20_OR_LATER(ah))
return MS_REG_READ(AR9300, gpio) != 0;
else if (AR_SREV_9271(ah))
return MS_REG_READ(AR9271, gpio) != 0;
@ -2332,10 +2366,16 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
{
u32 gpio_shift;
if (AR_DEVID_7010(ah)) {
gpio_shift = gpio;
REG_RMW(ah, AR7010_GPIO_OE,
(AR7010_GPIO_OE_AS_OUTPUT << gpio_shift),
(AR7010_GPIO_OE_MASK << gpio_shift));
return;
}
ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
gpio_shift = 2 * gpio;
REG_RMW(ah,
AR_GPIO_OE_OUT,
(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
@ -2345,6 +2385,13 @@ EXPORT_SYMBOL(ath9k_hw_cfg_output);
void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
{
if (AR_DEVID_7010(ah)) {
val = val ? 0 : 1;
REG_RMW(ah, AR7010_GPIO_OUT, ((val&1) << gpio),
AR_GPIO_BIT(gpio));
return;
}
if (AR_SREV_9271(ah))
val = ~val;

View File

@ -235,6 +235,7 @@ struct ath9k_ops_config {
int ack_6mb;
u32 cwm_ignore_extcca;
u8 pcie_powersave_enable;
bool pcieSerDesWrite;
u8 pcie_clock_req;
u32 pcie_waen;
u8 analog_shiftreg;
@ -819,6 +820,12 @@ struct ath_hw {
u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES];
u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES];
/*
* Store the permanent value of Reg 0x4004in WARegVal
* so we dont have to R/M/W. We should not be reading
* this register when in sleep states.
*/
u32 WARegVal;
};
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
@ -852,11 +859,9 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
/* Key Cache Management */
bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry);
bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac);
bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
const struct ath9k_keyval *k,
const u8 *mac);
bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry);
/* GPIO / RFKILL / Antennae */
void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);

View File

@ -33,6 +33,10 @@ int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
int led_blink = 1;
module_param_named(blink, led_blink, int, 0444);
MODULE_PARM_DESC(blink, "Enable LED blink on activity");
/* We use the hw_value as an index into our private channel structure */
#define CHAN2G(_freq, _idx) { \

View File

@ -268,7 +268,6 @@ void ath_paprd_calibrate(struct work_struct *work)
int time_left;
int i;
ath9k_ps_wakeup(sc);
skb = alloc_skb(len, GFP_KERNEL);
if (!skb)
return;
@ -289,6 +288,7 @@ void ath_paprd_calibrate(struct work_struct *work)
qnum = sc->tx.hwq_map[WME_AC_BE];
txctl.txq = &sc->tx.txq[qnum];
ath9k_ps_wakeup(sc);
ar9003_paprd_init_table(ah);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
if (!(ah->caps.tx_chainmask & BIT(chain)))
@ -310,13 +310,13 @@ void ath_paprd_calibrate(struct work_struct *work)
break;
time_left = wait_for_completion_timeout(&sc->paprd_complete,
100);
msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
if (!time_left) {
ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
"Timeout waiting for paprd training on "
"TX chain %d\n",
chain);
break;
goto fail_paprd;
}
if (!ar9003_paprd_is_done(ah))
@ -334,6 +334,7 @@ void ath_paprd_calibrate(struct work_struct *work)
ath_paprd_activate(sc);
}
fail_paprd:
ath9k_ps_restore(sc);
}
@ -451,6 +452,10 @@ static void ath_start_ani(struct ath_common *common)
{
struct ath_hw *ah = common->ah;
unsigned long timestamp = jiffies_to_msecs(jiffies);
struct ath_softc *sc = (struct ath_softc *) common->priv;
if (!(sc->sc_flags & SC_OP_ANI_RUN))
return;
common->ani.longcal_timer = timestamp;
common->ani.shortcal_timer = timestamp;
@ -766,11 +771,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
/* Reset rssi stats */
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_flags |= SC_OP_ANI_RUN;
ath_start_ani(common);
} else {
ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
common->curaid = 0;
/* Stop ANI */
sc->sc_flags &= ~SC_OP_ANI_RUN;
del_timer_sync(&common->ani.timer);
}
}
@ -1241,7 +1248,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
aphy->state = ATH_WIPHY_INACTIVE;
cancel_delayed_work_sync(&sc->ath_led_blink_work);
if (led_blink)
cancel_delayed_work_sync(&sc->ath_led_blink_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_work_sync(&sc->paprd_work);
@ -1374,8 +1383,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC ||
vif->type == NL80211_IFTYPE_MONITOR)
vif->type == NL80211_IFTYPE_MONITOR) {
sc->sc_flags |= SC_OP_ANI_RUN;
ath_start_ani(common);
}
out:
mutex_unlock(&sc->mutex);
@ -1396,6 +1407,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex);
/* Stop ANI */
sc->sc_flags &= ~SC_OP_ANI_RUN;
del_timer_sync(&common->ani.timer);
/* Reclaim beacon resources */

View File

@ -704,6 +704,11 @@
#define AR_WA_BIT7 (1 << 7)
#define AR_WA_BIT23 (1 << 23)
#define AR_WA_D3_L1_DISABLE (1 << 14)
#define AR_WA_D3_TO_L1_DISABLE_REAL (1 << 16)
#define AR_WA_ASPM_TIMER_BASED_DISABLE (1 << 17)
#define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */
#define AR_WA_ANALOG_SHIFT (1 << 20)
#define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */
#define AR9285_WA_DEFAULT 0x004a050b
#define AR9280_WA_DEFAULT 0x0040073b
#define AR_WA_DEFAULT 0x0000073f
@ -877,6 +882,7 @@
#define AR_SREV_9271_11(_ah) \
(AR_SREV_9271(_ah) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11))
#define AR_SREV_9300(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
#define AR_SREV_9300_20(_ah) \
@ -891,6 +897,10 @@
(AR_SREV_9285_12_OR_LATER(_ah) && \
((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
#define AR_DEVID_7010(_ah) \
(((_ah)->hw_version.devid == 0x7010) || \
((_ah)->hw_version.devid == 0x9018))
#define AR_RADIO_SREV_MAJOR 0xf0
#define AR_RAD5133_SREV_MAJOR 0xc0
#define AR_RAD2133_SREV_MAJOR 0xd0
@ -988,6 +998,7 @@ enum {
#define AR9287_NUM_GPIO 11
#define AR9271_NUM_GPIO 16
#define AR9300_NUM_GPIO 17
#define AR7010_NUM_GPIO 16
#define AR_GPIO_IN_OUT 0x4048
#define AR_GPIO_IN_VAL 0x0FFFC000
@ -1002,6 +1013,8 @@ enum {
#define AR9271_GPIO_IN_VAL_S 16
#define AR9300_GPIO_IN_VAL 0x0001FFFF
#define AR9300_GPIO_IN_VAL_S 0
#define AR7010_GPIO_IN_VAL 0x0000FFFF
#define AR7010_GPIO_IN_VAL_S 0
#define AR_GPIO_OE_OUT (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)
#define AR_GPIO_OE_OUT_DRV 0x3
@ -1010,6 +1023,21 @@ enum {
#define AR_GPIO_OE_OUT_DRV_HI 0x2
#define AR_GPIO_OE_OUT_DRV_ALL 0x3
#define AR7010_GPIO_OE 0x52000
#define AR7010_GPIO_OE_MASK 0x1
#define AR7010_GPIO_OE_AS_OUTPUT 0x0
#define AR7010_GPIO_OE_AS_INPUT 0x1
#define AR7010_GPIO_IN 0x52004
#define AR7010_GPIO_OUT 0x52008
#define AR7010_GPIO_SET 0x5200C
#define AR7010_GPIO_CLEAR 0x52010
#define AR7010_GPIO_INT 0x52014
#define AR7010_GPIO_INT_TYPE 0x52018
#define AR7010_GPIO_INT_POLARITY 0x5201C
#define AR7010_GPIO_PENDING 0x52020
#define AR7010_GPIO_INT_MASK 0x52024
#define AR7010_GPIO_FUNCTION 0x52028
#define AR_GPIO_INTR_POL (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050)
#define AR_GPIO_INTR_POL_VAL 0x0001FFFF
#define AR_GPIO_INTR_POL_VAL_S 0

View File

@ -328,6 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
u32 ba[WME_BA_BMP_SIZE >> 5];
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
bool rc_update = true;
struct ieee80211_tx_rate rates[4];
skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
@ -335,6 +336,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
tx_info = IEEE80211_SKB_CB(skb);
hw = bf->aphy->hw;
memcpy(rates, tx_info->control.rates, sizeof(rates));
rcu_read_lock();
/* XXX: use ieee80211_find_sta! */
@ -375,6 +378,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
txfail = txpending = 0;
bf_next = bf->bf_next;
skb = bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) {
/* transmit completion, subframe is
* acked by block ack */
@ -428,6 +434,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
spin_unlock_bh(&txq->axq_lock);
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
memcpy(tx_info->control.rates, rates, sizeof(rates));
ath_tx_rc_status(bf, ts, nbad, txok, true);
rc_update = false;
} else {
@ -1644,6 +1651,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
}
bf->bf_state.bfs_paprd = txctl->paprd;
if (txctl->paprd)
bf->bf_state.bfs_paprd_timestamp = jiffies;
bf->bf_flags = setup_tx_flags(skb, use_ldpc);
bf->bf_keytype = get_hw_crypto_keytype(skb);
@ -1944,8 +1953,12 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
if (bf->bf_state.bfs_paprd) {
sc->paprd_txok = txok;
complete(&sc->paprd_complete);
if (time_after(jiffies,
bf->bf_state.bfs_paprd_timestamp +
msecs_to_jiffies(ATH_PAPRD_TIMEOUT)))
dev_kfree_skb_any(skb);
else
complete(&sc->paprd_complete);
} else {
ath_tx_complete(sc, skb, bf->aphy, tx_flags);
ath_debug_stat_tx(sc, txq, bf, ts);
@ -2027,7 +2040,7 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
tx_info->status.rates[i].idx = -1;
}
tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1;
tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
}
static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
@ -2138,7 +2151,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
* This frame is sent out as a single frame.
* Use hardware retry status for this frame.
*/
bf->bf_retries = ts.ts_longretry;
if (ts.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(bf, &ts, 0, txok, true);
@ -2268,7 +2280,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
}
if (!bf_isampdu(bf)) {
bf->bf_retries = txs.ts_longretry;
if (txs.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(bf, &txs, 0, txok, true);

View File

@ -1804,7 +1804,7 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
dma_reason[2], dma_reason[3],
dma_reason[4], dma_reason[5]);
b43err(dev->wl, "This device does not support DMA "
"on your system. Please use PIO instead.\n");
"on your system. It will now be switched to PIO.\n");
/* Fall back to PIO transfers if we get fatal DMA errors! */
dev->use_pio = 1;
b43_controller_restart(dev, "DMA error");

View File

@ -182,6 +182,7 @@ static void b43_sdio_remove(struct sdio_func *func)
static const struct sdio_device_id b43_sdio_ids[] = {
{ SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */
{ SDIO_DEVICE(0x0092, 0x0004) }, /* C-guys, Inc. EW-CG1102GC */
{ },
};

View File

@ -688,7 +688,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
struct ap_data *ap = data;
struct net_device *dev = ap->local->dev;
struct ieee80211_hdr *hdr;
u16 fc, status;
u16 status;
__le16 *pos;
struct sta_info *sta = NULL;
char *txt = NULL;
@ -699,7 +699,6 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
}
hdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(hdr->frame_control);
if ((!ieee80211_is_assoc_resp(hdr->frame_control) &&
!ieee80211_is_reassoc_resp(hdr->frame_control)) ||
skb->len < IEEE80211_MGMT_HDR_LEN + 4) {

View File

@ -741,9 +741,7 @@ void hostap_set_multicast_list_queue(struct work_struct *work)
local_info_t *local =
container_of(work, local_info_t, set_multicast_list_queue);
struct net_device *dev = local->dev;
struct hostap_interface *iface;
iface = netdev_priv(dev);
if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE,
local->is_promisc)) {
printk(KERN_INFO "%s: %sabling promiscuous mode failed\n",

View File

@ -1,6 +1,6 @@
obj-$(CONFIG_IWLWIFI) += iwlcore.o
iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o
iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o
iwlcore-objs += iwl-scan.o iwl-led.o
iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
@ -11,7 +11,7 @@ CFLAGS_iwl-devtrace.o := -I$(src)
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
iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o

View File

@ -157,6 +157,8 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_TX_IQ_PERD) |
BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib)
priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
@ -215,6 +217,7 @@ static struct iwl_lib_ops iwl1000_lib = {
.set_ct_kill = iwl1000_set_ct_threshold,
},
.manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,

View File

@ -406,6 +406,11 @@ static bool iwl3945_good_plcp_health(struct iwl_priv *priv,
unsigned int plcp_msec;
unsigned long plcp_received_jiffies;
if (priv->cfg->plcp_delta_threshold ==
IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
return rc;
}
memcpy(&current_stat, pkt->u.raw, sizeof(struct
iwl3945_notif_statistics));
/*

View File

@ -1580,7 +1580,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
u32 R4;
if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
(priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
(priv->_agn.statistics.flag &
STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
@ -1604,8 +1605,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
if (!test_bit(STATUS_TEMPERATURE, &priv->status))
vt = sign_extend(R4, 23);
else
vt = sign_extend(
le32_to_cpu(priv->statistics.general.temperature), 23);
vt = sign_extend(le32_to_cpu(
priv->_agn.statistics.general.temperature), 23);
IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
@ -1785,6 +1786,7 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
{
unsigned long flags;
u16 ra_tid;
int ret;
if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
(IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@ -1800,7 +1802,9 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
ra_tid = BUILD_RAxTID(sta_id, tid);
/* Modify device's station table to Tx this TID */
iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
if (ret)
return ret;
spin_lock_irqsave(&priv->lock, flags);
@ -2276,6 +2280,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.set_ct_kill = iwl4965_set_ct_threshold,
},
.manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,

View File

@ -249,10 +249,11 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
/* Set initial calibration set */
priv->hw_params.sens = &iwl5150_sensitivity;
priv->hw_params.calib_init_cfg =
BIT(IWL_CALIB_DC) |
BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib)
priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
@ -264,7 +265,7 @@ static void iwl5150_temperature(struct iwl_priv *priv)
u32 vt = 0;
s32 offset = iwl_temp_calib_to_offset(priv);
vt = le32_to_cpu(priv->statistics.general.temperature);
vt = le32_to_cpu(priv->_agn.statistics.general.temperature);
vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
/* now vt hold the temperature in Kelvin */
priv->temperature = KELVIN_TO_CELSIUS(vt);
@ -392,6 +393,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.set_ct_kill = iwl5000_set_ct_threshold,
},
.manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
@ -454,6 +456,7 @@ static struct iwl_lib_ops iwl5150_lib = {
.set_ct_kill = iwl5150_set_ct_threshold,
},
.manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
@ -660,6 +663,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
.ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
struct iwl_cfg iwl5150_abg_cfg = {
@ -689,6 +693,7 @@ struct iwl_cfg iwl5150_abg_cfg = {
.ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));

View File

@ -84,9 +84,10 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
}
/* Indicate calibration version to uCode. */
static void iwl6050_set_calib_version(struct iwl_priv *priv)
static void iwl6000_set_calib_version(struct iwl_priv *priv)
{
if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)
if (priv->cfg->need_dc_calib &&
(priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6))
iwl_set_bit(priv, CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
}
@ -186,53 +187,8 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND);
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
return 0;
}
static int iwl6050_hw_set_hw_params(struct iwl_priv *priv)
{
if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
priv->cfg->num_of_queues =
priv->cfg->mod_params->num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
priv->cfg->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
priv->hw_params.max_bsm_size = 0;
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
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);
/* Set initial sensitivity parameters */
/* Set initial calibration set */
priv->hw_params.sens = &iwl6000_sensitivity;
priv->hw_params.calib_init_cfg =
BIT(IWL_CALIB_XTAL) |
BIT(IWL_CALIB_DC) |
BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib)
priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
@ -359,8 +315,10 @@ static struct iwl_lib_ops iwl6000_lib = {
.temp_ops = {
.temperature = iwlagn_temperature,
.set_ct_kill = iwl6000_set_ct_threshold,
.set_calib_version = iwl6000_set_calib_version,
},
.manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
@ -397,79 +355,6 @@ static const struct iwl_ops iwl6000g2b_ops = {
.led = &iwlagn_led_ops,
};
static struct iwl_lib_ops iwl6050_lib = {
.set_hw_params = iwl6050_hw_set_hw_params,
.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
.txq_set_sched = iwlagn_txq_set_sched,
.txq_agg_enable = iwlagn_txq_agg_enable,
.txq_agg_disable = iwlagn_txq_agg_disable,
.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
.txq_free_tfd = iwl_hw_txq_free_tfd,
.txq_init = iwl_hw_tx_queue_init,
.rx_handler_setup = iwlagn_rx_handler_setup,
.setup_deferred_work = iwlagn_setup_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
.load_ucode = iwlagn_load_ucode,
.dump_nic_event_log = iwl_dump_nic_event_log,
.dump_nic_error_log = iwl_dump_nic_error_log,
.dump_csr = iwl_dump_csr,
.dump_fh = iwl_dump_fh,
.init_alive_start = iwlagn_init_alive_start,
.alive_notify = iwlagn_alive_notify,
.send_tx_power = iwlagn_send_tx_power,
.update_chain_flags = iwl_update_chain_flags,
.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 = {
EEPROM_REG_BAND_1_CHANNELS,
EEPROM_REG_BAND_2_CHANNELS,
EEPROM_REG_BAND_3_CHANNELS,
EEPROM_REG_BAND_4_CHANNELS,
EEPROM_REG_BAND_5_CHANNELS,
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,
.query_addr = iwlagn_eeprom_query_addr,
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
},
.post_associate = iwl_post_associate,
.isr = iwl_isr_ict,
.config_ap = iwl_config_ap,
.temp_ops = {
.temperature = iwlagn_temperature,
.set_ct_kill = iwl6000_set_ct_threshold,
.set_calib_version = iwl6050_set_calib_version,
},
.manage_ibss_station = iwlagn_manage_ibss_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
};
static const struct iwl_ops iwl6050_ops = {
.lib = &iwl6050_lib,
.hcmd = &iwlagn_hcmd,
.utils = &iwlagn_hcmd_utils,
.led = &iwlagn_led_ops,
};
struct iwl_cfg iwl6000g2a_2agn_cfg = {
.name = "6000 Series 2x2 AGN Gen2a",
.fw_name_pre = IWL6000G2A_FW_PRE,
@ -505,6 +390,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = {
.ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
struct iwl_cfg iwl6000g2a_2abg_cfg = {
@ -537,6 +423,9 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = {
.chain_noise_scale = 1000,
.monitor_recover_period = IWL_MONITORING_PERIOD,
.max_event_log_size = 512,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
struct iwl_cfg iwl6000g2a_2bg_cfg = {
@ -569,6 +458,9 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = {
.chain_noise_scale = 1000,
.monitor_recover_period = IWL_MONITORING_PERIOD,
.max_event_log_size = 512,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
struct iwl_cfg iwl6000g2b_2agn_cfg = {
@ -603,6 +495,9 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
.chain_noise_scale = 1000,
.monitor_recover_period = IWL_MONITORING_PERIOD,
.max_event_log_size = 512,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
struct iwl_cfg iwl6000g2b_2abg_cfg = {
@ -635,6 +530,9 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {
.chain_noise_scale = 1000,
.monitor_recover_period = IWL_MONITORING_PERIOD,
.max_event_log_size = 512,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
struct iwl_cfg iwl6000g2b_2bgn_cfg = {
@ -669,6 +567,9 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
.chain_noise_scale = 1000,
.monitor_recover_period = IWL_MONITORING_PERIOD,
.max_event_log_size = 512,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
struct iwl_cfg iwl6000g2b_2bg_cfg = {
@ -701,6 +602,9 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {
.chain_noise_scale = 1000,
.monitor_recover_period = IWL_MONITORING_PERIOD,
.max_event_log_size = 512,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
struct iwl_cfg iwl6000g2b_bgn_cfg = {
@ -735,6 +639,9 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
.chain_noise_scale = 1000,
.monitor_recover_period = IWL_MONITORING_PERIOD,
.max_event_log_size = 512,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
struct iwl_cfg iwl6000g2b_bg_cfg = {
@ -767,6 +674,9 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {
.chain_noise_scale = 1000,
.monitor_recover_period = IWL_MONITORING_PERIOD,
.max_event_log_size = 512,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
/*
@ -885,7 +795,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.ucode_api_max = IWL6050_UCODE_API_MAX,
.ucode_api_min = IWL6050_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6050_ops,
.ops = &iwl6000_ops,
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
@ -914,6 +824,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
struct iwl_cfg iwl6050_2abg_cfg = {
@ -922,7 +833,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
.ucode_api_max = IWL6050_UCODE_API_MAX,
.ucode_api_min = IWL6050_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G,
.ops = &iwl6050_ops,
.ops = &iwl6000_ops,
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
@ -949,6 +860,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
.ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
};
struct iwl_cfg iwl6000_3agn_cfg = {

View File

@ -96,17 +96,16 @@ int iwl_send_calib_results(struct iwl_priv *priv)
hcmd.len = priv->calib_results[i].buf_len;
hcmd.data = priv->calib_results[i].buf;
ret = iwl_send_cmd_sync(priv, &hcmd);
if (ret)
goto err;
if (ret) {
IWL_ERR(priv, "Error %d iteration %d\n",
ret, i);
break;
}
}
}
return 0;
err:
IWL_ERR(priv, "Error %d iteration %d\n", ret, i);
return ret;
}
EXPORT_SYMBOL(iwl_send_calib_results);
int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len)
{
@ -121,7 +120,6 @@ int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len)
memcpy(res->buf, buf, len);
return 0;
}
EXPORT_SYMBOL(iwl_calib_set);
void iwl_calib_free_results(struct iwl_priv *priv)
{
@ -133,7 +131,6 @@ void iwl_calib_free_results(struct iwl_priv *priv)
priv->calib_results[i].buf_len = 0;
}
}
EXPORT_SYMBOL(iwl_calib_free_results);
/*****************************************************************************
* RUNTIME calibrations framework
@ -533,7 +530,6 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
ret |= iwl_sensitivity_write(priv);
IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
}
EXPORT_SYMBOL(iwl_init_sensitivity);
void iwl_sensitivity_calibration(struct iwl_priv *priv,
struct iwl_notif_statistics *resp)
@ -639,7 +635,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv,
iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
iwl_sensitivity_write(priv);
}
EXPORT_SYMBOL(iwl_sensitivity_calibration);
static inline u8 find_first_chain(u8 mask)
{
@ -848,10 +843,10 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
if (active_chains != priv->hw_params.valid_rx_ant &&
active_chains != priv->chain_noise_data.active_chains)
IWL_WARN(priv,
"Detected that not all antennas are connected! "
"Connected: %#x, valid: %#x.\n",
active_chains, priv->hw_params.valid_rx_ant);
IWL_DEBUG_CALIB(priv,
"Detected that not all antennas are connected! "
"Connected: %#x, valid: %#x.\n",
active_chains, priv->hw_params.valid_rx_ant);
/* Save for use within RXON, TX, SCAN commands, etc. */
priv->chain_noise_data.active_chains = active_chains;
@ -897,8 +892,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
data->state = IWL_CHAIN_NOISE_DONE;
iwl_power_update_mode(priv, false);
}
EXPORT_SYMBOL(iwl_chain_noise_calibration);
void iwl_reset_run_time_calib(struct iwl_priv *priv)
{
@ -915,5 +908,3 @@ void iwl_reset_run_time_calib(struct iwl_priv *priv)
* periodically after association */
iwl_send_statistics_request(priv, CMD_ASYNC, true);
}
EXPORT_SYMBOL(iwl_reset_run_time_calib);

View File

@ -33,17 +33,17 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
int p = 0;
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
le32_to_cpu(priv->statistics.flag));
if (le32_to_cpu(priv->statistics.flag) &
le32_to_cpu(priv->_agn.statistics.flag));
if (le32_to_cpu(priv->_agn.statistics.flag) &
UCODE_STATISTICS_CLEAR_MSK)
p += scnprintf(buf + p, bufsz - p,
"\tStatistics have been cleared\n");
p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
(le32_to_cpu(priv->statistics.flag) &
(le32_to_cpu(priv->_agn.statistics.flag) &
UCODE_STATISTICS_FREQUENCY_MSK)
? "2.4 GHz" : "5.2 GHz");
p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
(le32_to_cpu(priv->statistics.flag) &
(le32_to_cpu(priv->_agn.statistics.flag) &
UCODE_STATISTICS_NARROW_BAND_MSK)
? "enabled" : "disabled");
return p;
@ -79,22 +79,22 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
ofdm = &priv->statistics.rx.ofdm;
cck = &priv->statistics.rx.cck;
general = &priv->statistics.rx.general;
ht = &priv->statistics.rx.ofdm_ht;
accum_ofdm = &priv->accum_statistics.rx.ofdm;
accum_cck = &priv->accum_statistics.rx.cck;
accum_general = &priv->accum_statistics.rx.general;
accum_ht = &priv->accum_statistics.rx.ofdm_ht;
delta_ofdm = &priv->delta_statistics.rx.ofdm;
delta_cck = &priv->delta_statistics.rx.cck;
delta_general = &priv->delta_statistics.rx.general;
delta_ht = &priv->delta_statistics.rx.ofdm_ht;
max_ofdm = &priv->max_delta.rx.ofdm;
max_cck = &priv->max_delta.rx.cck;
max_general = &priv->max_delta.rx.general;
max_ht = &priv->max_delta.rx.ofdm_ht;
ofdm = &priv->_agn.statistics.rx.ofdm;
cck = &priv->_agn.statistics.rx.cck;
general = &priv->_agn.statistics.rx.general;
ht = &priv->_agn.statistics.rx.ofdm_ht;
accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm;
accum_cck = &priv->_agn.accum_statistics.rx.cck;
accum_general = &priv->_agn.accum_statistics.rx.general;
accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht;
delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm;
delta_cck = &priv->_agn.delta_statistics.rx.cck;
delta_general = &priv->_agn.delta_statistics.rx.general;
delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht;
max_ofdm = &priv->_agn.max_delta.rx.ofdm;
max_cck = &priv->_agn.max_delta.rx.cck;
max_general = &priv->_agn.max_delta.rx.general;
max_ht = &priv->_agn.max_delta.rx.ofdm_ht;
pos += iwl_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
@ -560,10 +560,10 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
tx = &priv->statistics.tx;
accum_tx = &priv->accum_statistics.tx;
delta_tx = &priv->delta_statistics.tx;
max_tx = &priv->max_delta.tx;
tx = &priv->_agn.statistics.tx;
accum_tx = &priv->_agn.accum_statistics.tx;
delta_tx = &priv->_agn.delta_statistics.tx;
max_tx = &priv->_agn.max_delta.tx;
pos += iwl_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
"acumulative delta max\n",
@ -777,18 +777,18 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
general = &priv->statistics.general;
dbg = &priv->statistics.general.dbg;
div = &priv->statistics.general.div;
accum_general = &priv->accum_statistics.general;
delta_general = &priv->delta_statistics.general;
max_general = &priv->max_delta.general;
accum_dbg = &priv->accum_statistics.general.dbg;
delta_dbg = &priv->delta_statistics.general.dbg;
max_dbg = &priv->max_delta.general.dbg;
accum_div = &priv->accum_statistics.general.div;
delta_div = &priv->delta_statistics.general.div;
max_div = &priv->max_delta.general.div;
general = &priv->_agn.statistics.general;
dbg = &priv->_agn.statistics.general.dbg;
div = &priv->_agn.statistics.general.div;
accum_general = &priv->_agn.accum_statistics.general;
delta_general = &priv->_agn.delta_statistics.general;
max_general = &priv->_agn.max_delta.general;
accum_dbg = &priv->_agn.accum_statistics.general.dbg;
delta_dbg = &priv->_agn.delta_statistics.general.dbg;
max_dbg = &priv->_agn.max_delta.general.dbg;
accum_div = &priv->_agn.accum_statistics.general.div;
delta_div = &priv->_agn.delta_statistics.general.div;
max_div = &priv->_agn.max_delta.general.div;
pos += iwl_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
"acumulative delta max\n",

View File

@ -214,11 +214,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
__le32 *tx_flags)
{
if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
(info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
*tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
else
*tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK;
*tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
}
/* Calc max signal level (dBm) among 3 possible receivers */

View File

@ -361,7 +361,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
void iwlagn_temperature(struct iwl_priv *priv)
{
/* store temperature from statistics (in Celsius) */
priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
priv->temperature =
le32_to_cpu(priv->_agn.statistics.general.temperature);
iwl_tt_handler(priv);
}

View File

@ -324,18 +324,11 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
struct iwl_lq_sta *lq_data,
struct ieee80211_sta *sta)
{
if ((tid < TID_MAX_LOAD_COUNT) &&
!rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta)) {
if (priv->cfg->use_rts_for_ht) {
/*
* switch to RTS/CTS if it is the prefer protection
* method for HT traffic
*/
IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n");
priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
iwlcore_commit_rxon(priv);
}
}
if (tid < TID_MAX_LOAD_COUNT)
rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
else
IWL_ERR(priv, "tid exceeds max load count: %d/%d\n",
tid, TID_MAX_LOAD_COUNT);
}
static inline int get_num_of_ant_from_rate(u32 rate_n_flags)

View File

@ -0,0 +1,284 @@
/******************************************************************************
*
* 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
*
*****************************************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-calib.h"
#include "iwl-sta.h"
#include "iwl-io.h"
#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
#include "iwl-agn.h"
void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_missed_beacon_notif *missed_beacon;
missed_beacon = &pkt->u.missed_beacon;
if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
priv->missed_beacon_threshold) {
IWL_DEBUG_CALIB(priv,
"missed bcn cnsq %d totl %d rcd %d expctd %d\n",
le32_to_cpu(missed_beacon->consecutive_missed_beacons),
le32_to_cpu(missed_beacon->total_missed_becons),
le32_to_cpu(missed_beacon->num_recvd_beacons),
le32_to_cpu(missed_beacon->num_expected_beacons));
if (!test_bit(STATUS_SCANNING, &priv->status))
iwl_init_sensitivity(priv);
}
}
/* Calculate noise level, based on measurements during network silence just
* before arriving beacon. This measurement can be done only if we know
* exactly when to expect beacons, therefore only when we're associated. */
static void iwl_rx_calc_noise(struct iwl_priv *priv)
{
struct statistics_rx_non_phy *rx_info
= &(priv->_agn.statistics.rx.general);
int num_active_rx = 0;
int total_silence = 0;
int bcn_silence_a =
le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
int bcn_silence_b =
le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
int bcn_silence_c =
le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
int last_rx_noise;
if (bcn_silence_a) {
total_silence += bcn_silence_a;
num_active_rx++;
}
if (bcn_silence_b) {
total_silence += bcn_silence_b;
num_active_rx++;
}
if (bcn_silence_c) {
total_silence += bcn_silence_c;
num_active_rx++;
}
/* Average among active antennas */
if (num_active_rx)
last_rx_noise = (total_silence / num_active_rx) - 107;
else
last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
bcn_silence_a, bcn_silence_b, bcn_silence_c,
last_rx_noise);
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
/*
* based on the assumption of all statistics counter are in DWORD
* FIXME: This function is for debugging, do not deal with
* the case of counters roll-over.
*/
static void iwl_accumulative_statistics(struct iwl_priv *priv,
__le32 *stats)
{
int i;
__le32 *prev_stats;
u32 *accum_stats;
u32 *delta, *max_delta;
prev_stats = (__le32 *)&priv->_agn.statistics;
accum_stats = (u32 *)&priv->_agn.accum_statistics;
delta = (u32 *)&priv->_agn.delta_statistics;
max_delta = (u32 *)&priv->_agn.max_delta;
for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
i += sizeof(__le32), stats++, prev_stats++, delta++,
max_delta++, accum_stats++) {
if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
*delta = (le32_to_cpu(*stats) -
le32_to_cpu(*prev_stats));
*accum_stats += *delta;
if (*delta > *max_delta)
*max_delta = *delta;
}
}
/* reset accumulative statistics for "no-counter" type statistics */
priv->_agn.accum_statistics.general.temperature =
priv->_agn.statistics.general.temperature;
priv->_agn.accum_statistics.general.temperature_m =
priv->_agn.statistics.general.temperature_m;
priv->_agn.accum_statistics.general.ttl_timestamp =
priv->_agn.statistics.general.ttl_timestamp;
priv->_agn.accum_statistics.tx.tx_power.ant_a =
priv->_agn.statistics.tx.tx_power.ant_a;
priv->_agn.accum_statistics.tx.tx_power.ant_b =
priv->_agn.statistics.tx.tx_power.ant_b;
priv->_agn.accum_statistics.tx.tx_power.ant_c =
priv->_agn.statistics.tx.tx_power.ant_c;
}
#endif
#define REG_RECALIB_PERIOD (60)
/**
* iwl_good_plcp_health - checks for plcp error.
*
* When the plcp error is exceeding the thresholds, reset the radio
* to improve the throughput.
*/
bool iwl_good_plcp_health(struct iwl_priv *priv,
struct iwl_rx_packet *pkt)
{
bool rc = true;
int combined_plcp_delta;
unsigned int plcp_msec;
unsigned long plcp_received_jiffies;
if (priv->cfg->plcp_delta_threshold ==
IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
return rc;
}
/*
* check for plcp_err and trigger radio reset if it exceeds
* the plcp error threshold plcp_delta.
*/
plcp_received_jiffies = jiffies;
plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
(long) priv->plcp_jiffies);
priv->plcp_jiffies = plcp_received_jiffies;
/*
* check to make sure plcp_msec is not 0 to prevent division
* by zero.
*/
if (plcp_msec) {
combined_plcp_delta =
(le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
le32_to_cpu(priv->_agn.statistics.rx.ofdm.plcp_err)) +
(le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
le32_to_cpu(priv->_agn.statistics.rx.ofdm_ht.plcp_err));
if ((combined_plcp_delta > 0) &&
((combined_plcp_delta * 100) / plcp_msec) >
priv->cfg->plcp_delta_threshold) {
/*
* if plcp_err exceed the threshold,
* the following data is printed in csv format:
* Text: plcp_err exceeded %d,
* Received ofdm.plcp_err,
* Current ofdm.plcp_err,
* Received ofdm_ht.plcp_err,
* Current ofdm_ht.plcp_err,
* combined_plcp_delta,
* plcp_msec
*/
IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
"%u, %u, %u, %u, %d, %u mSecs\n",
priv->cfg->plcp_delta_threshold,
le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
le32_to_cpu(
priv->_agn.statistics.rx.ofdm.plcp_err),
le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
le32_to_cpu(
priv->_agn.statistics.rx.ofdm_ht.plcp_err),
combined_plcp_delta, plcp_msec);
rc = false;
}
}
return rc;
}
void iwl_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
int change;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
(int)sizeof(priv->_agn.statistics),
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
change = ((priv->_agn.statistics.general.temperature !=
pkt->u.stats.general.temperature) ||
((priv->_agn.statistics.flag &
STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
(pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
#endif
iwl_recover_from_statistics(priv, pkt);
memcpy(&priv->_agn.statistics, &pkt->u.stats,
sizeof(priv->_agn.statistics));
set_bit(STATUS_STATISTICS, &priv->status);
/* Reschedule the statistics timer to occur in
* REG_RECALIB_PERIOD seconds to ensure we get a
* thermal update even if the uCode doesn't give
* us one */
mod_timer(&priv->statistics_periodic, jiffies +
msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
(pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
iwl_rx_calc_noise(priv);
queue_work(priv->workqueue, &priv->run_time_calib_work);
}
if (priv->cfg->ops->lib->temp_ops.temperature && change)
priv->cfg->ops->lib->temp_ops.temperature(priv);
}
void iwl_reply_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
#ifdef CONFIG_IWLWIFI_DEBUGFS
memset(&priv->_agn.accum_statistics, 0,
sizeof(struct iwl_notif_statistics));
memset(&priv->_agn.delta_statistics, 0,
sizeof(struct iwl_notif_statistics));
memset(&priv->_agn.max_delta, 0,
sizeof(struct iwl_notif_statistics));
#endif
IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
}
iwl_rx_statistics(priv, rxb);
}

View File

@ -233,6 +233,7 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
{
unsigned long flags;
u16 ra_tid;
int ret;
if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
(IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@ -248,7 +249,9 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
ra_tid = BUILD_RAxTID(sta_id, tid);
/* Modify device's station table to Tx this TID */
iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
if (ret)
return ret;
spin_lock_irqsave(&priv->lock, flags);

View File

@ -1461,13 +1461,13 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
actual_ack_cnt_delta =
le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
le32_to_cpu(priv->statistics.tx.actual_ack_cnt);
le32_to_cpu(priv->_agn.statistics.tx.actual_ack_cnt);
expected_ack_cnt_delta =
le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) -
le32_to_cpu(priv->statistics.tx.expected_ack_cnt);
le32_to_cpu(priv->_agn.statistics.tx.expected_ack_cnt);
ba_timeout_delta =
le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) -
le32_to_cpu(priv->statistics.tx.agg.ba_timeout);
le32_to_cpu(priv->_agn.statistics.tx.agg.ba_timeout);
if ((priv->_agn.agg_tids_count > 0) &&
(expected_ack_cnt_delta > 0) &&
(((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta)
@ -1484,10 +1484,10 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
* DEBUG is not, these will just compile out.
*/
IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
priv->delta_statistics.tx.rx_detected_cnt);
priv->_agn.delta_statistics.tx.rx_detected_cnt);
IWL_DEBUG_RADIO(priv,
"ack_or_ba_timeout_collision delta = %d\n",
priv->delta_statistics.tx.
priv->_agn.delta_statistics.tx.
ack_or_ba_timeout_collision);
#endif
IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
@ -2310,9 +2310,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line,
blink1, blink2, ilink1, ilink2);
IWL_ERR(priv, "Desc Time "
IWL_ERR(priv, "Desc Time "
"data1 data2 line\n");
IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
desc_lookup(desc), desc, time, data1, data2, line);
IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n");
IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n",
@ -2935,9 +2935,9 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
}
if (priv->start_calib) {
iwl_chain_noise_calibration(priv, &priv->statistics);
iwl_chain_noise_calibration(priv, &priv->_agn.statistics);
iwl_sensitivity_calibration(priv, &priv->statistics);
iwl_sensitivity_calibration(priv, &priv->_agn.statistics);
}
mutex_unlock(&priv->mutex);
@ -3368,13 +3368,32 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return ret;
}
/*
* switch to RTS/CTS for TX
*/
static void iwl_enable_rts_cts(struct iwl_priv *priv)
{
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
if (!test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_INFO(priv, "use RTS/CTS protection\n");
iwlcore_commit_rxon(priv);
} else {
/* scanning, defer the request until scan completed */
IWL_DEBUG_INFO(priv, "defer setting RTS/CTS protection\n");
}
}
static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{
struct iwl_priv *priv = hw->priv;
int ret;
int ret = -EINVAL;
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
sta->addr, tid);
@ -3382,17 +3401,19 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
if (!(priv->cfg->sku & IWL_SKU_N))
return -EACCES;
mutex_lock(&priv->mutex);
switch (action) {
case IEEE80211_AMPDU_RX_START:
IWL_DEBUG_HT(priv, "start Rx\n");
return iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
break;
case IEEE80211_AMPDU_RX_STOP:
IWL_DEBUG_HT(priv, "stop Rx\n");
ret = iwl_sta_rx_agg_stop(priv, sta, tid);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return 0;
else
return ret;
ret = 0;
break;
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT(priv, "start Tx\n");
ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
@ -3401,7 +3422,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
priv->_agn.agg_tids_count);
}
return ret;
break;
case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT(priv, "stop Tx\n");
ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
@ -3411,18 +3432,22 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
priv->_agn.agg_tids_count);
}
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return 0;
else
return ret;
ret = 0;
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
/* do nothing */
return -EOPNOTSUPP;
default:
IWL_DEBUG_HT(priv, "unknown\n");
return -EINVAL;
if (priv->cfg->use_rts_for_ht) {
/*
* switch to RTS/CTS if it is the prefer protection
* method for HT traffic
*/
iwl_enable_rts_cts(priv);
}
ret = 0;
break;
}
return 0;
mutex_unlock(&priv->mutex);
return ret;
}
static void iwl_mac_sta_notify(struct ieee80211_hw *hw,

View File

@ -201,6 +201,16 @@ static inline bool iwl_is_tx_success(u32 status)
(status == TX_STATUS_DIRECT_DONE);
}
/* rx */
void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
bool iwl_good_plcp_health(struct iwl_priv *priv,
struct iwl_rx_packet *pkt);
void iwl_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwl_reply_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
/* scan */
void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);

View File

@ -1399,18 +1399,27 @@ struct iwl_rx_mpdu_res_start {
/* REPLY_TX Tx flags field */
/* 1: Use RTS/CTS protocol or CTS-to-self if spec allows it
/*
* 1: Use RTS/CTS protocol or CTS-to-self if spec allows it
* before this frame. if CTS-to-self required check
* RXON_FLG_SELF_CTS_EN status. */
#define TX_CMD_FLG_RTS_CTS_MSK cpu_to_le32(1 << 0)
* RXON_FLG_SELF_CTS_EN status.
* unused in 3945/4965, used in 5000 series and after
*/
#define TX_CMD_FLG_PROT_REQUIRE_MSK cpu_to_le32(1 << 0)
/* 1: Use Request-To-Send protocol before this frame.
* Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */
/*
* 1: Use Request-To-Send protocol before this frame.
* Mutually exclusive vs. TX_CMD_FLG_CTS_MSK.
* used in 3945/4965, unused in 5000 series and after
*/
#define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1)
/* 1: Transmit Clear-To-Send to self before this frame.
/*
* 1: Transmit Clear-To-Send to self before this frame.
* Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
* Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */
* Mutually exclusive vs. TX_CMD_FLG_RTS_MSK.
* used in 3945/4965, unused in 5000 series and after
*/
#define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2)
/* 1: Expect ACK from receiving station
@ -1430,8 +1439,11 @@ struct iwl_rx_mpdu_res_start {
* Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */
#define TX_CMD_FLG_IMM_BA_RSP_MASK cpu_to_le32(1 << 6)
/* 1: Frame requires full Tx-Op protection.
* Set this if either RTS or CTS Tx Flag gets set. */
/*
* 1: Frame requires full Tx-Op protection.
* Set this if either RTS or CTS Tx Flag gets set.
* used in 3945/4965, unused in 5000 series and after
*/
#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7)
/* Tx antenna selection field; used only for 3945, reserved (0) for 4965.

View File

@ -1331,7 +1331,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
changed_flags, *total_flags);
CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
CHK(FIF_ALLMULTI, RXON_FILTER_ACCEPT_GRP_MSK);
CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
@ -1346,6 +1345,12 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
mutex_unlock(&priv->mutex);
/*
* Receiving all multicast frames is always enabled by the
* default flags setup in iwl_connection_init_rx_config()
* since we currently do not support programming multicast
* filters into the device.
*/
*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
}
@ -2105,6 +2110,9 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
iwl_set_flags_for_band(priv, conf->channel->band, priv->vif);
spin_unlock_irqrestore(&priv->lock, flags);
if (priv->cfg->ops->lib->update_bcast_station)
ret = priv->cfg->ops->lib->update_bcast_station(priv);
set_ch_out:
/* The list of supported rates and rate mask can be different
* for each band; since the band may have changed, reset
@ -2837,6 +2845,7 @@ int iwl_pci_resume(struct pci_dev *pdev)
{
struct iwl_priv *priv = pci_get_drvdata(pdev);
int ret;
bool hw_rfkill = false;
/*
* We disable the RETRY_TIMEOUT register (0x41) to keep
@ -2851,6 +2860,17 @@ int iwl_pci_resume(struct pci_dev *pdev)
pci_restore_state(pdev);
iwl_enable_interrupts(priv);
if (!(iwl_read32(priv, CSR_GP_CNTRL) &
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
hw_rfkill = true;
if (hw_rfkill)
set_bit(STATUS_RF_KILL_HW, &priv->status);
else
clear_bit(STATUS_RF_KILL_HW, &priv->status);
wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rfkill);
return 0;
}
EXPORT_SYMBOL(iwl_pci_resume);

View File

@ -196,6 +196,7 @@ struct iwl_lib_ops {
/* station management */
int (*manage_ibss_station)(struct iwl_priv *priv,
struct ieee80211_vif *vif, bool add);
int (*update_bcast_station)(struct iwl_priv *priv);
/* recover from tx queue stall */
void (*recover_from_tx_stall)(unsigned long data);
/* check for plcp health */
@ -330,6 +331,7 @@ struct iwl_cfg {
const bool chain_noise_calib_by_driver;
u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
const bool need_dc_calib;
};
/***************************
@ -455,20 +457,10 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
int iwl_rx_queue_space(const struct iwl_rx_queue *q);
void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
/* Handlers */
void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
bool iwl_good_plcp_health(struct iwl_priv *priv,
struct iwl_rx_packet *pkt);
bool iwl_good_ack_health(struct iwl_priv *priv,
struct iwl_rx_packet *pkt);
void iwl_recover_from_statistics(struct iwl_priv *priv,
struct iwl_rx_packet *pkt);
void iwl_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwl_reply_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);

View File

@ -1430,10 +1430,10 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
return -EFAULT;
if (sscanf(buf, "%d", &plcp) != 1)
return -EINVAL;
if ((plcp <= IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
priv->cfg->plcp_delta_threshold =
IWL_MAX_PLCP_ERR_THRESHOLD_DEF;
IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
else
priv->cfg->plcp_delta_threshold = plcp;
return count;

View File

@ -1036,11 +1036,12 @@ struct iwl_event_log {
* This is the threshold value of plcp error rate per 100mSecs. It is
* used to set and check for the validity of plcp_delta.
*/
#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0)
#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (1)
#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200)
#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE (0)
#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3)
#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
@ -1224,13 +1225,6 @@ struct iwl_priv {
struct iwl_power_mgr power_data;
struct iwl_tt_mgmt thermal_throttle;
struct iwl_notif_statistics statistics;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct iwl_notif_statistics accum_statistics;
struct iwl_notif_statistics delta_statistics;
struct iwl_notif_statistics max_delta;
#endif
/* context information */
u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */
@ -1323,6 +1317,13 @@ struct iwl_priv {
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
struct iwl_notif_statistics statistics;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct iwl_notif_statistics accum_statistics;
struct iwl_notif_statistics delta_statistics;
struct iwl_notif_statistics max_delta;
#endif
} _agn;
#endif
};

View File

@ -629,6 +629,9 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
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",

View File

@ -205,26 +205,6 @@ err_bd:
}
EXPORT_SYMBOL(iwl_rx_queue_alloc);
void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_missed_beacon_notif *missed_beacon;
missed_beacon = &pkt->u.missed_beacon;
if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
priv->missed_beacon_threshold) {
IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
le32_to_cpu(missed_beacon->consecutive_missed_beacons),
le32_to_cpu(missed_beacon->total_missed_becons),
le32_to_cpu(missed_beacon->num_recvd_beacons),
le32_to_cpu(missed_beacon->num_expected_beacons));
if (!test_bit(STATUS_SCANNING, &priv->status))
iwl_init_sensitivity(priv);
}
}
EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
@ -243,161 +223,6 @@ void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif);
/* Calculate noise level, based on measurements during network silence just
* before arriving beacon. This measurement can be done only if we know
* exactly when to expect beacons, therefore only when we're associated. */
static void iwl_rx_calc_noise(struct iwl_priv *priv)
{
struct statistics_rx_non_phy *rx_info
= &(priv->statistics.rx.general);
int num_active_rx = 0;
int total_silence = 0;
int bcn_silence_a =
le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
int bcn_silence_b =
le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
int bcn_silence_c =
le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
int last_rx_noise;
if (bcn_silence_a) {
total_silence += bcn_silence_a;
num_active_rx++;
}
if (bcn_silence_b) {
total_silence += bcn_silence_b;
num_active_rx++;
}
if (bcn_silence_c) {
total_silence += bcn_silence_c;
num_active_rx++;
}
/* Average among active antennas */
if (num_active_rx)
last_rx_noise = (total_silence / num_active_rx) - 107;
else
last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
bcn_silence_a, bcn_silence_b, bcn_silence_c,
last_rx_noise);
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
/*
* based on the assumption of all statistics counter are in DWORD
* FIXME: This function is for debugging, do not deal with
* the case of counters roll-over.
*/
static void iwl_accumulative_statistics(struct iwl_priv *priv,
__le32 *stats)
{
int i;
__le32 *prev_stats;
u32 *accum_stats;
u32 *delta, *max_delta;
prev_stats = (__le32 *)&priv->statistics;
accum_stats = (u32 *)&priv->accum_statistics;
delta = (u32 *)&priv->delta_statistics;
max_delta = (u32 *)&priv->max_delta;
for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
i += sizeof(__le32), stats++, prev_stats++, delta++,
max_delta++, accum_stats++) {
if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
*delta = (le32_to_cpu(*stats) -
le32_to_cpu(*prev_stats));
*accum_stats += *delta;
if (*delta > *max_delta)
*max_delta = *delta;
}
}
/* reset accumulative statistics for "no-counter" type statistics */
priv->accum_statistics.general.temperature =
priv->statistics.general.temperature;
priv->accum_statistics.general.temperature_m =
priv->statistics.general.temperature_m;
priv->accum_statistics.general.ttl_timestamp =
priv->statistics.general.ttl_timestamp;
priv->accum_statistics.tx.tx_power.ant_a =
priv->statistics.tx.tx_power.ant_a;
priv->accum_statistics.tx.tx_power.ant_b =
priv->statistics.tx.tx_power.ant_b;
priv->accum_statistics.tx.tx_power.ant_c =
priv->statistics.tx.tx_power.ant_c;
}
#endif
#define REG_RECALIB_PERIOD (60)
/**
* iwl_good_plcp_health - checks for plcp error.
*
* When the plcp error is exceeding the thresholds, reset the radio
* to improve the throughput.
*/
bool iwl_good_plcp_health(struct iwl_priv *priv,
struct iwl_rx_packet *pkt)
{
bool rc = true;
int combined_plcp_delta;
unsigned int plcp_msec;
unsigned long plcp_received_jiffies;
/*
* check for plcp_err and trigger radio reset if it exceeds
* the plcp error threshold plcp_delta.
*/
plcp_received_jiffies = jiffies;
plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
(long) priv->plcp_jiffies);
priv->plcp_jiffies = plcp_received_jiffies;
/*
* check to make sure plcp_msec is not 0 to prevent division
* by zero.
*/
if (plcp_msec) {
combined_plcp_delta =
(le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) +
(le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err));
if ((combined_plcp_delta > 0) &&
((combined_plcp_delta * 100) / plcp_msec) >
priv->cfg->plcp_delta_threshold) {
/*
* if plcp_err exceed the threshold,
* the following data is printed in csv format:
* Text: plcp_err exceeded %d,
* Received ofdm.plcp_err,
* Current ofdm.plcp_err,
* Received ofdm_ht.plcp_err,
* Current ofdm_ht.plcp_err,
* combined_plcp_delta,
* plcp_msec
*/
IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
"%u, %u, %u, %u, %d, %u mSecs\n",
priv->cfg->plcp_delta_threshold,
le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
le32_to_cpu(priv->statistics.rx.ofdm.plcp_err),
le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
le32_to_cpu(
priv->statistics.rx.ofdm_ht.plcp_err),
combined_plcp_delta, plcp_msec);
rc = false;
}
}
return rc;
}
EXPORT_SYMBOL(iwl_good_plcp_health);
void iwl_recover_from_statistics(struct iwl_priv *priv,
struct iwl_rx_packet *pkt)
{
@ -431,69 +256,6 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_recover_from_statistics);
void iwl_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
int change;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
(int)sizeof(priv->statistics),
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
change = ((priv->statistics.general.temperature !=
pkt->u.stats.general.temperature) ||
((priv->statistics.flag &
STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
(pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
#endif
iwl_recover_from_statistics(priv, pkt);
memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
set_bit(STATUS_STATISTICS, &priv->status);
/* Reschedule the statistics timer to occur in
* REG_RECALIB_PERIOD seconds to ensure we get a
* thermal update even if the uCode doesn't give
* us one */
mod_timer(&priv->statistics_periodic, jiffies +
msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
(pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
iwl_rx_calc_noise(priv);
queue_work(priv->workqueue, &priv->run_time_calib_work);
}
if (priv->cfg->ops->lib->temp_ops.temperature && change)
priv->cfg->ops->lib->temp_ops.temperature(priv);
}
EXPORT_SYMBOL(iwl_rx_statistics);
void iwl_reply_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
#ifdef CONFIG_IWLWIFI_DEBUGFS
memset(&priv->accum_statistics, 0,
sizeof(struct iwl_notif_statistics));
memset(&priv->delta_statistics, 0,
sizeof(struct iwl_notif_statistics));
memset(&priv->max_delta, 0,
sizeof(struct iwl_notif_statistics));
#endif
IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
}
iwl_rx_statistics(priv, rxb);
}
EXPORT_SYMBOL(iwl_reply_statistics);
/*
* returns non-zero if packet should be dropped
*/

View File

@ -537,6 +537,15 @@ void iwl_bg_scan_completed(struct work_struct *work)
/* Since setting the TXPOWER may have been deferred while
* 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
*/
if (memcmp(&priv->active_rxon,
&priv->staging_rxon, sizeof(priv->staging_rxon)))
iwlcore_commit_rxon(priv);
out:
mutex_unlock(&priv->mutex);

View File

@ -30,6 +30,7 @@
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <linux/sched.h>
#include <linux/lockdep.h>
#include "iwl-dev.h"
#include "iwl-core.h"
@ -54,18 +55,19 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
}
}
static void iwl_process_add_sta_resp(struct iwl_priv *priv,
struct iwl_addsta_cmd *addsta,
struct iwl_rx_packet *pkt,
bool sync)
static int iwl_process_add_sta_resp(struct iwl_priv *priv,
struct iwl_addsta_cmd *addsta,
struct iwl_rx_packet *pkt,
bool sync)
{
u8 sta_id = addsta->sta.sta_id;
unsigned long flags;
int ret = -EIO;
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
pkt->hdr.flags);
return;
return ret;
}
IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
@ -77,6 +79,7 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv,
case ADD_STA_SUCCESS_MSK:
IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
iwl_sta_ucode_activate(priv, sta_id);
ret = 0;
break;
case ADD_STA_NO_ROOM_IN_TABLE:
IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
@ -114,6 +117,8 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv,
STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
addsta->sta.addr);
spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
}
static void iwl_add_sta_callback(struct iwl_priv *priv,
@ -145,8 +150,10 @@ int iwl_send_add_sta(struct iwl_priv *priv,
if (flags & CMD_ASYNC)
cmd.callback = iwl_add_sta_callback;
else
else {
cmd.flags |= CMD_WANT_SKB;
might_sleep();
}
cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
ret = iwl_send_cmd(priv, &cmd);
@ -156,7 +163,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
if (ret == 0) {
pkt = (struct iwl_rx_packet *)cmd.reply_page;
iwl_process_add_sta_resp(priv, sta, pkt, true);
ret = iwl_process_add_sta_resp(priv, sta, pkt, true);
}
iwl_free_pages(priv, cmd.reply_page);
@ -831,7 +838,9 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
{
unsigned long flags;
__le16 key_flags = 0;
int ret;
struct iwl_addsta_cmd sta_cmd;
lockdep_assert_held(&priv->mutex);
keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
@ -871,11 +880,10 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
@ -884,7 +892,9 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
{
unsigned long flags;
__le16 key_flags = 0;
int ret;
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);
@ -919,11 +929,10 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
@ -1013,9 +1022,11 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
u8 sta_id)
{
unsigned long flags;
int ret = 0;
u16 key_flags;
u8 keyidx;
struct iwl_addsta_cmd sta_cmd;
lockdep_assert_held(&priv->mutex);
priv->key_mapping_key--;
@ -1062,9 +1073,10 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
spin_unlock_irqrestore(&priv->sta_lock, flags);
return 0;
}
ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
EXPORT_SYMBOL(iwl_remove_dynamic_key);
@ -1073,6 +1085,8 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
{
int ret;
lockdep_assert_held(&priv->mutex);
priv->key_mapping_key++;
keyconf->hw_key_idx = HW_KEY_DYNAMIC;
@ -1245,6 +1259,36 @@ int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq)
}
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.
*/
int iwl_update_bcast_station(struct iwl_priv *priv)
{
unsigned long flags;
struct iwl_link_quality_cmd *link_cmd;
u8 sta_id = priv->hw_params.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;
}
EXPORT_SYMBOL_GPL(iwl_update_bcast_station);
void iwl_dealloc_bcast_station(struct iwl_priv *priv)
{
unsigned long flags;
@ -1268,17 +1312,22 @@ EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station);
/**
* iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
*/
void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
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;
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
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);
@ -1287,6 +1336,9 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
{
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)
@ -1298,10 +1350,10 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
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, &priv->stations[sta_id].sta,
CMD_ASYNC);
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
EXPORT_SYMBOL(iwl_sta_rx_agg_start);
@ -1309,7 +1361,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
int tid)
{
unsigned long flags;
int sta_id, ret;
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) {
@ -1322,11 +1377,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
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;
ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
EXPORT_SYMBOL(iwl_sta_rx_agg_stop);

View File

@ -60,6 +60,7 @@ void iwl_restore_stations(struct iwl_priv *priv);
void iwl_clear_ucode_stations(struct iwl_priv *priv);
int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq);
void iwl_dealloc_bcast_station(struct iwl_priv *priv);
int iwl_update_bcast_station(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);
@ -73,7 +74,7 @@ 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);
void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
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,

View File

@ -1424,7 +1424,7 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32));
IWL_ERR(priv,
"%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
"%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
desc_lookup(desc), desc, time, blink1, blink2,
ilink1, ilink2, data1);
trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0,

View File

@ -670,20 +670,24 @@ static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
}
static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
enum tx_power_setting type, int dbm)
enum nl80211_tx_power_setting type, int mbm)
{
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
int ret;
switch (type) {
case TX_POWER_AUTOMATIC:
case NL80211_TX_POWER_AUTOMATIC:
return 0;
case TX_POWER_FIXED:
case NL80211_TX_POWER_FIXED:
if (mbm < 0 || (mbm % 100))
return -EOPNOTSUPP;
if (!test_bit(IWM_STATUS_READY, &iwm->status))
return 0;
ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
CFG_TX_PWR_LIMIT_USR, dbm * 2);
CFG_TX_PWR_LIMIT_USR,
MBM_TO_DBM(mbm) * 2);
if (ret < 0)
return ret;

View File

@ -1,4 +1,3 @@
libertas-y += assoc.o
libertas-y += cfg.o
libertas-y += cmd.o
libertas-y += cmdresp.o
@ -6,9 +5,7 @@ libertas-y += debugfs.o
libertas-y += ethtool.o
libertas-y += main.o
libertas-y += rx.o
libertas-y += scan.o
libertas-y += tx.o
libertas-y += wext.o
libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o
usb8xxx-objs += if_usb.o

File diff suppressed because it is too large Load Diff

View File

@ -1,155 +0,0 @@
/* Copyright (C) 2006, Red Hat, Inc. */
#ifndef _LBS_ASSOC_H_
#define _LBS_ASSOC_H_
#include "defs.h"
#include "host.h"
struct lbs_private;
/*
* In theory, the IE is limited to the IE length, 255,
* but in practice 64 bytes are enough.
*/
#define MAX_WPA_IE_LEN 64
struct lbs_802_11_security {
u8 WPAenabled;
u8 WPA2enabled;
u8 wep_enabled;
u8 auth_mode;
u32 key_mgmt;
};
/** Current Basic Service Set State Structure */
struct current_bss_params {
/** bssid */
u8 bssid[ETH_ALEN];
/** ssid */
u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 ssid_len;
/** band */
u8 band;
/** channel is directly in priv->channel */
/** zero-terminated array of supported data rates */
u8 rates[MAX_RATES + 1];
};
/**
* @brief Structure used to store information for each beacon/probe response
*/
struct bss_descriptor {
u8 bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 ssid_len;
u16 capability;
u32 rssi;
u32 channel;
u16 beaconperiod;
__le16 atimwindow;
/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
u8 mode;
/* zero-terminated array of supported data rates */
u8 rates[MAX_RATES + 1];
unsigned long last_scanned;
union ieee_phy_param_set phy;
union ieee_ss_param_set ss;
u8 wpa_ie[MAX_WPA_IE_LEN];
size_t wpa_ie_len;
u8 rsn_ie[MAX_WPA_IE_LEN];
size_t rsn_ie_len;
u8 mesh;
struct list_head list;
};
/** Association request
*
* Encapsulates all the options that describe a specific assocation request
* or configuration of the wireless card's radio, mode, and security settings.
*/
struct assoc_request {
#define ASSOC_FLAG_SSID 1
#define ASSOC_FLAG_CHANNEL 2
#define ASSOC_FLAG_BAND 3
#define ASSOC_FLAG_MODE 4
#define ASSOC_FLAG_BSSID 5
#define ASSOC_FLAG_WEP_KEYS 6
#define ASSOC_FLAG_WEP_TX_KEYIDX 7
#define ASSOC_FLAG_WPA_MCAST_KEY 8
#define ASSOC_FLAG_WPA_UCAST_KEY 9
#define ASSOC_FLAG_SECINFO 10
#define ASSOC_FLAG_WPA_IE 11
unsigned long flags;
u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 ssid_len;
u8 channel;
u8 band;
u8 mode;
u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
/** WEP keys */
struct enc_key wep_keys[4];
u16 wep_tx_keyidx;
/** WPA keys */
struct enc_key wpa_mcast_key;
struct enc_key wpa_unicast_key;
struct lbs_802_11_security secinfo;
/** WPA Information Elements*/
u8 wpa_ie[MAX_WPA_IE_LEN];
u8 wpa_ie_len;
/* BSS to associate with for infrastructure of Ad-Hoc join */
struct bss_descriptor bss;
};
extern u8 lbs_bg_rates[MAX_RATES];
void lbs_association_worker(struct work_struct *work);
struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
int lbs_adhoc_stop(struct lbs_private *priv);
int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
u8 bssid[ETH_ALEN], u16 reason);
int lbs_cmd_802_11_rssi(struct lbs_private *priv,
struct cmd_ds_command *cmd);
int lbs_ret_802_11_rssi(struct lbs_private *priv,
struct cmd_ds_command *resp);
int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action);
int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
struct cmd_ds_command *resp);
int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
struct assoc_request *assoc);
int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
uint16_t *enable);
int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
struct assoc_request *assoc);
#endif /* _LBS_ASSOC_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,27 @@
#ifndef __LBS_CFG80211_H__
#define __LBS_CFG80211_H__
#include "dev.h"
struct device;
struct lbs_private;
struct regulatory_request;
struct wiphy;
struct wireless_dev *lbs_cfg_alloc(struct device *dev);
int lbs_cfg_register(struct lbs_private *priv);
void lbs_cfg_free(struct lbs_private *priv);
int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
u8 ssid_len);
int lbs_scan_networks(struct lbs_private *priv, int full_scan);
void lbs_cfg_scan_worker(struct work_struct *work);
int lbs_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *request);
/* All of those are TODOs: */
#define lbs_cmd_802_11_rssi(priv, cmdptr) (0)
#define lbs_ret_802_11_rssi(priv, resp) (0)
#define lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action) (0)
#define lbs_ret_802_11_bcn_ctrl(priv, resp) (0)
void lbs_send_disconnect_notification(struct lbs_private *priv);
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
void lbs_scan_deinit(struct lbs_private *priv);
#endif

View File

@ -7,13 +7,8 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include "host.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "assoc.h"
#include "wext.h"
#include "scan.h"
#include "cfg.h"
#include "cmd.h"
@ -177,11 +172,6 @@ int lbs_update_hw_spec(struct lbs_private *priv)
if (priv->mesh_dev)
memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
ret = -1;
goto out;
}
out:
lbs_deb_leave(LBS_DEB_CMD);
return ret;
@ -908,6 +898,66 @@ void lbs_set_mac_control(struct lbs_private *priv)
lbs_deb_leave(LBS_DEB_CMD);
}
/**
* @brief This function implements command CMD_802_11D_DOMAIN_INFO
* @param priv pointer to struct lbs_private
* @param cmd pointer to cmd buffer
* @param cmdno cmd ID
* @param cmdOption cmd action
* @return 0
*/
int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmdoption)
{
struct cmd_ds_802_11d_domain_info *pdomaininfo =
&cmd->params.domaininfo;
struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain;
u8 nr_triplet = priv->domain_reg.no_triplet;
lbs_deb_enter(LBS_DEB_11D);
lbs_deb_11d("nr_triplet=%x\n", nr_triplet);
pdomaininfo->action = cpu_to_le16(cmdoption);
if (cmdoption == CMD_ACT_GET) {
cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
sizeof(struct cmd_header));
lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
le16_to_cpu(cmd->size));
goto done;
}
domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
memcpy(domain->countrycode, priv->domain_reg.country_code,
sizeof(domain->countrycode));
domain->header.len = cpu_to_le16(nr_triplet
* sizeof(struct ieee80211_country_ie_triplet)
+ sizeof(domain->countrycode));
if (nr_triplet) {
memcpy(domain->triplet, priv->domain_reg.triplet,
nr_triplet *
sizeof(struct ieee80211_country_ie_triplet));
cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
le16_to_cpu(domain->header.len) +
sizeof(struct mrvl_ie_header) +
sizeof(struct cmd_header));
} else {
cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
sizeof(struct cmd_header));
}
lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
le16_to_cpu(cmd->size));
done:
lbs_deb_enter(LBS_DEB_11D);
return 0;
}
/**
* @brief This function prepare the command before send to firmware.
*
@ -1006,6 +1056,11 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
ret = 0;
goto done;
case CMD_802_11D_DOMAIN_INFO:
cmdptr->command = cpu_to_le16(cmd_no);
ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, cmd_action);
break;
case CMD_802_11_TPC_CFG:
cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
cmdptr->size =
@ -1325,6 +1380,15 @@ int lbs_execute_next_command(struct lbs_private *priv)
* check if in power save mode, if yes, put the device back
* to PS mode
*/
#ifdef TODO
/*
* This was the old code for libertas+wext. Someone that
* understands this beast should re-code it in a sane way.
*
* I actually don't understand why this is related to WPA
* and to connection status, shouldn't powering should be
* independ of such things?
*/
if ((priv->psmode != LBS802_11POWERMODECAM) &&
(priv->psstate == PS_STATE_FULL_POWER) &&
((priv->connect_status == LBS_CONNECTED) ||
@ -1346,6 +1410,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
lbs_ps_sleep(priv, 0);
}
}
#endif
}
ret = 0;

View File

@ -5,18 +5,10 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <asm/unaligned.h>
#include <net/iw_handler.h>
#include <net/cfg80211.h>
#include "host.h"
#include "decl.h"
#include "cmd.h"
#include "defs.h"
#include "dev.h"
#include "assoc.h"
#include "wext.h"
#include "cfg.h"
#include "cmd.h"
/**
@ -39,7 +31,9 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
* It causes problem in the Supplicant
*/
msleep_interruptible(1000);
lbs_send_disconnect_notification(priv);
if (priv->wdev->iftype == NL80211_IFTYPE_STATION)
lbs_send_disconnect_notification(priv);
/* report disconnect to upper layer */
netif_stop_queue(priv->dev);
@ -50,23 +44,8 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
priv->currenttxskb = NULL;
priv->tx_pending_len = 0;
/* reset SNR/NF/RSSI values */
memset(priv->SNR, 0x00, sizeof(priv->SNR));
memset(priv->NF, 0x00, sizeof(priv->NF));
memset(priv->RSSI, 0x00, sizeof(priv->RSSI));
memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
priv->nextSNRNF = 0;
priv->numSNRNF = 0;
priv->connect_status = LBS_DISCONNECTED;
/* Clear out associated SSID and BSSID since connection is
* no longer valid.
*/
memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
memset(&priv->curbssparams.ssid, 0, IEEE80211_MAX_SSID_LEN);
priv->curbssparams.ssid_len = 0;
if (priv->psstate != PS_STATE_FULL_POWER) {
/* make firmware to exit PS mode */
lbs_deb_cmd("disconnected, so exit PS mode\n");
@ -118,6 +97,52 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
return ret;
}
/**
* @brief This function parses countryinfo from AP and download country info to FW
* @param priv pointer to struct lbs_private
* @param resp pointer to command response buffer
* @return 0; -1
*/
static int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
{
struct cmd_ds_802_11d_domain_info *domaininfo =
&resp->params.domaininforesp;
struct mrvl_ie_domain_param_set *domain = &domaininfo->domain;
u16 action = le16_to_cpu(domaininfo->action);
s16 ret = 0;
u8 nr_triplet = 0;
lbs_deb_enter(LBS_DEB_11D);
lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp,
(int)le16_to_cpu(resp->size));
nr_triplet = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
sizeof(struct ieee80211_country_ie_triplet);
lbs_deb_11d("domain info resp: nr_triplet %d\n", nr_triplet);
if (nr_triplet > MRVDRV_MAX_TRIPLET_802_11D) {
lbs_deb_11d("invalid number of triplets returned!!\n");
return -1;
}
switch (action) {
case CMD_ACT_SET: /*Proc set action */
break;
case CMD_ACT_GET:
break;
default:
lbs_deb_11d("invalid action:%d\n", domaininfo->action);
ret = -1;
break;
}
lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
return ret;
}
static inline int handle_cmd_response(struct lbs_private *priv,
struct cmd_header *cmd_response)
{
@ -151,6 +176,10 @@ static inline int handle_cmd_response(struct lbs_private *priv,
ret = lbs_ret_802_11_rssi(priv, resp);
break;
case CMD_RET(CMD_802_11D_DOMAIN_INFO):
ret = lbs_ret_802_11d_domain_info(resp);
break;
case CMD_RET(CMD_802_11_TPC_CFG):
spin_lock_irqsave(&priv->driver_lock, flags);
memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg,
@ -262,7 +291,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
* ad-hoc mode. It takes place in
* lbs_execute_next_command().
*/
if (priv->mode == IW_MODE_ADHOC &&
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR &&
action == CMD_SUBCMD_ENTER_PS)
priv->psmode = LBS802_11POWERMODECAM;
} else if (action == CMD_SUBCMD_ENTER_PS) {

View File

@ -1,18 +1,13 @@
#include <linux/module.h>
#include <linux/dcache.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <net/iw_handler.h>
#include <net/lib80211.h>
#include "dev.h"
#include "decl.h"
#include "host.h"
#include "debugfs.h"
#include "cmd.h"
#include "debugfs.h"
static struct dentry *lbs_dir;
static char *szStates[] = {
@ -60,51 +55,6 @@ static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
return res;
}
static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
size_t pos = 0;
int numscansdone = 0, res;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
DECLARE_SSID_BUF(ssid);
struct bss_descriptor * iter_bss;
if (!buf)
return -ENOMEM;
pos += snprintf(buf+pos, len-pos,
"# | ch | rssi | bssid | cap | Qual | SSID\n");
mutex_lock(&priv->lock);
list_for_each_entry (iter_bss, &priv->network_list, list) {
u16 ibss = (iter_bss->capability & WLAN_CAPABILITY_IBSS);
u16 privacy = (iter_bss->capability & WLAN_CAPABILITY_PRIVACY);
u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
pos += snprintf(buf+pos, len-pos, "%02u| %03d | %04d | %pM |",
numscansdone, iter_bss->channel, iter_bss->rssi,
iter_bss->bssid);
pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
pos += snprintf(buf+pos, len-pos, "%c%c%c |",
ibss ? 'A' : 'I', privacy ? 'P' : ' ',
spectrum_mgmt ? 'S' : ' ');
pos += snprintf(buf+pos, len-pos, " %04d |", SCAN_RSSI(iter_bss->rssi));
pos += snprintf(buf+pos, len-pos, " %s\n",
print_ssid(ssid, iter_bss->ssid,
iter_bss->ssid_len));
numscansdone++;
}
mutex_unlock(&priv->lock);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
free_page(addr);
return res;
}
static ssize_t lbs_sleepparams_write(struct file *file,
const char __user *user_buf, size_t count,
loff_t *ppos)
@ -723,8 +673,6 @@ struct lbs_debugfs_files {
static const struct lbs_debugfs_files debugfs_files[] = {
{ "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
{ "getscantable", 0444, FOPS(lbs_getscantable,
write_file_dummy), },
{ "sleepparams", 0644, FOPS(lbs_sleepparams_read,
lbs_sleepparams_write), },
};

View File

@ -1,3 +1,4 @@
/**
* This file contains declaration referring to
* functions defined in other source files
@ -12,6 +13,7 @@
struct lbs_private;
struct sk_buff;
struct net_device;
struct cmd_ds_command;
/* ethtool.c */
@ -34,6 +36,8 @@ int lbs_start_card(struct lbs_private *priv);
void lbs_stop_card(struct lbs_private *priv);
void lbs_host_to_card_done(struct lbs_private *priv);
int lbs_rtap_supported(struct lbs_private *priv);
int lbs_set_mac_address(struct net_device *dev, void *addr);
void lbs_set_multicast_list(struct net_device *dev);
@ -49,5 +53,9 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
u32 lbs_fw_index_to_data_rate(u8 index);
u8 lbs_data_rate_to_fw_index(u32 rate);
int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
struct cmd_ds_command *cmd, u16 cmdoption);
int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
#endif

View File

@ -7,8 +7,8 @@
#define _LBS_DEV_H_
#include "mesh.h"
#include "scan.h"
#include "assoc.h"
#include "defs.h"
#include "host.h"
#include <linux/kfifo.h>
@ -29,7 +29,6 @@ struct lbs_private {
/* Basic networking */
struct net_device *dev;
u32 connect_status;
int infra_open;
struct work_struct mcast_work;
u32 nr_of_multicastmacaddr;
u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
@ -37,6 +36,9 @@ struct lbs_private {
/* CFG80211 */
struct wireless_dev *wdev;
bool wiphy_registered;
struct cfg80211_scan_request *scan_req;
u8 assoc_bss[ETH_ALEN];
u8 disassoc_reason;
/* Mesh */
struct net_device *mesh_dev; /* Virtual device */
@ -49,10 +51,6 @@ struct lbs_private {
u8 mesh_ssid_len;
#endif
/* Monitor mode */
struct net_device *rtap_net_dev;
u32 monitormode;
/* Debugfs */
struct dentry *debugfs_dir;
struct dentry *debugfs_debug;
@ -62,6 +60,9 @@ struct lbs_private {
struct dentry *regs_dir;
struct dentry *debugfs_regs_files[6];
/** 11D and domain regulatory data */
struct lbs_802_11d_domain_reg domain_reg;
/* Hardware debugging */
u32 mac_offset;
u32 bbp_offset;
@ -133,14 +134,10 @@ struct lbs_private {
struct workqueue_struct *work_thread;
/** Encryption stuff */
struct lbs_802_11_security secinfo;
struct enc_key wpa_mcast_key;
struct enc_key wpa_unicast_key;
u8 wpa_ie[MAX_WPA_IE_LEN];
u8 wpa_ie_len;
u16 wep_tx_keyidx;
struct enc_key wep_keys[4];
u8 authtype_auto;
u8 wep_tx_key;
u8 wep_key[4][WLAN_KEY_LEN_WEP104];
u8 wep_key_len[4];
/* Wake On LAN */
uint32_t wol_criteria;
@ -161,6 +158,7 @@ struct lbs_private {
/* NIC/link operation characteristics */
u16 mac_control;
u8 radio_on;
u8 cur_rate;
u8 channel;
s16 txpower_cur;
s16 txpower_min;
@ -169,42 +167,6 @@ struct lbs_private {
/** Scanning */
struct delayed_work scan_work;
int scan_channel;
/* remember which channel was scanned last, != 0 if currently scanning */
u8 scan_ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 scan_ssid_len;
/* Associating */
struct delayed_work assoc_work;
struct current_bss_params curbssparams;
u8 mode;
struct list_head network_list;
struct list_head network_free_list;
struct bss_descriptor *networks;
struct assoc_request * pending_assoc_req;
struct assoc_request * in_progress_assoc_req;
uint16_t enablehwauto;
/* ADHOC */
u16 beacon_period;
u8 beacon_enable;
u8 adhoccreate;
/* WEXT */
char name[DEV_NAME_LEN];
u8 nodename[16];
struct iw_statistics wstats;
u8 cur_rate;
#define MAX_REGION_CHANNEL_NUM 2
struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];
/** Requested Signal Strength*/
u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG];
u16 NF[MAX_TYPE_B][MAX_TYPE_AVG];
u8 RSSI[MAX_TYPE_B][MAX_TYPE_AVG];
u8 rawSNR[DEFAULT_DATA_AVG_FACTOR];
u8 rawNF[DEFAULT_DATA_AVG_FACTOR];
u16 nextSNRNF;
u16 numSNRNF;
};
extern struct cmd_confirm_sleep confirm_sleep;

View File

@ -2,13 +2,8 @@
#include <linux/ethtool.h>
#include <linux/delay.h>
#include "host.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "wext.h"
#include "cmd.h"
#include "mesh.h"
static void lbs_ethtool_get_drvinfo(struct net_device *dev,

View File

@ -389,6 +389,30 @@ struct lbs_offset_value {
u32 value;
} __packed;
#define MRVDRV_MAX_TRIPLET_802_11D 83
#define COUNTRY_CODE_LEN 3
struct mrvl_ie_domain_param_set {
struct mrvl_ie_header header;
u8 countrycode[COUNTRY_CODE_LEN];
struct ieee80211_country_ie_triplet triplet[1];
} __attribute__ ((packed));
struct cmd_ds_802_11d_domain_info {
__le16 action;
struct mrvl_ie_domain_param_set domain;
} __attribute__ ((packed));
struct lbs_802_11d_domain_reg {
/** Country code*/
u8 country_code[COUNTRY_CODE_LEN];
/** No. of triplet*/
u8 no_triplet;
struct ieee80211_country_ie_triplet triplet[MRVDRV_MAX_TRIPLET_802_11D];
} __attribute__ ((packed));
/*
* Define data structure for CMD_GET_HW_SPEC
* This structure defines the response for the GET_HW_SPEC command
@ -949,6 +973,9 @@ struct cmd_ds_command {
struct cmd_ds_bbp_reg_access bbpreg;
struct cmd_ds_rf_reg_access rfreg;
struct cmd_ds_802_11d_domain_info domaininfo;
struct cmd_ds_802_11d_domain_info domaininforesp;
struct cmd_ds_802_11_tpc_cfg tpccfg;
struct cmd_ds_802_11_afc afc;
struct cmd_ds_802_11_led_ctrl ledgpio;
@ -958,5 +985,4 @@ struct cmd_ds_command {
struct cmd_ds_802_11_beacon_control bcn_ctrl;
} params;
} __packed;
#endif

View File

@ -11,20 +11,14 @@
#include <linux/if_arp.h>
#include <linux/kthread.h>
#include <linux/kfifo.h>
#include <linux/stddef.h>
#include <linux/ieee80211.h>
#include <linux/slab.h>
#include <net/iw_handler.h>
#include <net/cfg80211.h>
#include "host.h"
#include "decl.h"
#include "dev.h"
#include "wext.h"
#include "cfg.h"
#include "debugfs.h"
#include "scan.h"
#include "assoc.h"
#include "cmd.h"
#define DRIVER_RELEASE_VERSION "323.p0"
@ -96,72 +90,6 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
}
static int lbs_add_rtap(struct lbs_private *priv);
static void lbs_remove_rtap(struct lbs_private *priv);
/**
* Get function for sysfs attribute rtap
*/
static ssize_t lbs_rtap_get(struct device *dev,
struct device_attribute *attr, char * buf)
{
struct lbs_private *priv = to_net_dev(dev)->ml_priv;
return snprintf(buf, 5, "0x%X\n", priv->monitormode);
}
/**
* Set function for sysfs attribute rtap
*/
static ssize_t lbs_rtap_set(struct device *dev,
struct device_attribute *attr, const char * buf, size_t count)
{
int monitor_mode;
struct lbs_private *priv = to_net_dev(dev)->ml_priv;
sscanf(buf, "%x", &monitor_mode);
if (monitor_mode) {
if (priv->monitormode == monitor_mode)
return strlen(buf);
if (!priv->monitormode) {
if (priv->infra_open || lbs_mesh_open(priv))
return -EBUSY;
if (priv->mode == IW_MODE_INFRA)
lbs_cmd_80211_deauthenticate(priv,
priv->curbssparams.bssid,
WLAN_REASON_DEAUTH_LEAVING);
else if (priv->mode == IW_MODE_ADHOC)
lbs_adhoc_stop(priv);
lbs_add_rtap(priv);
}
priv->monitormode = monitor_mode;
} else {
if (!priv->monitormode)
return strlen(buf);
priv->monitormode = 0;
lbs_remove_rtap(priv);
if (priv->currenttxskb) {
dev_kfree_skb_any(priv->currenttxskb);
priv->currenttxskb = NULL;
}
/* Wake queues, command thread, etc. */
lbs_host_to_card_done(priv);
}
lbs_prepare_and_send_command(priv,
CMD_802_11_MONITOR_MODE, CMD_ACT_SET,
CMD_OPTION_WAITFORRSP, 0, &priv->monitormode);
return strlen(buf);
}
/**
* lbs_rtap attribute to be exported per ethX interface
* through sysfs (/sys/class/net/ethX/lbs_rtap)
*/
static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
/**
* @brief This function opens the ethX interface
*
@ -177,13 +105,6 @@ static int lbs_dev_open(struct net_device *dev)
spin_lock_irq(&priv->driver_lock);
if (priv->monitormode) {
ret = -EBUSY;
goto out;
}
priv->infra_open = 1;
if (priv->connect_status == LBS_CONNECTED)
netif_carrier_on(dev);
else
@ -191,7 +112,6 @@ static int lbs_dev_open(struct net_device *dev)
if (!priv->tx_pending_len)
netif_wake_queue(dev);
out:
spin_unlock_irq(&priv->driver_lock);
lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
@ -211,7 +131,6 @@ static int lbs_eth_stop(struct net_device *dev)
lbs_deb_enter(LBS_DEB_NET);
spin_lock_irq(&priv->driver_lock);
priv->infra_open = 0;
netif_stop_queue(dev);
spin_unlock_irq(&priv->driver_lock);
@ -733,6 +652,9 @@ static int lbs_setup_firmware(struct lbs_private *priv)
priv->txpower_max = maxlevel;
}
/* Send cmd to FW to enable 11D function */
ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1);
lbs_set_mac_control(priv);
done:
lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
@ -822,37 +744,16 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
static int lbs_init_adapter(struct lbs_private *priv)
{
size_t bufsize;
int i, ret = 0;
int ret;
lbs_deb_enter(LBS_DEB_MAIN);
/* Allocate buffer to store the BSSID list */
bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
priv->networks = kzalloc(bufsize, GFP_KERNEL);
if (!priv->networks) {
lbs_pr_err("Out of memory allocating beacons\n");
ret = -1;
goto out;
}
/* Initialize scan result lists */
INIT_LIST_HEAD(&priv->network_free_list);
INIT_LIST_HEAD(&priv->network_list);
for (i = 0; i < MAX_NETWORK_COUNT; i++) {
list_add_tail(&priv->networks[i].list,
&priv->network_free_list);
}
memset(priv->current_addr, 0xff, ETH_ALEN);
priv->connect_status = LBS_DISCONNECTED;
priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
priv->mode = IW_MODE_INFRA;
priv->channel = DEFAULT_AD_HOC_CHANNEL;
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
priv->radio_on = 1;
priv->enablehwauto = 1;
priv->psmode = LBS802_11POWERMODECAM;
priv->psstate = PS_STATE_FULL_POWER;
priv->is_deep_sleep = 0;
@ -907,8 +808,6 @@ static void lbs_free_adapter(struct lbs_private *priv)
kfifo_free(&priv->event_fifo);
del_timer(&priv->command_timer);
del_timer(&priv->auto_deepsleep_timer);
kfree(priv->networks);
priv->networks = NULL;
lbs_deb_leave(LBS_DEB_MAIN);
}
@ -945,7 +844,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
lbs_pr_err("cfg80211 init failed\n");
goto done;
}
/* TODO? */
wdev->iftype = NL80211_IFTYPE_STATION;
priv = wdev_priv(wdev);
priv->wdev = wdev;
@ -955,7 +854,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
goto err_wdev;
}
//TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
dev = alloc_netdev(0, "wlan%d", ether_setup);
if (!dev) {
dev_err(dmdev, "no memory for network device instance\n");
@ -971,20 +869,10 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
dev->netdev_ops = &lbs_netdev_ops;
dev->watchdog_timeo = 5 * HZ;
dev->ethtool_ops = &lbs_ethtool_ops;
#ifdef WIRELESS_EXT
dev->wireless_handlers = &lbs_handler_def;
#endif
dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
// TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ??
priv->card = card;
priv->infra_open = 0;
priv->rtap_net_dev = NULL;
strcpy(dev->name, "wlan%d");
lbs_deb_thread("Starting main thread...\n");
@ -996,8 +884,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
}
priv->work_thread = create_singlethread_workqueue("lbs_worker");
INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
priv->wol_criteria = 0xffffffff;
@ -1031,12 +917,10 @@ void lbs_remove_card(struct lbs_private *priv)
lbs_deb_enter(LBS_DEB_MAIN);
lbs_remove_mesh(priv);
lbs_remove_rtap(priv);
lbs_scan_deinit(priv);
dev = priv->dev;
cancel_delayed_work_sync(&priv->scan_work);
cancel_delayed_work_sync(&priv->assoc_work);
cancel_work_sync(&priv->mcast_work);
/* worker thread destruction blocks on the in-flight command which
@ -1051,8 +935,6 @@ void lbs_remove_card(struct lbs_private *priv)
lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
}
lbs_send_disconnect_notification(priv);
if (priv->is_deep_sleep) {
priv->is_deep_sleep = 0;
wake_up_interruptible(&priv->ds_awake_q);
@ -1077,7 +959,7 @@ void lbs_remove_card(struct lbs_private *priv)
EXPORT_SYMBOL_GPL(lbs_remove_card);
static int lbs_rtap_supported(struct lbs_private *priv)
int lbs_rtap_supported(struct lbs_private *priv)
{
if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
return 1;
@ -1109,16 +991,6 @@ int lbs_start_card(struct lbs_private *priv)
lbs_init_mesh(priv);
/*
* While rtap isn't related to mesh, only mesh-enabled
* firmware implements the rtap functionality via
* CMD_802_11_MONITOR_MODE.
*/
if (lbs_rtap_supported(priv)) {
if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
lbs_pr_err("cannot register lbs_rtap attribute\n");
}
lbs_debugfs_init_one(priv, dev);
lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
@ -1150,9 +1022,6 @@ void lbs_stop_card(struct lbs_private *priv)
lbs_debugfs_remove_one(priv);
lbs_deinit_mesh(priv);
if (lbs_rtap_supported(priv))
device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
/* Delete the timeout of the currently processing command */
del_timer_sync(&priv->command_timer);
del_timer_sync(&priv->auto_deepsleep_timer);
@ -1239,87 +1108,6 @@ static void __exit lbs_exit_module(void)
lbs_deb_leave(LBS_DEB_MAIN);
}
/*
* rtap interface support fuctions
*/
static int lbs_rtap_open(struct net_device *dev)
{
/* Yes, _stop_ the queue. Because we don't support injection */
lbs_deb_enter(LBS_DEB_MAIN);
netif_carrier_off(dev);
netif_stop_queue(dev);
lbs_deb_leave(LBS_DEB_LEAVE);
return 0;
}
static int lbs_rtap_stop(struct net_device *dev)
{
lbs_deb_enter(LBS_DEB_MAIN);
lbs_deb_leave(LBS_DEB_MAIN);
return 0;
}
static netdev_tx_t lbs_rtap_hard_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
netif_stop_queue(dev);
return NETDEV_TX_BUSY;
}
static void lbs_remove_rtap(struct lbs_private *priv)
{
lbs_deb_enter(LBS_DEB_MAIN);
if (priv->rtap_net_dev == NULL)
goto out;
unregister_netdev(priv->rtap_net_dev);
free_netdev(priv->rtap_net_dev);
priv->rtap_net_dev = NULL;
out:
lbs_deb_leave(LBS_DEB_MAIN);
}
static const struct net_device_ops rtap_netdev_ops = {
.ndo_open = lbs_rtap_open,
.ndo_stop = lbs_rtap_stop,
.ndo_start_xmit = lbs_rtap_hard_start_xmit,
};
static int lbs_add_rtap(struct lbs_private *priv)
{
int ret = 0;
struct net_device *rtap_dev;
lbs_deb_enter(LBS_DEB_MAIN);
if (priv->rtap_net_dev) {
ret = -EPERM;
goto out;
}
rtap_dev = alloc_netdev(0, "rtap%d", ether_setup);
if (rtap_dev == NULL) {
ret = -ENOMEM;
goto out;
}
memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN);
rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP;
rtap_dev->netdev_ops = &rtap_netdev_ops;
rtap_dev->ml_priv = priv;
SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent);
ret = register_netdev(rtap_dev);
if (ret) {
free_netdev(rtap_dev);
goto out;
}
priv->rtap_net_dev = rtap_dev;
out:
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
return ret;
}
module_init(lbs_init_module);
module_exit(lbs_exit_module);

View File

@ -5,6 +5,7 @@
#include <linux/if_arp.h>
#include <linux/kthread.h>
#include <linux/kfifo.h>
#include <net/cfg80211.h>
#include "mesh.h"
#include "decl.h"
@ -314,7 +315,7 @@ static int lbs_mesh_dev_open(struct net_device *dev)
spin_lock_irq(&priv->driver_lock);
if (priv->monitormode) {
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
ret = -EBUSY;
goto out;
}
@ -369,9 +370,6 @@ int lbs_add_mesh(struct lbs_private *priv)
SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
#ifdef WIRELESS_EXT
mesh_dev->wireless_handlers = &mesh_handler_def;
#endif
mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
/* Register virtual mesh interface */
ret = register_netdev(mesh_dev);

View File

@ -70,11 +70,6 @@ void lbs_persist_config_init(struct net_device *net);
void lbs_persist_config_remove(struct net_device *net);
/* WEXT handler */
extern struct iw_handler_def mesh_handler_def;
/* Ethtool statistics */
struct ethtool_stats;

View File

@ -4,12 +4,13 @@
#include <linux/etherdevice.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <net/cfg80211.h>
#include "defs.h"
#include "host.h"
#include "radiotap.h"
#include "decl.h"
#include "dev.h"
#include "wext.h"
struct eth803hdr {
u8 dest_addr[6];
@ -38,98 +39,6 @@ struct rx80211packethdr {
static int process_rxed_802_11_packet(struct lbs_private *priv,
struct sk_buff *skb);
/**
* @brief This function computes the avgSNR .
*
* @param priv A pointer to struct lbs_private structure
* @return avgSNR
*/
static u8 lbs_getavgsnr(struct lbs_private *priv)
{
u8 i;
u16 temp = 0;
if (priv->numSNRNF == 0)
return 0;
for (i = 0; i < priv->numSNRNF; i++)
temp += priv->rawSNR[i];
return (u8) (temp / priv->numSNRNF);
}
/**
* @brief This function computes the AvgNF
*
* @param priv A pointer to struct lbs_private structure
* @return AvgNF
*/
static u8 lbs_getavgnf(struct lbs_private *priv)
{
u8 i;
u16 temp = 0;
if (priv->numSNRNF == 0)
return 0;
for (i = 0; i < priv->numSNRNF; i++)
temp += priv->rawNF[i];
return (u8) (temp / priv->numSNRNF);
}
/**
* @brief This function save the raw SNR/NF to our internel buffer
*
* @param priv A pointer to struct lbs_private structure
* @param prxpd A pointer to rxpd structure of received packet
* @return n/a
*/
static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
{
if (priv->numSNRNF < DEFAULT_DATA_AVG_FACTOR)
priv->numSNRNF++;
priv->rawSNR[priv->nextSNRNF] = p_rx_pd->snr;
priv->rawNF[priv->nextSNRNF] = p_rx_pd->nf;
priv->nextSNRNF++;
if (priv->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR)
priv->nextSNRNF = 0;
}
/**
* @brief This function computes the RSSI in received packet.
*
* @param priv A pointer to struct lbs_private structure
* @param prxpd A pointer to rxpd structure of received packet
* @return n/a
*/
static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
{
lbs_deb_enter(LBS_DEB_RX);
lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf);
lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n",
priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
priv->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr;
priv->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf;
lbs_save_rawSNRNF(priv, p_rx_pd);
priv->SNR[TYPE_RXPD][TYPE_AVG] = lbs_getavgsnr(priv) * AVG_SCALE;
priv->NF[TYPE_RXPD][TYPE_AVG] = lbs_getavgnf(priv) * AVG_SCALE;
lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n",
priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
priv->RSSI[TYPE_RXPD][TYPE_NOAVG] =
CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_NOAVG],
priv->NF[TYPE_RXPD][TYPE_NOAVG]);
priv->RSSI[TYPE_RXPD][TYPE_AVG] =
CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
lbs_deb_leave(LBS_DEB_RX);
}
/**
* @brief This function processes received packet and forwards it
* to kernel/upper layer
@ -154,7 +63,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE;
if (priv->monitormode)
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
return process_rxed_802_11_packet(priv, skb);
p_rx_pd = (struct rxpd *) skb->data;
@ -225,13 +134,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
*/
skb_pull(skb, hdrchop);
/* Take the data rate from the rxpd structure
* only if the rate is auto
*/
if (priv->enablehwauto)
priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
lbs_compute_rssi(priv, p_rx_pd);
priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
dev->stats.rx_bytes += skb->len;
@ -352,20 +255,18 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr));
memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));
/* Take the data rate from the rxpd structure
* only if the rate is auto
*/
if (priv->enablehwauto)
priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
lbs_compute_rssi(priv, prxpd);
priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
dev->stats.rx_bytes += skb->len;
dev->stats.rx_packets++;
skb->protocol = eth_type_trans(skb, priv->rtap_net_dev);
netif_rx(skb);
skb->protocol = eth_type_trans(skb, priv->dev);
if (in_interrupt())
netif_rx(skb);
else
netif_rx_ni(skb);
ret = 0;

File diff suppressed because it is too large Load Diff

View File

@ -1,63 +0,0 @@
/**
* Interface for the wlan network scan routines
*
* Driver interface functions and type declarations for the scan module
* implemented in scan.c.
*/
#ifndef _LBS_SCAN_H
#define _LBS_SCAN_H
#include <net/iw_handler.h>
struct lbs_private;
#define MAX_NETWORK_COUNT 128
/** Chan-freq-TxPower mapping table*/
struct chan_freq_power {
/** channel Number */
u16 channel;
/** frequency of this channel */
u32 freq;
/** Max allowed Tx power level */
u16 maxtxpower;
/** TRUE:channel unsupported; FLASE:supported*/
u8 unsupported;
};
/** region-band mapping table*/
struct region_channel {
/** TRUE if this entry is valid */
u8 valid;
/** region code for US, Japan ... */
u8 region;
/** band B/G/A, used for BAND_CONFIG cmd */
u8 band;
/** Actual No. of elements in the array below */
u8 nrcfp;
/** chan-freq-txpower mapping table*/
struct chan_freq_power *CFP;
};
/**
* @brief Maximum number of channels that can be sent in a setuserscan ioctl
*/
#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
u8 ssid_len);
int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra);
int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
union iwreq_data *wrqu, char *extra);
int lbs_scan_networks(struct lbs_private *priv, int full_scan);
void lbs_scan_worker(struct work_struct *work);
#endif

View File

@ -4,13 +4,13 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/sched.h>
#include <net/cfg80211.h>
#include "host.h"
#include "radiotap.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "wext.h"
/**
* @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
@ -111,7 +111,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
p802x_hdr = skb->data;
pkt_len = skb->len;
if (dev == priv->rtap_net_dev) {
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data;
/* set txpd fields from the radiotap header */
@ -147,7 +147,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
if (priv->monitormode) {
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
/* Keep the skb to echo it back once Tx feedback is
received from FW */
skb_orphan(skb);
@ -158,6 +158,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
free:
dev_kfree_skb_any(skb);
}
unlock:
spin_unlock_irqrestore(&priv->driver_lock, flags);
wake_up(&priv->waitq);
@ -179,7 +180,8 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
{
struct tx_radiotap_hdr *radiotap_hdr;
if (!priv->monitormode || priv->currenttxskb == NULL)
if (!priv->wdev->iftype == NL80211_IFTYPE_MONITOR ||
priv->currenttxskb == NULL)
return;
radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
@ -188,7 +190,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
(1 + priv->txretrycount - try_count) : 0;
priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
priv->rtap_net_dev);
priv->dev);
netif_rx(priv->currenttxskb);
priv->currenttxskb = NULL;

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +0,0 @@
/**
* This file contains definition for IOCTL call.
*/
#ifndef _LBS_WEXT_H_
#define _LBS_WEXT_H_
void lbs_send_disconnect_notification(struct lbs_private *priv);
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
struct lbs_private *priv,
u8 band,
u16 channel);
extern struct iw_handler_def lbs_handler_def;
#endif

View File

@ -1291,6 +1291,11 @@ static int __init init_mac80211_hwsim(void)
hw->wiphy->n_addresses = 2;
hw->wiphy->addresses = data->addresses;
if (fake_hw_scan) {
hw->wiphy->max_scan_ssids = 255;
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
}
hw->channel_change_time = 1;
hw->queues = 4;
hw->wiphy->interface_modes =

View File

@ -520,8 +520,9 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed);
static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
int dbm);
static int rndis_set_tx_power(struct wiphy *wiphy,
enum nl80211_tx_power_setting type,
int mbm);
static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm);
static int rndis_connect(struct wiphy *wiphy, struct net_device *dev,
@ -1856,20 +1857,25 @@ static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed)
return 0;
}
static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
int dbm)
static int rndis_set_tx_power(struct wiphy *wiphy,
enum nl80211_tx_power_setting type,
int mbm)
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
struct usbnet *usbdev = priv->usbdev;
netdev_dbg(usbdev->net, "%s(): type:0x%x dbm:%i\n",
__func__, type, dbm);
netdev_dbg(usbdev->net, "%s(): type:0x%x mbm:%i\n",
__func__, type, mbm);
if (mbm < 0 || (mbm % 100))
return -ENOTSUPP;
/* Device doesn't support changing txpower after initialization, only
* turn off/on radio. Support 'auto' mode and setting same dBm that is
* currently used.
*/
if (type == TX_POWER_AUTOMATIC || dbm == get_bcm4320_power_dbm(priv)) {
if (type == NL80211_TX_POWER_AUTOMATIC ||
MBM_TO_DBM(mbm) == get_bcm4320_power_dbm(priv)) {
if (!priv->radio_on)
disassociate(usbdev, true); /* turn on radio */

View File

@ -1229,7 +1229,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
}
txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
rt2x00pci_txdone(entry, &txdesc);
rt2x00lib_txdone(entry, &txdesc);
}
}
@ -1588,7 +1588,6 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.reset_tuner = rt2400pci_reset_tuner,
.link_tuner = rt2400pci_link_tuner,
.write_tx_desc = rt2400pci_write_tx_desc,
.write_tx_data = rt2x00pci_write_tx_data,
.write_beacon = rt2400pci_write_beacon,
.kick_tx_queue = rt2400pci_kick_tx_queue,
.kill_tx_queue = rt2400pci_kill_tx_queue,

View File

@ -1365,7 +1365,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
}
txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
rt2x00pci_txdone(entry, &txdesc);
rt2x00lib_txdone(entry, &txdesc);
}
}
@ -1886,7 +1886,6 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.reset_tuner = rt2500pci_reset_tuner,
.link_tuner = rt2500pci_link_tuner,
.write_tx_desc = rt2500pci_write_tx_desc,
.write_tx_data = rt2x00pci_write_tx_data,
.write_beacon = rt2500pci_write_beacon,
.kick_tx_queue = rt2500pci_kick_tx_queue,
.kill_tx_queue = rt2500pci_kill_tx_queue,

View File

@ -347,6 +347,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
{
u32 mask;
u16 reg;
enum cipher curr_cipher;
if (crypto->cmd == SET_KEY) {
/*
@ -357,6 +358,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
mask = TXRX_CSR0_KEY_ID.bit_mask;
rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM);
reg &= mask;
if (reg && reg == mask)
@ -365,6 +367,14 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
key->hw_key_idx += reg ? ffz(reg) : 0;
/*
* Hardware requires that all keys use the same cipher
* (e.g. TKIP-only, AES-only, but not TKIP+AES).
* If this is not the first key, compare the cipher with the
* first one and fall back to SW crypto if not the same.
*/
if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher)
return -EOPNOTSUPP;
rt2500usb_register_multiwrite(rt2x00dev, reg,
crypto->key, sizeof(crypto->key));
@ -1769,7 +1779,6 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
.link_stats = rt2500usb_link_stats,
.reset_tuner = rt2500usb_reset_tuner,
.write_tx_desc = rt2500usb_write_tx_desc,
.write_tx_data = rt2x00usb_write_tx_data,
.write_beacon = rt2500usb_write_beacon,
.get_tx_data_len = rt2500usb_get_tx_data_len,
.kick_tx_queue = rt2x00usb_kick_tx_queue,

View File

@ -99,8 +99,7 @@ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 0);
if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
}
@ -128,8 +127,7 @@ static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 1);
if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
@ -432,6 +430,20 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
}
EXPORT_SYMBOL(rt2800_write_beacon);
static void inline rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
unsigned int beacon_base)
{
int i;
/*
* For the Beacon base registers we only need to clear
* the whole TXWI which (when set to 0) will invalidate
* the entire beacon.
*/
for (i = 0; i < TXWI_DESC_SIZE; i += sizeof(__le32))
rt2800_register_write(rt2x00dev, beacon_base + i, 0);
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
const struct rt2x00debug rt2800_rt2x00debug = {
.owner = THIS_MODULE,
@ -733,19 +745,14 @@ EXPORT_SYMBOL_GPL(rt2800_config_filter);
void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
struct rt2x00intf_conf *conf, const unsigned int flags)
{
unsigned int beacon_base;
u32 reg;
if (flags & CONFIG_UPDATE_TYPE) {
/*
* Clear current synchronisation setup.
* For the Beacon base registers we only need to clear
* the first byte since that byte contains the VALID and OWNER
* bits which (when set to 0) will invalidate the entire beacon.
*/
beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
rt2800_register_write(rt2x00dev, beacon_base, 0);
rt2800_clear_beacon(rt2x00dev,
HW_BEACON_OFFSET(intf->beacon->entry_idx));
/*
* Enable synchronisation.
*/
@ -768,8 +775,8 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
if (flags & CONFIG_UPDATE_BSSID) {
reg = le32_to_cpu(conf->bssid[1]);
rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 0);
rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
conf->bssid[1] = cpu_to_le32(reg);
rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,
@ -827,14 +834,12 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
switch ((int)ant->tx) {
case 1:
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
break;
case 2:
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
break;
case 3:
/* Do nothing */
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
break;
}
@ -1565,18 +1570,15 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* Clear all beacons
* For the Beacon base registers we only need to clear
* the first byte since that byte contains the VALID and OWNER
* bits which (when set to 0) will invalidate the entire beacon.
*/
rt2800_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
rt2800_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
rt2800_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
rt2800_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
rt2800_register_write(rt2x00dev, HW_BEACON_BASE4, 0);
rt2800_register_write(rt2x00dev, HW_BEACON_BASE5, 0);
rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0);
rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0);
rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE0);
rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE1);
rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE2);
rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE3);
rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE4);
rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE5);
rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE6);
rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE7);
if (rt2x00_is_usb(rt2x00dev)) {
rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
@ -2185,6 +2187,8 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0);
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0);
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0);
rt2x00_set_field16(&word, EEPROM_NIC_ANT_DIVERSITY, 0);
rt2x00_set_field16(&word, EEPROM_NIC_DAC_TEST, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
}
@ -2192,6 +2196,10 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
if ((word & 0x00ff) == 0x00ff) {
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
}
if ((word & 0xff00) == 0xff00) {
rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
LED_MODE_TXRX_ACTIVITY);
rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
@ -2199,7 +2207,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8);
EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
EEPROM(rt2x00dev, "Led Mode: 0x%04x\n", word);
}
/*
@ -2499,7 +2507,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK;
IEEE80211_HW_PS_NULLFUNC_STACK |
IEEE80211_HW_AMPDU_AGGREGATION;
SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@ -2559,12 +2568,15 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_GRN_FLD |
IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_RX_STBC;
IEEE80211_HT_CAP_SGI_40;
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) >= 2)
spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC;
spec->ht.cap |=
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) <<
IEEE80211_HT_CAP_RX_STBC_SHIFT;
spec->ht.ampdu_factor = 3;
spec->ht.ampdu_density = 4;
spec->ht.mcs.tx_params =
@ -2751,6 +2763,35 @@ static u64 rt2800_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
static int rt2800_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta,
u16 tid, u16 *ssn)
{
int ret = 0;
switch (action) {
case IEEE80211_AMPDU_RX_START:
case IEEE80211_AMPDU_RX_STOP:
/* we don't support RX aggregation yet */
ret = -ENOTSUPP;
break;
case IEEE80211_AMPDU_TX_START:
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP:
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
break;
default:
WARNING((struct rt2x00_dev *)hw->priv, "Unknown AMPDU action\n");
}
return ret;
}
const struct ieee80211_ops rt2800_mac80211_ops = {
.tx = rt2x00mac_tx,
.start = rt2x00mac_start,
@ -2768,6 +2809,7 @@ const struct ieee80211_ops rt2800_mac80211_ops = {
.conf_tx = rt2800_conf_tx,
.get_tsf = rt2800_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
.ampdu_action = rt2800_ampdu_action,
};
EXPORT_SYMBOL_GPL(rt2800_mac80211_ops);

View File

@ -139,8 +139,18 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
eeprom.data = rt2x00dev;
eeprom.register_read = rt2800pci_eepromregister_read;
eeprom.register_write = rt2800pci_eepromregister_write;
eeprom.width = !rt2x00_get_field32(reg, E2PROM_CSR_TYPE) ?
PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66;
switch (rt2x00_get_field32(reg, E2PROM_CSR_TYPE))
{
case 0:
eeprom.width = PCI_EEPROM_WIDTH_93C46;
break;
case 1:
eeprom.width = PCI_EEPROM_WIDTH_93C66;
break;
default:
eeprom.width = PCI_EEPROM_WIDTH_93C86;
break;
}
eeprom.reg_data_in = 0;
eeprom.reg_data_out = 0;
eeprom.reg_data_clock = 0;
@ -645,10 +655,12 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* TX descriptor initialization
*/
static void rt2800pci_write_tx_datadesc(struct queue_entry* entry,
struct txentry_desc *txdesc)
static void rt2800pci_write_tx_data(struct queue_entry* entry,
struct txentry_desc *txdesc)
{
rt2800_write_txwi((__le32 *) entry->skb->data, txdesc);
__le32 *txwi = (__le32 *) entry->skb->data;
rt2800_write_txwi(txwi, txdesc);
}
@ -905,7 +917,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
if (txdesc.retry)
__set_bit(TXDONE_FALLBACK, &txdesc.flags);
rt2x00pci_txdone(entry, &txdesc);
rt2x00lib_txdone(entry, &txdesc);
}
}
@ -941,6 +953,12 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
rt2800pci_txdone(rt2x00dev);
/*
* Current beacon was sent out, fetch the next one
*/
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
rt2x00lib_beacondone(rt2x00dev);
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
rt2800pci_wakeup(rt2x00dev);
@ -1044,8 +1062,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.reset_tuner = rt2800_reset_tuner,
.link_tuner = rt2800_link_tuner,
.write_tx_desc = rt2800pci_write_tx_desc,
.write_tx_data = rt2x00pci_write_tx_data,
.write_tx_datadesc = rt2800pci_write_tx_datadesc,
.write_tx_data = rt2800pci_write_tx_data,
.write_beacon = rt2800_write_beacon,
.kick_tx_queue = rt2800pci_kick_tx_queue,
.kill_tx_queue = rt2800pci_kill_tx_queue,

View File

@ -430,20 +430,23 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* TX descriptor initialization
*/
static void rt2800usb_write_tx_data(struct queue_entry* entry,
struct txentry_desc *txdesc)
{
__le32 *txwi = (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE);
rt2800_write_txwi(txwi, txdesc);
}
static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb,
struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
__le32 *txi = (__le32 *) skb->data;
__le32 *txwi = (__le32 *) (skb->data + TXINFO_DESC_SIZE);
u32 word;
/*
* Initialize TXWI descriptor
*/
rt2800_write_txwi(txwi, txdesc);
/*
* Initialize TXINFO descriptor
*/
@ -652,7 +655,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.reset_tuner = rt2800_reset_tuner,
.link_tuner = rt2800_link_tuner,
.write_tx_desc = rt2800usb_write_tx_desc,
.write_tx_data = rt2x00usb_write_tx_data,
.write_tx_data = rt2800usb_write_tx_data,
.write_beacon = rt2800_write_beacon,
.get_tx_data_len = rt2800usb_get_tx_data_len,
.kick_tx_queue = rt2x00usb_kick_tx_queue,

View File

@ -550,10 +550,8 @@ struct rt2x00lib_ops {
void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb,
struct txentry_desc *txdesc);
int (*write_tx_data) (struct queue_entry *entry,
struct txentry_desc *txdesc);
void (*write_tx_datadesc) (struct queue_entry *entry,
struct txentry_desc *txdesc);
void (*write_tx_data) (struct queue_entry *entry,
struct txentry_desc *txdesc);
void (*write_beacon) (struct queue_entry *entry,
struct txentry_desc *txdesc);
int (*get_tx_data_len) (struct queue_entry *entry);

View File

@ -210,6 +210,21 @@ void rt2x00lib_txdone(struct queue_entry *entry,
unsigned int i;
bool success;
/*
* Unmap the skb.
*/
rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
/*
* Remove the extra tx headroom from the skb.
*/
skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom);
/*
* Signal that the TX descriptor is no longer in the skb.
*/
skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
/*
* Remove L2 padding which was added during
*/
@ -286,6 +301,21 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rt2x00dev->low_level_stats.dot11ACKFailureCount++;
}
/*
* Every single frame has it's own tx status, hence report
* every frame as ampdu of size 1.
*
* TODO: if we can find out how many frames were aggregated
* by the hw we could provide the real ampdu_len to mac80211
* which would allow the rc algorithm to better decide on
* which rates are suitable.
*/
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
tx_info->status.ampdu_len = 1;
tx_info->status.ampdu_ack_len = success ? 1 : 0;
}
if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
if (success)
rt2x00dev->low_level_stats.dot11RTSSuccessCount++;

View File

@ -271,11 +271,11 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
/*
* Link tuning should only be performed when
* an active sta or master interface exists.
* Single monitor mode interfaces should never have
* work with link tuners.
* an active sta interface exists. AP interfaces
* don't need link tuning and monitor mode interfaces
* should never have to work with link tuners.
*/
if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)
if (!rt2x00dev->intf_sta_count)
return;
rt2x00link_reset_tuner(rt2x00dev, false);

View File

@ -282,7 +282,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
* has been initialized. Otherwise the device can reset
* the MAC registers.
*/
rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL);
rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
intf->mac, intf->bssid);
/*
* Some filters depend on the current working mode. We can force
@ -562,7 +563,6 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct rt2x00_intf *intf = vif_to_intf(vif);
int update_bssid = 0;
/*
* mac80211 might be calling this function while we are trying
@ -577,10 +577,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
* conf->bssid can be NULL if coming from the internal
* beacon update routine.
*/
if (changes & BSS_CHANGED_BSSID) {
update_bssid = 1;
if (changes & BSS_CHANGED_BSSID)
memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN);
}
spin_unlock(&intf->lock);
@ -592,7 +590,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
*/
if (changes & BSS_CHANGED_BSSID)
rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
update_bssid ? bss_conf->bssid : NULL);
bss_conf->bssid);
/*
* Update the beacon.

View File

@ -60,80 +60,6 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
}
EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
/*
* TX data handlers.
*/
int rt2x00pci_write_tx_data(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
/*
* This should not happen, we already checked the entry
* was ours. When the hardware disagrees there has been
* a queue corruption!
*/
if (unlikely(rt2x00dev->ops->lib->get_entry_state(entry))) {
ERROR(rt2x00dev,
"Corrupt queue %d, accessing entry which is not ours.\n"
"Please file bug report to %s.\n",
entry->queue->qid, DRV_PROJECT);
return -EINVAL;
}
/*
* Add the requested extra tx headroom in front of the skb.
*/
skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom);
memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom);
/*
* Call the driver's write_tx_datadesc function, if it exists.
*/
if (rt2x00dev->ops->lib->write_tx_datadesc)
rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc);
/*
* Map the skb to DMA.
*/
if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
rt2x00queue_map_txskb(rt2x00dev, entry->skb);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
/*
* TX/RX data handlers.
*/
void rt2x00pci_txdone(struct queue_entry *entry,
struct txdone_entry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
/*
* Unmap the skb.
*/
rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
/*
* Remove the extra tx headroom from the skb.
*/
skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom);
/*
* Signal that the TX descriptor is no longer in the skb.
*/
skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
/*
* Pass on to rt2x00lib.
*/
rt2x00lib_txdone(entry, txdesc);
}
EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue = rt2x00dev->rx;

View File

@ -85,16 +85,6 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
const struct rt2x00_field32 field,
u32 *reg);
/**
* rt2x00pci_write_tx_data - Initialize data for TX operation
* @entry: The entry where the frame is located
*
* This function will initialize the DMA and skb descriptor
* to prepare the entry for the actual TX operation.
*/
int rt2x00pci_write_tx_data(struct queue_entry *entry,
struct txentry_desc *txdesc);
/**
* struct queue_entry_priv_pci: Per entry PCI specific information
*
@ -108,14 +98,6 @@ struct queue_entry_priv_pci {
dma_addr_t desc_dma;
};
/**
* rt2x00pci_txdone - Handle TX done events.
* @entry: The queue entry for which a TX done event was received.
* @txdesc: The TX done descriptor for the entry.
*/
void rt2x00pci_txdone(struct queue_entry *entry,
struct txdone_entry_desc *txdesc);
/**
* rt2x00pci_rxdone - Handle RX done events
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.

View File

@ -404,6 +404,46 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
}
static int rt2x00queue_write_tx_data(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
/*
* This should not happen, we already checked the entry
* was ours. When the hardware disagrees there has been
* a queue corruption!
*/
if (unlikely(rt2x00dev->ops->lib->get_entry_state &&
rt2x00dev->ops->lib->get_entry_state(entry))) {
ERROR(rt2x00dev,
"Corrupt queue %d, accessing entry which is not ours.\n"
"Please file bug report to %s.\n",
entry->queue->qid, DRV_PROJECT);
return -EINVAL;
}
/*
* Add the requested extra tx headroom in front of the skb.
*/
skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom);
memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom);
/*
* Call the driver's write_tx_data function, if it exists.
*/
if (rt2x00dev->ops->lib->write_tx_data)
rt2x00dev->ops->lib->write_tx_data(entry, txdesc);
/*
* Map the skb to DMA.
*/
if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
rt2x00queue_map_txskb(rt2x00dev, entry->skb);
return 0;
}
static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
@ -515,8 +555,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
* call failed. Since we always return NETDEV_TX_OK to mac80211,
* this frame will simply be dropped.
*/
if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry,
&txdesc))) {
if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
entry->skb = NULL;
return -EIO;

View File

@ -177,11 +177,6 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;
/*
* Remove the descriptor from the front of the skb.
*/
skb_pull(entry->skb, entry->queue->desc_size);
/*
* Obtain the status about this packet.
* Note that when the status is 0 it does not mean the
@ -201,48 +196,28 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
rt2x00lib_txdone(entry, &txdesc);
}
int rt2x00usb_write_tx_data(struct queue_entry *entry,
struct txentry_desc *txdesc)
static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
u32 length;
/*
* Add the descriptor in front of the skb.
*/
skb_push(entry->skb, entry->queue->desc_size);
memset(entry->skb->data, 0, entry->queue->desc_size);
if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) {
/*
* USB devices cannot blindly pass the skb->len as the
* length of the data to usb_fill_bulk_urb. Pass the skb
* to the driver to determine what the length should be.
*/
length = rt2x00dev->ops->lib->get_tx_data_len(entry);
/*
* USB devices cannot blindly pass the skb->len as the
* length of the data to usb_fill_bulk_urb. Pass the skb
* to the driver to determine what the length should be.
*/
length = rt2x00dev->ops->lib->get_tx_data_len(entry);
usb_fill_bulk_urb(entry_priv->urb, usb_dev,
usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
entry->skb->data, length,
rt2x00usb_interrupt_txdone, entry);
usb_fill_bulk_urb(entry_priv->urb, usb_dev,
usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
entry->skb->data, length,
rt2x00usb_interrupt_txdone, entry);
/*
* Call the driver's write_tx_datadesc function, if it exists.
*/
if (rt2x00dev->ops->lib->write_tx_datadesc)
rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
{
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
}
}
void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,

View File

@ -350,16 +350,6 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
*/
void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
/**
* rt2x00usb_write_tx_data - Initialize URB for TX operation
* @entry: The entry where the frame is located
*
* This function will initialize the URB and skb descriptor
* to prepare the entry for the actual TX operation.
*/
int rt2x00usb_write_tx_data(struct queue_entry *entry,
struct txentry_desc *txdesc);
/**
* struct queue_entry_priv_usb: Per entry USB specific information
*

View File

@ -2108,7 +2108,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
__set_bit(TXDONE_UNKNOWN, &txdesc.flags);
txdesc.retry = 0;
rt2x00pci_txdone(entry_done, &txdesc);
rt2x00lib_txdone(entry_done, &txdesc);
entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
}
@ -2135,7 +2135,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
if (txdesc.retry)
__set_bit(TXDONE_FALLBACK, &txdesc.flags);
rt2x00pci_txdone(entry, &txdesc);
rt2x00lib_txdone(entry, &txdesc);
}
}
@ -2200,6 +2200,12 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
rt61pci_wakeup(rt2x00dev);
/*
* 5 - Beacon done interrupt.
*/
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
rt2x00lib_beacondone(rt2x00dev);
return IRQ_HANDLED;
}
@ -2800,7 +2806,6 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.reset_tuner = rt61pci_reset_tuner,
.link_tuner = rt61pci_link_tuner,
.write_tx_desc = rt61pci_write_tx_desc,
.write_tx_data = rt2x00pci_write_tx_data,
.write_beacon = rt61pci_write_beacon,
.kick_tx_queue = rt61pci_kick_tx_queue,
.kill_tx_queue = rt61pci_kill_tx_queue,

View File

@ -2249,7 +2249,6 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.reset_tuner = rt73usb_reset_tuner,
.link_tuner = rt73usb_link_tuner,
.write_tx_desc = rt73usb_write_tx_desc,
.write_tx_data = rt2x00usb_write_tx_data,
.write_beacon = rt73usb_write_beacon,
.get_tx_data_len = rt73usb_get_tx_data_len,
.kick_tx_queue = rt2x00usb_kick_tx_queue,

View File

@ -671,7 +671,7 @@ static u64 rtl8180_get_tsf(struct ieee80211_hw *dev)
(u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
}
void rtl8180_beacon_work(struct work_struct *work)
static void rtl8180_beacon_work(struct work_struct *work)
{
struct rtl8180_vif *vif_priv =
container_of(work, struct rtl8180_vif, beacon_work.work);

View File

@ -30,6 +30,7 @@
#define PCI_EEPROM_WIDTH_93C46 6
#define PCI_EEPROM_WIDTH_93C56 8
#define PCI_EEPROM_WIDTH_93C66 8
#define PCI_EEPROM_WIDTH_93C86 8
#define PCI_EEPROM_WIDTH_OPCODE 3
#define PCI_EEPROM_WRITE_OPCODE 0x05
#define PCI_EEPROM_READ_OPCODE 0x06

View File

@ -725,6 +725,12 @@ enum nl80211_commands {
* @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations
* connected to this BSS.
*
* @NL80211_ATTR_WIPHY_TX_POWER_SETTING: Transmit power setting type. See
* &enum nl80211_tx_power_setting for possible values.
* @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units.
* This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING
* for non-automatic settings.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@ -882,6 +888,9 @@ enum nl80211_attrs {
NL80211_ATTR_AP_ISOLATE,
NL80211_ATTR_WIPHY_TX_POWER_SETTING,
NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@ -1659,4 +1668,17 @@ enum nl80211_cqm_rssi_threshold_event {
NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
};
/**
* enum nl80211_tx_power_setting - TX power adjustment
* @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power
* @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter
* @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter
*/
enum nl80211_tx_power_setting {
NL80211_TX_POWER_AUTOMATIC,
NL80211_TX_POWER_LIMITED,
NL80211_TX_POWER_FIXED,
};
#endif /* __LINUX_NL80211_H */

View File

@ -875,19 +875,6 @@ enum wiphy_params_flags {
WIPHY_PARAM_COVERAGE_CLASS = 1 << 4,
};
/**
* enum tx_power_setting - TX power adjustment
*
* @TX_POWER_AUTOMATIC: the dbm parameter is ignored
* @TX_POWER_LIMITED: limit TX power by the dbm parameter
* @TX_POWER_FIXED: fix TX power to the dbm parameter
*/
enum tx_power_setting {
TX_POWER_AUTOMATIC,
TX_POWER_LIMITED,
TX_POWER_FIXED,
};
/*
* cfg80211_bitrate_mask - masks for bitrate control
*/
@ -1149,7 +1136,7 @@ struct cfg80211_ops {
int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
int (*set_tx_power)(struct wiphy *wiphy,
enum tx_power_setting type, int dbm);
enum nl80211_tx_power_setting type, int mbm);
int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,

View File

@ -1271,6 +1271,15 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
* dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS
* enabled whenever user has enabled powersave.
*
* Some hardware need to toggle a single shared antenna between WLAN and
* Bluetooth to facilitate co-existence. These types of hardware set
* limitations on the use of host controlled dynamic powersave whenever there
* is simultaneous WLAN and Bluetooth traffic. For these types of hardware, the
* driver may request temporarily going into full power save, in order to
* enable toggling the antenna between BT and WLAN. If the driver requests
* disabling dynamic powersave, the @dynamic_ps_timeout value will be
* temporarily set to zero until the driver re-enables dynamic powersave.
*
* Driver informs U-APSD client support by enabling
* %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the
* uapsd paramater in conf_tx() operation. Hardware needs to send the QoS
@ -2446,6 +2455,36 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif);
*/
void ieee80211_connection_loss(struct ieee80211_vif *vif);
/**
* ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm
*
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
*
* Some hardware require full power save to manage simultaneous BT traffic
* on the WLAN frequency. Full PSM is required periodically, whenever there are
* burst of BT traffic. The hardware gets information of BT traffic via
* hardware co-existence lines, and consequentially requests mac80211 to
* (temporarily) enter full psm.
* This function will only temporarily disable dynamic PS, not enable PSM if
* it was not already enabled.
* The driver must make sure to re-enable dynamic PS using
* ieee80211_enable_dyn_ps() if the driver has disabled it.
*
*/
void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif);
/**
* ieee80211_enable_dyn_ps - restore dynamic psm after being disabled
*
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
*
* This function restores dynamic PS after being temporarily disabled via
* ieee80211_disable_dyn_ps(). Each ieee80211_disable_dyn_ps() call must
* be coupled with an eventual call to this function.
*
*/
void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif);
/**
* ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring
* rssi threshold triggered

View File

@ -69,6 +69,7 @@ endchoice
config MAC80211_RC_DEFAULT
string
default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT
default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
default "pid" if MAC80211_RC_DEFAULT_PID
default ""

View File

@ -413,9 +413,6 @@ static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
if (!local->ops->get_survey)
return -EOPNOTSUPP;
return drv_get_survey(local, idx, survey);
}
@ -1329,28 +1326,28 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
}
static int ieee80211_set_tx_power(struct wiphy *wiphy,
enum tx_power_setting type, int dbm)
enum nl80211_tx_power_setting type, int mbm)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_channel *chan = local->hw.conf.channel;
u32 changes = 0;
switch (type) {
case TX_POWER_AUTOMATIC:
case NL80211_TX_POWER_AUTOMATIC:
local->user_power_level = -1;
break;
case TX_POWER_LIMITED:
if (dbm < 0)
return -EINVAL;
local->user_power_level = dbm;
case NL80211_TX_POWER_LIMITED:
if (mbm < 0 || (mbm % 100))
return -EOPNOTSUPP;
local->user_power_level = MBM_TO_DBM(mbm);
break;
case TX_POWER_FIXED:
if (dbm < 0)
return -EINVAL;
case NL80211_TX_POWER_FIXED:
if (mbm < 0 || (mbm % 100))
return -EOPNOTSUPP;
/* TODO: move to cfg80211 when it knows the channel */
if (dbm > chan->max_power)
if (MBM_TO_DBM(mbm) > chan->max_power)
return -EINVAL;
local->user_power_level = dbm;
local->user_power_level = MBM_TO_DBM(mbm);
break;
}

View File

@ -375,9 +375,14 @@ static inline int drv_get_survey(struct ieee80211_local *local, int idx,
struct survey_info *survey)
{
int ret = -EOPNOTSUPP;
trace_drv_get_survey(local, idx, survey);
if (local->ops->get_survey)
ret = local->ops->get_survey(&local->hw, idx, survey);
/* trace_drv_get_survey(local, idx, survey, ret); */
trace_drv_return_int(local, ret);
return ret;
}

View File

@ -761,6 +761,28 @@ TRACE_EVENT(drv_ampdu_action,
)
);
TRACE_EVENT(drv_get_survey,
TP_PROTO(struct ieee80211_local *local, int idx,
struct survey_info *survey),
TP_ARGS(local, idx, survey),
TP_STRUCT__entry(
LOCAL_ENTRY
__field(int, idx)
),
TP_fast_assign(
LOCAL_ASSIGN;
__entry->idx = idx;
),
TP_printk(
LOCAL_PR_FMT " idx:%d",
LOCAL_PR_ARG, __entry->idx
)
);
TRACE_EVENT(drv_flush,
TP_PROTO(struct ieee80211_local *local, bool drop),

View File

@ -855,6 +855,8 @@ struct ieee80211_local {
* this will override whatever chosen by mac80211 internally.
*/
int dynamic_ps_forced_timeout;
int dynamic_ps_user_timeout;
bool disable_dynamic_ps;
int user_power_level; /* in dBm */
int power_constr_level; /* in dBm */

View File

@ -65,7 +65,6 @@ void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
{
atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
mesh_accept_plinks_update(sdata);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
}
static inline
@ -73,7 +72,6 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
{
atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
mesh_accept_plinks_update(sdata);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
}
/**
@ -115,7 +113,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
}
/**
* mesh_plink_deactivate - deactivate mesh peer link
* __mesh_plink_deactivate - deactivate mesh peer link
*
* @sta: mesh peer link to deactivate
*
@ -123,18 +121,23 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
*
* Locking: the caller must hold sta->lock
*/
static void __mesh_plink_deactivate(struct sta_info *sta)
static bool __mesh_plink_deactivate(struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
bool deactivated = false;
if (sta->plink_state == PLINK_ESTAB)
if (sta->plink_state == PLINK_ESTAB) {
mesh_plink_dec_estab_count(sdata);
deactivated = true;
}
sta->plink_state = PLINK_BLOCKED;
mesh_path_flush_by_nexthop(sta);
return deactivated;
}
/**
* __mesh_plink_deactivate - deactivate mesh peer link
* mesh_plink_deactivate - deactivate mesh peer link
*
* @sta: mesh peer link to deactivate
*
@ -142,9 +145,15 @@ static void __mesh_plink_deactivate(struct sta_info *sta)
*/
void mesh_plink_deactivate(struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
bool deactivated;
spin_lock_bh(&sta->lock);
__mesh_plink_deactivate(sta);
deactivated = __mesh_plink_deactivate(sta);
spin_unlock_bh(&sta->lock);
if (deactivated)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
}
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
@ -381,10 +390,16 @@ int mesh_plink_open(struct sta_info *sta)
void mesh_plink_block(struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
bool deactivated;
spin_lock_bh(&sta->lock);
__mesh_plink_deactivate(sta);
deactivated = __mesh_plink_deactivate(sta);
sta->plink_state = PLINK_BLOCKED;
spin_unlock_bh(&sta->lock);
if (deactivated)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
}
@ -397,6 +412,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
enum plink_event event;
enum plink_frame_type ftype;
size_t baselen;
bool deactivated;
u8 ie_len;
u8 *baseaddr;
__le16 plid, llid, reason;
@ -651,8 +667,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
case CNF_ACPT:
del_timer(&sta->plink_timer);
sta->plink_state = PLINK_ESTAB;
mesh_plink_inc_estab_count(sdata);
spin_unlock_bh(&sta->lock);
mesh_plink_inc_estab_count(sdata);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
sta->sta.addr);
break;
@ -684,8 +701,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
case OPN_ACPT:
del_timer(&sta->plink_timer);
sta->plink_state = PLINK_ESTAB;
mesh_plink_inc_estab_count(sdata);
spin_unlock_bh(&sta->lock);
mesh_plink_inc_estab_count(sdata);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
sta->sta.addr);
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
@ -702,11 +720,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
case CLS_ACPT:
reason = cpu_to_le16(MESH_CLOSE_RCVD);
sta->reason = reason;
__mesh_plink_deactivate(sta);
deactivated = __mesh_plink_deactivate(sta);
sta->plink_state = PLINK_HOLDING;
llid = sta->llid;
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
spin_unlock_bh(&sta->lock);
if (deactivated)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
plid, reason);
break;

View File

@ -478,6 +478,39 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
}
}
void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct ieee80211_conf *conf = &local->hw.conf;
WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) ||
(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS));
local->disable_dynamic_ps = false;
conf->dynamic_ps_timeout = local->dynamic_ps_user_timeout;
}
EXPORT_SYMBOL(ieee80211_enable_dyn_ps);
void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct ieee80211_conf *conf = &local->hw.conf;
WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) ||
(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS));
local->disable_dynamic_ps = true;
conf->dynamic_ps_timeout = 0;
del_timer_sync(&local->dynamic_ps_timer);
ieee80211_queue_work(&local->hw,
&local->dynamic_ps_enable_work);
}
EXPORT_SYMBOL(ieee80211_disable_dyn_ps);
/* powersave */
static void ieee80211_enable_ps(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
@ -553,6 +586,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
found->u.mgd.associated->beacon_ies &&
!(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
IEEE80211_STA_CONNECTION_POLL))) {
struct ieee80211_conf *conf = &local->hw.conf;
s32 beaconint_us;
if (latency < 0)
@ -575,7 +609,10 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
else
timeout = 100;
}
local->hw.conf.dynamic_ps_timeout = timeout;
local->dynamic_ps_user_timeout = timeout;
if (!local->disable_dynamic_ps)
conf->dynamic_ps_timeout =
local->dynamic_ps_user_timeout;
if (beaconint_us > latency) {
local->ps_sdata = NULL;

View File

@ -328,7 +328,8 @@ minstrel_next_sample_idx(struct minstrel_ht_sta *mi)
}
static void
minstrel_downgrade_rate(struct minstrel_ht_sta *mi, int *idx, bool primary)
minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx,
bool primary)
{
int group, orig_group;

Some files were not shown because too many files have changed in this diff Show More