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

Conflicts:
	drivers/net/wireless/iwlwifi/iwl-agn.c
	drivers/net/wireless/libertas/cfg.c
This commit is contained in:
John W. Linville 2011-12-02 15:44:03 -05:00
commit d7a4858c0f
30 changed files with 210 additions and 91 deletions

View File

@ -1967,6 +1967,7 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
} }
/* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ /* 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); REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
} }

View File

@ -182,6 +182,7 @@ static struct iwl_base_params iwl1000_base_params = {
.chain_noise_scale = 1000, .chain_noise_scale = 1000,
.wd_timeout = IWL_DEF_WD_TIMEOUT, .wd_timeout = IWL_DEF_WD_TIMEOUT,
.max_event_log_size = 128, .max_event_log_size = 128,
.wd_disable = true,
}; };
static struct iwl_ht_params iwl1000_ht_params = { static struct iwl_ht_params iwl1000_ht_params = {
.ht_greenfield_support = true, .ht_greenfield_support = true,

View File

@ -350,6 +350,7 @@ static struct iwl_base_params iwl5000_base_params = {
.wd_timeout = IWL_LONG_WD_TIMEOUT, .wd_timeout = IWL_LONG_WD_TIMEOUT,
.max_event_log_size = 512, .max_event_log_size = 512,
.no_idle_support = true, .no_idle_support = true,
.wd_disable = true,
}; };
static struct iwl_ht_params iwl5000_ht_params = { static struct iwl_ht_params iwl5000_ht_params = {
.ht_greenfield_support = true, .ht_greenfield_support = true,

View File

@ -529,6 +529,24 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
return 0; return 0;
} }
void iwlagn_config_ht40(struct ieee80211_conf *conf,
struct iwl_rxon_context *ctx)
{
if (conf_is_ht40_minus(conf)) {
ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
ctx->ht.is_40mhz = true;
} else if (conf_is_ht40_plus(conf)) {
ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
ctx->ht.is_40mhz = true;
} else {
ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_NONE;
ctx->ht.is_40mhz = false;
}
}
int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
{ {
struct iwl_priv *priv = hw->priv; struct iwl_priv *priv = hw->priv;
@ -590,19 +608,11 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
ctx->ht.enabled = conf_is_ht(conf); ctx->ht.enabled = conf_is_ht(conf);
if (ctx->ht.enabled) { if (ctx->ht.enabled) {
if (conf_is_ht40_minus(conf)) { /* if HT40 is used, it should not change
ctx->ht.extension_chan_offset = * after associated except channel switch */
IEEE80211_HT_PARAM_CHA_SEC_BELOW; if (iwl_is_associated_ctx(ctx) &&
ctx->ht.is_40mhz = true; !ctx->ht.is_40mhz)
} else if (conf_is_ht40_plus(conf)) { iwlagn_config_ht40(conf, ctx);
ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
ctx->ht.is_40mhz = true;
} else {
ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_NONE;
ctx->ht.is_40mhz = false;
}
} else } else
ctx->ht.is_40mhz = false; ctx->ht.is_40mhz = false;

View File

@ -1250,9 +1250,6 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
switch (keyconf->cipher) { switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
if (sta) if (sta)
addr = sta->addr; addr = sta->addr;
else /* station mode case only */ else /* station mode case only */
@ -1265,8 +1262,6 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
seq.tkip.iv32, p1k, CMD_SYNC); seq.tkip.iv32, p1k, CMD_SYNC);
break; break;
case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP:
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
/* fall through */
case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_WEP104:
ret = iwlagn_send_sta_key(priv, keyconf, sta_id, ret = iwlagn_send_sta_key(priv, keyconf, sta_id,

View File

@ -2022,9 +2022,10 @@ MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO); module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);
MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])"); MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");
module_param_named(wd_disable, iwlagn_mod_params.wd_disable, bool, S_IRUGO); module_param_named(wd_disable, iwlagn_mod_params.wd_disable, int, S_IRUGO);
MODULE_PARM_DESC(wd_disable, MODULE_PARM_DESC(wd_disable,
"Disable stuck queue watchdog timer (default: 0 [enabled])"); "Disable stuck queue watchdog timer 0=system default, "
"1=disable, 2=enable (default: 0)");
/* /*
* set bt_coex_active to true, uCode will do kill/defer * set bt_coex_active to true, uCode will do kill/defer

View File

@ -101,6 +101,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf, struct ieee80211_bss_conf *bss_conf,
u32 changes); u32 changes);
void iwlagn_config_ht40(struct ieee80211_conf *conf,
struct iwl_rxon_context *ctx);
/* uCode */ /* uCode */
int iwlagn_rx_calib_result(struct iwl_priv *priv, int iwlagn_rx_calib_result(struct iwl_priv *priv,

View File

@ -1505,11 +1505,23 @@ void iwl_setup_watchdog(struct iwl_priv *priv)
{ {
unsigned int timeout = priv->cfg->base_params->wd_timeout; unsigned int timeout = priv->cfg->base_params->wd_timeout;
if (timeout && !iwlagn_mod_params.wd_disable) if (!iwlagn_mod_params.wd_disable) {
/* use system default */
if (timeout && !priv->cfg->base_params->wd_disable)
mod_timer(&priv->watchdog, mod_timer(&priv->watchdog,
jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout))); jiffies +
msecs_to_jiffies(IWL_WD_TICK(timeout)));
else else
del_timer(&priv->watchdog); del_timer(&priv->watchdog);
} else {
/* module parameter overwrite default configuration */
if (timeout && iwlagn_mod_params.wd_disable == 2)
mod_timer(&priv->watchdog,
jiffies +
msecs_to_jiffies(IWL_WD_TICK(timeout)));
else
del_timer(&priv->watchdog);
}
} }
/** /**

View File

@ -113,6 +113,7 @@ struct iwl_lib_ops {
* @shadow_reg_enable: HW shadhow register bit * @shadow_reg_enable: HW shadhow register bit
* @no_idle_support: do not support idle mode * @no_idle_support: do not support idle mode
* @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
* wd_disable: disable watchdog timer
*/ */
struct iwl_base_params { struct iwl_base_params {
int eeprom_size; int eeprom_size;
@ -134,6 +135,7 @@ struct iwl_base_params {
const bool shadow_reg_enable; const bool shadow_reg_enable;
const bool no_idle_support; const bool no_idle_support;
const bool hd_v2; const bool hd_v2;
const bool wd_disable;
}; };
/* /*
* @advanced_bt_coexist: support advanced bt coexist * @advanced_bt_coexist: support advanced bt coexist

View File

@ -120,7 +120,7 @@ extern struct iwl_mod_params iwlagn_mod_params;
* @restart_fw: restart firmware, default = 1 * @restart_fw: restart firmware, default = 1
* @plcp_check: enable plcp health check, default = true * @plcp_check: enable plcp health check, default = true
* @ack_check: disable ack health check, default = false * @ack_check: disable ack health check, default = false
* @wd_disable: enable stuck queue check, default = false * @wd_disable: enable stuck queue check, default = 0
* @bt_coex_active: enable bt coex, default = true * @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0 * @led_mode: system default, default = 0
* @no_sleep_autoadjust: disable autoadjust, default = true * @no_sleep_autoadjust: disable autoadjust, default = true
@ -141,7 +141,7 @@ struct iwl_mod_params {
int restart_fw; int restart_fw;
bool plcp_check; bool plcp_check;
bool ack_check; bool ack_check;
bool wd_disable; int wd_disable;
bool bt_coex_active; bool bt_coex_active;
int led_mode; int led_mode;
bool no_sleep_autoadjust; bool no_sleep_autoadjust;

View File

@ -990,29 +990,16 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
return 0; return 0;
} }
static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
{ {
unsigned long flags; unsigned long flags;
struct iwl_trans_pcie *trans_pcie = struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
IWL_TRANS_GET_PCIE_TRANS(trans);
/* tell the device to stop sending interrupts */
spin_lock_irqsave(&trans->shrd->lock, flags); spin_lock_irqsave(&trans->shrd->lock, flags);
iwl_disable_interrupts(trans); iwl_disable_interrupts(trans);
spin_unlock_irqrestore(&trans->shrd->lock, flags); spin_unlock_irqrestore(&trans->shrd->lock, flags);
/* wait to make sure we flush pending tasklet*/
synchronize_irq(bus(trans)->irq);
tasklet_kill(&trans_pcie->irq_tasklet);
}
static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
{
/* stop and reset the on-board processor */
iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
/* tell the device to stop sending interrupts */
iwl_trans_pcie_disable_sync_irq(trans);
/* device going down, Stop using ICT table */ /* device going down, Stop using ICT table */
iwl_disable_ict(trans); iwl_disable_ict(trans);
@ -1039,6 +1026,20 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
/* Stop the device, and put it in low power state */ /* Stop the device, and put it in low power state */
iwl_apm_stop(priv(trans)); iwl_apm_stop(priv(trans));
/* Upon stop, the APM issues an interrupt if HW RF kill is set.
* Clean again the interrupt here
*/
spin_lock_irqsave(&trans->shrd->lock, flags);
iwl_disable_interrupts(trans);
spin_unlock_irqrestore(&trans->shrd->lock, flags);
/* wait to make sure we flush pending tasklet*/
synchronize_irq(bus(trans)->irq);
tasklet_kill(&trans_pcie->irq_tasklet);
/* stop and reset the on-board processor */
iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
} }
static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,

View File

@ -635,7 +635,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
if (channel && if (channel &&
!(channel->flags & IEEE80211_CHAN_DISABLED)) { !(channel->flags & IEEE80211_CHAN_DISABLED)) {
bss = cfg80211_inform_bss(wiphy, channel, bss = cfg80211_inform_bss(wiphy, channel,
bssid, le64_to_cpu(*(__le64 *)tsfdesc), bssid, get_unaligned_le64(tsfdesc),
capa, intvl, ie, ielen, capa, intvl, ie, ielen,
LBS_SCAN_RSSI_TO_MBM(rssi), LBS_SCAN_RSSI_TO_MBM(rssi),
GFP_KERNEL); GFP_KERNEL);

View File

@ -995,6 +995,7 @@ static int if_spi_host_to_card(struct lbs_private *priv,
spin_unlock_irqrestore(&card->buffer_lock, flags); spin_unlock_irqrestore(&card->buffer_lock, flags);
break; break;
default: default:
kfree(packet);
netdev_err(priv->dev, "can't transfer buffer of type %d\n", netdev_err(priv->dev, "can't transfer buffer of type %d\n",
type); type);
err = -EINVAL; err = -EINVAL;

View File

@ -819,8 +819,10 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
wildcard_ssid_tlv->header.len = cpu_to_le16( wildcard_ssid_tlv->header.len = cpu_to_le16(
(u16) (ssid_len + sizeof(wildcard_ssid_tlv-> (u16) (ssid_len + sizeof(wildcard_ssid_tlv->
max_ssid_length))); max_ssid_length)));
wildcard_ssid_tlv->max_ssid_length =
user_scan_in->ssid_list[ssid_idx].max_len; /* max_ssid_length = 0 tells firmware to perform
specific scan for the SSID filled */
wildcard_ssid_tlv->max_ssid_length = 0;
memcpy(wildcard_ssid_tlv->ssid, memcpy(wildcard_ssid_tlv->ssid,
user_scan_in->ssid_list[ssid_idx].ssid, user_scan_in->ssid_list[ssid_idx].ssid,

View File

@ -584,8 +584,6 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
WARN_ON(priv->fw_state != FW_STATE_READY); WARN_ON(priv->fw_state != FW_STATE_READY);
cancel_work_sync(&priv->work);
p54spi_power_off(priv); p54spi_power_off(priv);
spin_lock_irqsave(&priv->tx_lock, flags); spin_lock_irqsave(&priv->tx_lock, flags);
INIT_LIST_HEAD(&priv->tx_pending); INIT_LIST_HEAD(&priv->tx_pending);
@ -593,6 +591,8 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
priv->fw_state = FW_STATE_OFF; priv->fw_state = FW_STATE_OFF;
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
cancel_work_sync(&priv->work);
} }
static int __devinit p54spi_probe(struct spi_device *spi) static int __devinit p54spi_probe(struct spi_device *spi)
@ -652,6 +652,7 @@ static int __devinit p54spi_probe(struct spi_device *spi)
init_completion(&priv->fw_comp); init_completion(&priv->fw_comp);
INIT_LIST_HEAD(&priv->tx_pending); INIT_LIST_HEAD(&priv->tx_pending);
mutex_init(&priv->mutex); mutex_init(&priv->mutex);
spin_lock_init(&priv->tx_lock);
SET_IEEE80211_DEV(hw, &spi->dev); SET_IEEE80211_DEV(hw, &spi->dev);
priv->common.open = p54spi_op_start; priv->common.open = p54spi_op_start;
priv->common.stop = p54spi_op_stop; priv->common.stop = p54spi_op_stop;

View File

@ -778,7 +778,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
dwrq->flags = 0; dwrq->flags = 0;
dwrq->length = 0; dwrq->length = 0;
} }
essid->octets[essid->length] = '\0'; essid->octets[dwrq->length] = '\0';
memcpy(extra, essid->octets, dwrq->length); memcpy(extra, essid->octets, dwrq->length);
kfree(essid); kfree(essid);

View File

@ -3773,7 +3773,7 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
/* Apparently the data is read from end to start */ /* Apparently the data is read from end to start */
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg); rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
/* The returned value is in CPU order, but eeprom is le */ /* The returned value is in CPU order, but eeprom is le */
rt2x00dev->eeprom[i] = cpu_to_le32(reg); *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg); rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg); rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);

View File

@ -919,6 +919,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x050d, 0x935b) }, { USB_DEVICE(0x050d, 0x935b) },
/* Buffalo */ /* Buffalo */
{ USB_DEVICE(0x0411, 0x00e8) }, { USB_DEVICE(0x0411, 0x00e8) },
{ USB_DEVICE(0x0411, 0x0158) },
{ USB_DEVICE(0x0411, 0x016f) }, { USB_DEVICE(0x0411, 0x016f) },
{ USB_DEVICE(0x0411, 0x01a2) }, { USB_DEVICE(0x0411, 0x01a2) },
/* Corega */ /* Corega */

View File

@ -943,6 +943,7 @@ struct rt2x00_dev {
* Powersaving work * Powersaving work
*/ */
struct delayed_work autowakeup_work; struct delayed_work autowakeup_work;
struct work_struct sleep_work;
/* /*
* Data queue arrays for RX, TX, Beacon and ATIM. * Data queue arrays for RX, TX, Beacon and ATIM.

View File

@ -465,6 +465,23 @@ static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie)
return NULL; return NULL;
} }
static void rt2x00lib_sleep(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, sleep_work);
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return;
/*
* Check again is powersaving is enabled, to prevent races from delayed
* work execution.
*/
if (!test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
IEEE80211_CONF_CHANGE_PS);
}
static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev, static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb, struct sk_buff *skb,
struct rxdone_entry_desc *rxdesc) struct rxdone_entry_desc *rxdesc)
@ -512,8 +529,7 @@ static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
cam |= (tim_ie->bitmap_ctrl & 0x01); cam |= (tim_ie->bitmap_ctrl & 0x01);
if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags)) if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf, queue_work(rt2x00dev->workqueue, &rt2x00dev->sleep_work);
IEEE80211_CONF_CHANGE_PS);
} }
static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
@ -1141,6 +1157,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup); INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
/* /*
* Let the driver probe the device to detect the capabilities. * Let the driver probe the device to detect the capabilities.
@ -1197,6 +1214,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
*/ */
cancel_work_sync(&rt2x00dev->intf_work); cancel_work_sync(&rt2x00dev->intf_work);
cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
cancel_work_sync(&rt2x00dev->sleep_work);
if (rt2x00_is_usb(rt2x00dev)) { if (rt2x00_is_usb(rt2x00dev)) {
del_timer_sync(&rt2x00dev->txstatus_timer); del_timer_sync(&rt2x00dev->txstatus_timer);
cancel_work_sync(&rt2x00dev->rxdone_work); cancel_work_sync(&rt2x00dev->rxdone_work);

View File

@ -395,7 +395,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
if (mac->link_state != MAC80211_LINKED) if (mac->link_state != MAC80211_LINKED)
return; return;
spin_lock(&rtlpriv->locks.lps_lock); spin_lock_irq(&rtlpriv->locks.lps_lock);
/* Idle for a while if we connect to AP a while ago. */ /* Idle for a while if we connect to AP a while ago. */
if (mac->cnt_after_linked >= 2) { if (mac->cnt_after_linked >= 2) {
@ -407,7 +407,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
} }
} }
spin_unlock(&rtlpriv->locks.lps_lock); spin_unlock_irq(&rtlpriv->locks.lps_lock);
} }
/*Leave the leisure power save mode.*/ /*Leave the leisure power save mode.*/
@ -416,8 +416,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
unsigned long flags;
spin_lock(&rtlpriv->locks.lps_lock); spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags);
if (ppsc->fwctrl_lps) { if (ppsc->fwctrl_lps) {
if (ppsc->dot11_psmode != EACTIVE) { if (ppsc->dot11_psmode != EACTIVE) {
@ -438,7 +439,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
rtl_lps_set_psmode(hw, EACTIVE); rtl_lps_set_psmode(hw, EACTIVE);
} }
} }
spin_unlock(&rtlpriv->locks.lps_lock); spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags);
} }
/* For sw LPS*/ /* For sw LPS*/
@ -539,9 +540,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
} }
spin_lock(&rtlpriv->locks.lps_lock); spin_lock_irq(&rtlpriv->locks.lps_lock);
rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS); rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
spin_unlock(&rtlpriv->locks.lps_lock); spin_unlock_irq(&rtlpriv->locks.lps_lock);
} }
void rtl_swlps_rfon_wq_callback(void *data) void rtl_swlps_rfon_wq_callback(void *data)
@ -574,9 +575,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
if (rtlpriv->link_info.busytraffic) if (rtlpriv->link_info.busytraffic)
return; return;
spin_lock(&rtlpriv->locks.lps_lock); spin_lock_irq(&rtlpriv->locks.lps_lock);
rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
spin_unlock(&rtlpriv->locks.lps_lock); spin_unlock_irq(&rtlpriv->locks.lps_lock);
if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
!RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {

View File

@ -162,6 +162,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
return -ENOENT; return -ENOENT;
} }
/* if we're already stopping ignore any new requests to stop */
if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
spin_unlock_bh(&sta->lock);
return -EALREADY;
}
if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
/* not even started yet! */ /* not even started yet! */
ieee80211_assign_tid_tx(sta, tid, NULL); ieee80211_assign_tid_tx(sta, tid, NULL);
@ -170,6 +176,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
return 0; return 0;
} }
set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
@ -177,8 +185,6 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
sta->sta.addr, tid); sta->sta.addr, tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */ #endif /* CONFIG_MAC80211_HT_DEBUG */
set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
del_timer_sync(&tid_tx->addba_resp_timer); del_timer_sync(&tid_tx->addba_resp_timer);
del_timer_sync(&tid_tx->session_timer); del_timer_sync(&tid_tx->session_timer);
@ -189,6 +195,20 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
*/ */
clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
/*
* There might be a few packets being processed right now (on
* another CPU) that have already gotten past the aggregation
* check when it was still OPERATIONAL and consequently have
* IEEE80211_TX_CTL_AMPDU set. In that case, this code might
* call into the driver at the same time or even before the
* TX paths calls into it, which could confuse the driver.
*
* Wait for all currently running TX paths to finish before
* telling the driver. New packets will not go through since
* the aggregation session is no longer OPERATIONAL.
*/
synchronize_net();
tid_tx->stop_initiator = initiator; tid_tx->stop_initiator = initiator;
tid_tx->tx_stop = tx; tid_tx->tx_stop = tx;
@ -781,11 +801,27 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
goto out; goto out;
} }
del_timer(&tid_tx->addba_resp_timer); del_timer_sync(&tid_tx->addba_resp_timer);
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid);
#endif #endif
/*
* addba_resp_timer may have fired before we got here, and
* caused WANT_STOP to be set. If the stop then was already
* processed further, STOPPING might be set.
*/
if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) ||
test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG
"got addBA resp for tid %d but we already gave up\n",
tid);
#endif
goto out;
}
/* /*
* IEEE 802.11-2007 7.3.1.14: * IEEE 802.11-2007 7.3.1.14:
* In an ADDBA Response frame, when the Status Code field * In an ADDBA Response frame, when the Status Code field

View File

@ -274,9 +274,9 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack"); PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack");
PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: "
"3839 bytes");
PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: " PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: "
"3839 bytes");
PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: "
"7935 bytes"); "7935 bytes");
/* /*

View File

@ -738,6 +738,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (!local->int_scan_req) if (!local->int_scan_req)
return -ENOMEM; return -ENOMEM;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
if (!local->hw.wiphy->bands[band])
continue;
local->int_scan_req->rates[band] = (u32) -1;
}
/* if low-level driver supports AP, we also support VLAN */ /* if low-level driver supports AP, we also support VLAN */
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);

View File

@ -2301,6 +2301,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
cancel_work_sync(&ifmgd->request_smps_work); cancel_work_sync(&ifmgd->request_smps_work);
cancel_work_sync(&ifmgd->monitor_work);
cancel_work_sync(&ifmgd->beacon_connection_loss_work); cancel_work_sync(&ifmgd->beacon_connection_loss_work);
if (del_timer_sync(&ifmgd->timer)) if (del_timer_sync(&ifmgd->timer))
set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
@ -2309,7 +2310,6 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
if (del_timer_sync(&ifmgd->chswitch_timer)) if (del_timer_sync(&ifmgd->chswitch_timer))
set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
cancel_work_sync(&ifmgd->monitor_work);
/* these will just be re-established on connection */ /* these will just be re-established on connection */
del_timer_sync(&ifmgd->conn_mon_timer); del_timer_sync(&ifmgd->conn_mon_timer);
del_timer_sync(&ifmgd->bcn_mon_timer); del_timer_sync(&ifmgd->bcn_mon_timer);

View File

@ -141,8 +141,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
pos++; pos++;
/* IEEE80211_RADIOTAP_RATE */ /* IEEE80211_RADIOTAP_RATE */
if (status->flag & RX_FLAG_HT) { if (!rate || status->flag & RX_FLAG_HT) {
/* /*
* Without rate information don't add it. If we have,
* MCS information is a separate field in radiotap, * MCS information is a separate field in radiotap,
* added below. The byte here is needed as padding * added below. The byte here is needed as padding
* for the channel though, so initialise it to 0. * for the channel though, so initialise it to 0.
@ -163,12 +164,14 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
else if (status->flag & RX_FLAG_HT) else if (status->flag & RX_FLAG_HT)
put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ,
pos); pos);
else if (rate->flags & IEEE80211_RATE_ERP_G) else if (rate && rate->flags & IEEE80211_RATE_ERP_G)
put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ,
pos); pos);
else else if (rate)
put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ,
pos); pos);
else
put_unaligned_le16(IEEE80211_CHAN_2GHZ, pos);
pos += 2; pos += 2;
/* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */

View File

@ -260,7 +260,7 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_radiotap_header *rthdr; struct ieee80211_radiotap_header *rthdr;
unsigned char *pos; unsigned char *pos;
__le16 txflags; u16 txflags;
rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len); rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len);
@ -290,13 +290,13 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
txflags = 0; txflags = 0;
if (!(info->flags & IEEE80211_TX_STAT_ACK) && if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
!is_multicast_ether_addr(hdr->addr1)) !is_multicast_ether_addr(hdr->addr1))
txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); txflags |= IEEE80211_RADIOTAP_F_TX_FAIL;
if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
(info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); txflags |= IEEE80211_RADIOTAP_F_TX_CTS;
else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); txflags |= IEEE80211_RADIOTAP_F_TX_RTS;
put_unaligned_le16(txflags, pos); put_unaligned_le16(txflags, pos);
pos += 2; pos += 2;

View File

@ -1034,6 +1034,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
skb = ieee80211_probereq_get(&local->hw, &sdata->vif, skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
ssid, ssid_len, ssid, ssid_len,
buf, buf_len); buf, buf_len);
if (!skb)
goto out;
if (dst) { if (dst) {
mgmt = (struct ieee80211_mgmt *) skb->data; mgmt = (struct ieee80211_mgmt *) skb->data;
@ -1042,6 +1044,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
} }
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
out:
kfree(buf); kfree(buf);
return skb; return skb;
@ -1188,7 +1192,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
struct ieee80211_sub_if_data, struct ieee80211_sub_if_data,
u.ap); u.ap);
memset(&sta->sta.drv_priv, 0, hw->sta_data_size);
WARN_ON(drv_sta_add(local, sdata, &sta->sta)); WARN_ON(drv_sta_add(local, sdata, &sta->sta));
} }
} }

View File

@ -89,8 +89,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
[NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
[NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, [NL80211_ATTR_MAC] = { .len = ETH_ALEN },
[NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN }, [NL80211_ATTR_PREV_BSSID] = { .len = ETH_ALEN },
[NL80211_ATTR_KEY] = { .type = NLA_NESTED, }, [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
[NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,

View File

@ -57,8 +57,17 @@
#define REG_DBG_PRINT(args...) #define REG_DBG_PRINT(args...)
#endif #endif
static struct regulatory_request core_request_world = {
.initiator = NL80211_REGDOM_SET_BY_CORE,
.alpha2[0] = '0',
.alpha2[1] = '0',
.intersect = false,
.processed = true,
.country_ie_env = ENVIRON_ANY,
};
/* Receipt of information from last regulatory request */ /* Receipt of information from last regulatory request */
static struct regulatory_request *last_request; static struct regulatory_request *last_request = &core_request_world;
/* To trigger userspace events */ /* To trigger userspace events */
static struct platform_device *reg_pdev; static struct platform_device *reg_pdev;
@ -150,7 +159,7 @@ static char user_alpha2[2];
module_param(ieee80211_regdom, charp, 0444); module_param(ieee80211_regdom, charp, 0444);
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
static void reset_regdomains(void) static void reset_regdomains(bool full_reset)
{ {
/* avoid freeing static information or freeing something twice */ /* avoid freeing static information or freeing something twice */
if (cfg80211_regdomain == cfg80211_world_regdom) if (cfg80211_regdomain == cfg80211_world_regdom)
@ -165,6 +174,13 @@ static void reset_regdomains(void)
cfg80211_world_regdom = &world_regdom; cfg80211_world_regdom = &world_regdom;
cfg80211_regdomain = NULL; cfg80211_regdomain = NULL;
if (!full_reset)
return;
if (last_request != &core_request_world)
kfree(last_request);
last_request = &core_request_world;
} }
/* /*
@ -175,7 +191,7 @@ static void update_world_regdomain(const struct ieee80211_regdomain *rd)
{ {
BUG_ON(!last_request); BUG_ON(!last_request);
reset_regdomains(); reset_regdomains(false);
cfg80211_world_regdom = rd; cfg80211_world_regdom = rd;
cfg80211_regdomain = rd; cfg80211_regdomain = rd;
@ -1409,6 +1425,7 @@ static int __regulatory_hint(struct wiphy *wiphy,
} }
new_request: new_request:
if (last_request != &core_request_world)
kfree(last_request); kfree(last_request);
last_request = pending_request; last_request = pending_request;
@ -1579,9 +1596,6 @@ static int regulatory_hint_core(const char *alpha2)
{ {
struct regulatory_request *request; struct regulatory_request *request;
kfree(last_request);
last_request = NULL;
request = kzalloc(sizeof(struct regulatory_request), request = kzalloc(sizeof(struct regulatory_request),
GFP_KERNEL); GFP_KERNEL);
if (!request) if (!request)
@ -1779,7 +1793,7 @@ static void restore_regulatory_settings(bool reset_user)
mutex_lock(&cfg80211_mutex); mutex_lock(&cfg80211_mutex);
mutex_lock(&reg_mutex); mutex_lock(&reg_mutex);
reset_regdomains(); reset_regdomains(true);
restore_alpha2(alpha2, reset_user); restore_alpha2(alpha2, reset_user);
/* /*
@ -2076,12 +2090,18 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
} }
request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
if (!request_wiphy &&
(last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
schedule_delayed_work(&reg_timeout, 0);
return -ENODEV;
}
if (!last_request->intersect) { if (!last_request->intersect) {
int r; int r;
if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) { if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) {
reset_regdomains(); reset_regdomains(false);
cfg80211_regdomain = rd; cfg80211_regdomain = rd;
return 0; return 0;
} }
@ -2102,7 +2122,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
if (r) if (r)
return r; return r;
reset_regdomains(); reset_regdomains(false);
cfg80211_regdomain = rd; cfg80211_regdomain = rd;
return 0; return 0;
} }
@ -2127,7 +2147,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
rd = NULL; rd = NULL;
reset_regdomains(); reset_regdomains(false);
cfg80211_regdomain = intersected_rd; cfg80211_regdomain = intersected_rd;
return 0; return 0;
@ -2147,7 +2167,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
kfree(rd); kfree(rd);
rd = NULL; rd = NULL;
reset_regdomains(); reset_regdomains(false);
cfg80211_regdomain = intersected_rd; cfg80211_regdomain = intersected_rd;
return 0; return 0;
@ -2300,9 +2320,9 @@ void /* __init_or_exit */ regulatory_exit(void)
mutex_lock(&cfg80211_mutex); mutex_lock(&cfg80211_mutex);
mutex_lock(&reg_mutex); mutex_lock(&reg_mutex);
reset_regdomains(); reset_regdomains(true);
kfree(last_request); dev_set_uevent_suppress(&reg_pdev->dev, true);
platform_device_unregister(reg_pdev); platform_device_unregister(reg_pdev);