Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into wireless
John W. Linville says: ==================== This will probably be the last batch of wireless fixes intended for 3.10. Many of these are one- or two-liners, and a couple of others are mostly relocating existing code to avoid races or to limit the code to effecting specific hardware, etc. The mac80211 fixes have a couple of exceptions to the above. Regarding those, Johannes says: "Following davem's complaint about my patch, here's a new pull request w/o the patch he was complaining about, but instead with the const fix rolled into the fix. I have a fix for radar detection, one for rate control and a workaround for broken HT APs which is a regression fix because we didn't rely on them to be correct before." Johannes also sends some iwlwifi fixes: "I picked up Nikolay's patch for the chain noise calibration bug that seems to have been there forever, a fix from Emmanuel for setting TX flags on BAR frames and a fix of my own to avoid printing request_module() errors if the kernel isn't even modular. We also have our own version of Stanislaw's fix for rate control." Along with those... Anderson Lizardo fixes a Bluetooth memory corruption bug when an MTU value is set to too small of a value. Arend van Spriel sends a revised brcmsmac bug that fixes a regression caused by a bad return value in an earlier patch. He also sends a brcmfmac fix to avoid an oops when loading the driver at boot. Daniel Drake fixes a race condition in btmrvl that causes hangs on suspend for OLPC hardware. Johan Hedberg adds a check to avoid sending a HCI_Delete_Stored_Link_Key command to devices that don't support them, avoiding some scary looking log spam. Stanislaw Gruszka gives us a fix for iwlegacy to be able to use rates higher than 1Mb/s on older wireless networks. He also sends an rt2x00 fix to reinstate older tx power handling behavior for some devices that didn't work well with the current code. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
c5b248dd05
|
@ -498,6 +498,10 @@ static int btmrvl_service_main_thread(void *data)
|
|||
add_wait_queue(&thread->wait_q, &wait);
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (kthread_should_stop()) {
|
||||
BT_DBG("main_thread: break from main thread");
|
||||
break;
|
||||
}
|
||||
|
||||
if (adapter->wakeup_tries ||
|
||||
((!adapter->int_count) &&
|
||||
|
@ -513,11 +517,6 @@ static int btmrvl_service_main_thread(void *data)
|
|||
|
||||
BT_DBG("main_thread woke up");
|
||||
|
||||
if (kthread_should_stop()) {
|
||||
BT_DBG("main_thread: break from main thread");
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
if (adapter->int_count) {
|
||||
adapter->int_count = 0;
|
||||
|
|
|
@ -930,6 +930,10 @@ fail:
|
|||
brcmf_fws_del_interface(ifp);
|
||||
brcmf_fws_deinit(drvr);
|
||||
}
|
||||
if (drvr->iflist[0]) {
|
||||
free_netdev(ifp->ndev);
|
||||
drvr->iflist[0] = NULL;
|
||||
}
|
||||
if (p2p_ifp) {
|
||||
free_netdev(p2p_ifp->ndev);
|
||||
drvr->iflist[1] = NULL;
|
||||
|
|
|
@ -3074,21 +3074,8 @@ static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
|
|||
*/
|
||||
static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
|
||||
{
|
||||
/* disallow PS when one of the following global conditions meets */
|
||||
if (!wlc->pub->associated)
|
||||
return false;
|
||||
|
||||
/* disallow PS when one of these meets when not scanning */
|
||||
if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
|
||||
return false;
|
||||
|
||||
if (wlc->bsscfg->type == BRCMS_TYPE_AP)
|
||||
return false;
|
||||
|
||||
if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
/* not supporting PS so always return false for now */
|
||||
return false;
|
||||
}
|
||||
|
||||
static void brcms_c_statsupd(struct brcms_c_info *wlc)
|
||||
|
|
|
@ -816,6 +816,7 @@ out:
|
|||
rs_sta->last_txrate_idx = idx;
|
||||
info->control.rates[0].idx = rs_sta->last_txrate_idx;
|
||||
}
|
||||
info->control.rates[0].count = 1;
|
||||
|
||||
D_RATE("leave: %d\n", idx);
|
||||
}
|
||||
|
|
|
@ -2268,7 +2268,7 @@ il4965_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta,
|
|||
info->control.rates[0].flags = 0;
|
||||
}
|
||||
info->control.rates[0].idx = rate_idx;
|
||||
|
||||
info->control.rates[0].count = 1;
|
||||
}
|
||||
|
||||
static void *
|
||||
|
|
|
@ -2799,7 +2799,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
|
|||
info->control.rates[0].flags = 0;
|
||||
}
|
||||
info->control.rates[0].idx = rate_idx;
|
||||
|
||||
info->control.rates[0].count = 1;
|
||||
}
|
||||
|
||||
static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
|
||||
|
|
|
@ -1378,7 +1378,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
|
|||
struct iwl_chain_noise_data *data = &priv->chain_noise_data;
|
||||
int ret;
|
||||
|
||||
if (!(priv->calib_disabled & IWL_CHAIN_NOISE_CALIB_DISABLED))
|
||||
if (priv->calib_disabled & IWL_CHAIN_NOISE_CALIB_DISABLED)
|
||||
return;
|
||||
|
||||
if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
|
||||
|
|
|
@ -1000,10 +1000,12 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
|||
*/
|
||||
if (load_module) {
|
||||
err = request_module("%s", op->name);
|
||||
#ifdef CONFIG_IWLWIFI_OPMODE_MODULAR
|
||||
if (err)
|
||||
IWL_ERR(drv,
|
||||
"failed to load module %s (error %d), is dynamic loading enabled?\n",
|
||||
op->name, err);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
|
||||
|
|
|
@ -2546,6 +2546,7 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta,
|
|||
info->control.rates[0].flags = 0;
|
||||
}
|
||||
info->control.rates[0].idx = rate_idx;
|
||||
info->control.rates[0].count = 1;
|
||||
}
|
||||
|
||||
static void *rs_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta,
|
||||
|
|
|
@ -180,7 +180,8 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
|
|||
tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
|
||||
return;
|
||||
} else if (ieee80211_is_back_req(fc)) {
|
||||
tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
|
||||
tx_cmd->tx_flags |=
|
||||
cpu_to_le32(TX_CMD_FLG_ACK | TX_CMD_FLG_BAR);
|
||||
}
|
||||
|
||||
/* HT rate doesn't make sense for a non data frame */
|
||||
|
|
|
@ -3027,19 +3027,26 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
|
|||
* TODO: we do not use +6 dBm option to do not increase power beyond
|
||||
* regulatory limit, however this could be utilized for devices with
|
||||
* CAPABILITY_POWER_LIMIT.
|
||||
*
|
||||
* TODO: add different temperature compensation code for RT3290 & RT5390
|
||||
* to allow to use BBP_R1 for those chips.
|
||||
*/
|
||||
rt2800_bbp_read(rt2x00dev, 1, &r1);
|
||||
if (delta <= -12) {
|
||||
power_ctrl = 2;
|
||||
delta += 12;
|
||||
} else if (delta <= -6) {
|
||||
power_ctrl = 1;
|
||||
delta += 6;
|
||||
} else {
|
||||
power_ctrl = 0;
|
||||
if (!rt2x00_rt(rt2x00dev, RT3290) &&
|
||||
!rt2x00_rt(rt2x00dev, RT5390)) {
|
||||
rt2800_bbp_read(rt2x00dev, 1, &r1);
|
||||
if (delta <= -12) {
|
||||
power_ctrl = 2;
|
||||
delta += 12;
|
||||
} else if (delta <= -6) {
|
||||
power_ctrl = 1;
|
||||
delta += 6;
|
||||
} else {
|
||||
power_ctrl = 0;
|
||||
}
|
||||
rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
|
||||
rt2800_bbp_write(rt2x00dev, 1, r1);
|
||||
}
|
||||
rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
|
||||
rt2800_bbp_write(rt2x00dev, 1, r1);
|
||||
|
||||
offset = TX_PWR_CFG_0;
|
||||
|
||||
for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) {
|
||||
|
|
|
@ -341,7 +341,6 @@ static void hci_init1_req(struct hci_request *req, unsigned long opt)
|
|||
|
||||
static void bredr_setup(struct hci_request *req)
|
||||
{
|
||||
struct hci_cp_delete_stored_link_key cp;
|
||||
__le16 param;
|
||||
__u8 flt_type;
|
||||
|
||||
|
@ -365,10 +364,6 @@ static void bredr_setup(struct hci_request *req)
|
|||
param = __constant_cpu_to_le16(0x7d00);
|
||||
hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m);
|
||||
|
||||
bacpy(&cp.bdaddr, BDADDR_ANY);
|
||||
cp.delete_all = 0x01;
|
||||
hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
|
||||
|
||||
/* Read page scan parameters */
|
||||
if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) {
|
||||
hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL);
|
||||
|
@ -602,6 +597,16 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
|
|||
struct hci_dev *hdev = req->hdev;
|
||||
u8 p;
|
||||
|
||||
/* Only send HCI_Delete_Stored_Link_Key if it is supported */
|
||||
if (hdev->commands[6] & 0x80) {
|
||||
struct hci_cp_delete_stored_link_key cp;
|
||||
|
||||
bacpy(&cp.bdaddr, BDADDR_ANY);
|
||||
cp.delete_all = 0x01;
|
||||
hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY,
|
||||
sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
if (hdev->commands[5] & 0x10)
|
||||
hci_setup_link_policy(req);
|
||||
|
||||
|
|
|
@ -2852,6 +2852,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
|
|||
BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
|
||||
conn, code, ident, dlen);
|
||||
|
||||
if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
|
||||
return NULL;
|
||||
|
||||
len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
|
||||
count = min_t(unsigned int, conn->mtu, len);
|
||||
|
||||
|
|
|
@ -1057,6 +1057,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||
|
||||
if (sdata->wdev.cac_started) {
|
||||
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
||||
cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
drv_stop_ap(sdata->local, sdata);
|
||||
|
||||
/* free all potentially still buffered bcast frames */
|
||||
|
|
|
@ -1497,10 +1497,11 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
|
|||
ieee80211_tx_skb_tid(sdata, skb, 7);
|
||||
}
|
||||
|
||||
u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action,
|
||||
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
||||
struct ieee802_11_elems *elems,
|
||||
u64 filter, u32 crc);
|
||||
static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action,
|
||||
static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||
bool action,
|
||||
struct ieee802_11_elems *elems)
|
||||
{
|
||||
ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
|
||||
|
|
|
@ -2522,8 +2522,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||
u16 capab_info, aid;
|
||||
struct ieee802_11_elems elems;
|
||||
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
|
||||
const struct cfg80211_bss_ies *bss_ies = NULL;
|
||||
struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
|
||||
u32 changed = 0;
|
||||
int err;
|
||||
bool ret;
|
||||
|
||||
/* AssocResp and ReassocResp have identical structure */
|
||||
|
||||
|
@ -2554,6 +2557,69 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
ifmgd->aid = aid;
|
||||
|
||||
/*
|
||||
* Some APs are erroneously not including some information in their
|
||||
* (re)association response frames. Try to recover by using the data
|
||||
* from the beacon or probe response. This seems to afflict mobile
|
||||
* 2G/3G/4G wifi routers, reported models include the "Onda PN51T",
|
||||
* "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device.
|
||||
*/
|
||||
if ((assoc_data->wmm && !elems.wmm_param) ||
|
||||
(!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
|
||||
(!elems.ht_cap_elem || !elems.ht_operation)) ||
|
||||
(!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
|
||||
(!elems.vht_cap_elem || !elems.vht_operation))) {
|
||||
const struct cfg80211_bss_ies *ies;
|
||||
struct ieee802_11_elems bss_elems;
|
||||
|
||||
rcu_read_lock();
|
||||
ies = rcu_dereference(cbss->ies);
|
||||
if (ies)
|
||||
bss_ies = kmemdup(ies, sizeof(*ies) + ies->len,
|
||||
GFP_ATOMIC);
|
||||
rcu_read_unlock();
|
||||
if (!bss_ies)
|
||||
return false;
|
||||
|
||||
ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
|
||||
false, &bss_elems);
|
||||
if (assoc_data->wmm &&
|
||||
!elems.wmm_param && bss_elems.wmm_param) {
|
||||
elems.wmm_param = bss_elems.wmm_param;
|
||||
sdata_info(sdata,
|
||||
"AP bug: WMM param missing from AssocResp\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Also check if we requested HT/VHT, otherwise the AP doesn't
|
||||
* have to include the IEs in the (re)association response.
|
||||
*/
|
||||
if (!elems.ht_cap_elem && bss_elems.ht_cap_elem &&
|
||||
!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
|
||||
elems.ht_cap_elem = bss_elems.ht_cap_elem;
|
||||
sdata_info(sdata,
|
||||
"AP bug: HT capability missing from AssocResp\n");
|
||||
}
|
||||
if (!elems.ht_operation && bss_elems.ht_operation &&
|
||||
!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
|
||||
elems.ht_operation = bss_elems.ht_operation;
|
||||
sdata_info(sdata,
|
||||
"AP bug: HT operation missing from AssocResp\n");
|
||||
}
|
||||
if (!elems.vht_cap_elem && bss_elems.vht_cap_elem &&
|
||||
!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
|
||||
elems.vht_cap_elem = bss_elems.vht_cap_elem;
|
||||
sdata_info(sdata,
|
||||
"AP bug: VHT capa missing from AssocResp\n");
|
||||
}
|
||||
if (!elems.vht_operation && bss_elems.vht_operation &&
|
||||
!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
|
||||
elems.vht_operation = bss_elems.vht_operation;
|
||||
sdata_info(sdata,
|
||||
"AP bug: VHT operation missing from AssocResp\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We previously checked these in the beacon/probe response, so
|
||||
* they should be present here. This is just a safety net.
|
||||
|
@ -2561,15 +2627,17 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
|
||||
(!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) {
|
||||
sdata_info(sdata,
|
||||
"HT AP is missing WMM params or HT capability/operation in AssocResp\n");
|
||||
return false;
|
||||
"HT AP is missing WMM params or HT capability/operation\n");
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
|
||||
(!elems.vht_cap_elem || !elems.vht_operation)) {
|
||||
sdata_info(sdata,
|
||||
"VHT AP is missing VHT capability/operation in AssocResp\n");
|
||||
return false;
|
||||
"VHT AP is missing VHT capability/operation\n");
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_lock(&sdata->local->sta_mtx);
|
||||
|
@ -2580,7 +2648,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||
sta = sta_info_get(sdata, cbss->bssid);
|
||||
if (WARN_ON(!sta)) {
|
||||
mutex_unlock(&sdata->local->sta_mtx);
|
||||
return false;
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
|
||||
|
@ -2633,7 +2702,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||
sta->sta.addr);
|
||||
WARN_ON(__sta_info_destroy(sta));
|
||||
mutex_unlock(&sdata->local->sta_mtx);
|
||||
return false;
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_unlock(&sdata->local->sta_mtx);
|
||||
|
@ -2673,7 +2743,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||
ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
|
||||
ieee80211_sta_reset_beacon_monitor(sdata);
|
||||
|
||||
return true;
|
||||
ret = true;
|
||||
out:
|
||||
kfree(bss_ies);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum rx_mgmt_action __must_check
|
||||
|
|
|
@ -615,7 +615,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
|
|||
if (rates[i].idx < 0)
|
||||
break;
|
||||
|
||||
rate_idx_match_mask(&rates[i], sband, mask, chan_width,
|
||||
rate_idx_match_mask(&rates[i], sband, chan_width, mask,
|
||||
mcs_mask);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -661,12 +661,12 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_queue_delayed_work);
|
||||
|
||||
u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action,
|
||||
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
||||
struct ieee802_11_elems *elems,
|
||||
u64 filter, u32 crc)
|
||||
{
|
||||
size_t left = len;
|
||||
u8 *pos = start;
|
||||
const u8 *pos = start;
|
||||
bool calc_crc = filter != 0;
|
||||
DECLARE_BITMAP(seen_elems, 256);
|
||||
const u8 *ie;
|
||||
|
|
Загрузка…
Ссылка в новой задаче