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:
commit
05318bc905
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) { \
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 */
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(¤t_stat, pkt->u.raw, sizeof(struct
|
||||
iwl3945_notif_statistics));
|
||||
/*
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
|
|
@ -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",
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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), },
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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 =
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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, ®);
|
||||
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,
|
||||
|
|
|
@ -99,8 +99,7 @@ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0);
|
||||
if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1);
|
||||
rt2x00_set_field32(®, 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(®, BBP_CSR_CFG_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1);
|
||||
if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1);
|
||||
rt2x00_set_field32(®, 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(®, MAC_BSSID_DW1_BSS_ID_MASK, 0);
|
||||
rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
|
||||
rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 3);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ""
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue