Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless

John W. Linville says:

====================
This is a batch of fixes intended for the 3.7 stream.

Dan Carpenter brings a fix for a simple signedness bug that could
prevent the proper termination of a loop.

Felix Fietkau found a few more places that need to use
ieee80211_free_txskb for properly releasing SKBs used by mac80211.

Franky Lin offers a pair of brcmfmac fixes, both fixing simple state
reporting errors.

Hante Meuleman corrects an error reporting case that wasn't handling
all types of errors properly.

Johan Hedberg offers a fix for an issue discovered at the Bluetooth
UnPlug Fest.  Gustavo says "the patch fixes a failure to pair with
devices that support the LE Secure Connections feature."

Johannes Berg sends an iwlwifi fix to handle a message type that
is too large for the normal command mechanism.  He also provides a
mac80211 fix to use HT20 channels when HT40 channels are not permitted.

Jouni Malinen offers a mac80211 fix for a masking error that was
incorrectly marking some frames.

Piotr Haber provides a fix to make sure bcma devices are unregistered
properly.

Stanislav Yakovlev gives us a fix for a panic in the ipw2200 driver.

Stanislaw Gruszka sends a pair of fixes: one prevents a mismatch on
connection states between cfg80211 and mac80211; the other prevents
some frame corruption related to handling encryption.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2012-10-21 20:57:37 -04:00
commit e6e71054cd
13 changed files with 99 additions and 95 deletions

View File

@ -158,9 +158,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
static void bcma_unregister_cores(struct bcma_bus *bus)
{
struct bcma_device *core;
struct bcma_device *core, *tmp;
list_for_each_entry(core, &bus->cores, list) {
list_for_each_entry_safe(core, tmp, &bus->cores, list) {
list_del(&core->list);
if (core->dev_registered)
device_unregister(&core->dev);
}

View File

@ -1339,7 +1339,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
}
ret = brcmf_bus_start(dev);
if (ret == -ENOLINK) {
if (ret) {
brcmf_dbg(ERROR, "dongle is not responding\n");
brcmf_detach(dev);
goto fail;

View File

@ -3972,7 +3972,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
u8 *iovar_ie_buf;
u8 *curr_ie_buf;
u8 *mgmt_ie_buf = NULL;
u32 mgmt_ie_buf_len = 0;
int mgmt_ie_buf_len;
u32 *mgmt_ie_len = 0;
u32 del_add_ie_buf_len = 0;
u32 total_ie_buf_len = 0;
@ -3982,7 +3982,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
struct parsed_vndr_ie_info *vndrie_info;
s32 i;
u8 *ptr;
u32 remained_buf_len;
int remained_buf_len;
WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag);
iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
@ -4606,12 +4606,13 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
struct brcmf_cfg80211_profile *profile = cfg->profile;
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
struct wiphy *wiphy = cfg_to_wiphy(cfg);
struct brcmf_channel_info_le channel_le;
struct ieee80211_channel *notify_channel;
struct ieee80211_channel *notify_channel = NULL;
struct ieee80211_supported_band *band;
struct brcmf_bss_info_le *bi;
u32 freq;
s32 err = 0;
u32 target_channel;
u8 *buf;
WL_TRACE("Enter\n");
@ -4619,11 +4620,22 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
memcpy(profile->bssid, e->addr, ETH_ALEN);
brcmf_update_bss_info(cfg);
brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
sizeof(channel_le));
buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
if (buf == NULL) {
err = -ENOMEM;
goto done;
}
target_channel = le32_to_cpu(channel_le.target_channel);
WL_CONN("Roamed to channel %d\n", target_channel);
/* data sent to dongle has to be little endian */
*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
if (err)
goto done;
bi = (struct brcmf_bss_info_le *)(buf + 4);
target_channel = bi->ctl_ch ? bi->ctl_ch :
CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
if (target_channel <= CH_MAX_2G_CHANNEL)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
@ -4633,6 +4645,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
freq = ieee80211_channel_to_frequency(target_channel, band->band);
notify_channel = ieee80211_get_channel(wiphy, freq);
done:
kfree(buf);
cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid,
conn_info->req_ie, conn_info->req_ie_len,
conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
@ -5186,41 +5200,6 @@ brcmf_cfg80211_event(struct net_device *ndev,
schedule_work(&cfg->event_work);
}
static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
{
s32 infra = 0;
s32 err = 0;
switch (iftype) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_WDS:
WL_ERR("type (%d) : currently we do not support this mode\n",
iftype);
err = -EINVAL;
return err;
case NL80211_IFTYPE_ADHOC:
infra = 0;
break;
case NL80211_IFTYPE_STATION:
infra = 1;
break;
case NL80211_IFTYPE_AP:
infra = 1;
break;
default:
err = -EINVAL;
WL_ERR("invalid type (%d)\n", iftype);
return err;
}
err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
if (err) {
WL_ERR("WLC_SET_INFRA error (%d)\n", err);
return err;
}
return 0;
}
static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
{
/* Room for "event_msgs" + '\0' + bitvec */
@ -5439,7 +5418,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
WL_BEACON_TIMEOUT);
if (err)
goto default_conf_out;
err = brcmf_dongle_mode(ndev, wdev->iftype);
err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
NULL, NULL);
if (err && err != -EINPROGRESS)
goto default_conf_out;
err = brcmf_dongle_probecap(cfg);

View File

@ -10472,7 +10472,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
} else
len = src->len;
dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC);
dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC);
if (!dst)
continue;

View File

@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
* See iwlagn_mac_channel_switch.
*/
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl6000_channel_switch_cmd cmd;
struct iwl6000_channel_switch_cmd *cmd;
u32 switch_time_in_usec, ucode_switch_time;
u16 ch;
u32 tsf_low;
@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
struct ieee80211_vif *vif = ctx->vif;
struct iwl_host_cmd hcmd = {
.id = REPLY_CHANNEL_SWITCH,
.len = { sizeof(cmd), },
.len = { sizeof(*cmd), },
.flags = CMD_SYNC,
.data = { &cmd, },
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
};
int err;
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
hcmd.data[0] = cmd;
cmd->band = priv->band == IEEE80211_BAND_2GHZ;
ch = ch_switch->channel->hw_value;
IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
ctx->active.channel, ch);
cmd.channel = cpu_to_le16(ch);
cmd.rxon_flags = ctx->staging.flags;
cmd.rxon_filter_flags = ctx->staging.filter_flags;
cmd->channel = cpu_to_le16(ch);
cmd->rxon_flags = ctx->staging.flags;
cmd->rxon_filter_flags = ctx->staging.filter_flags;
switch_count = ch_switch->count;
tsf_low = ch_switch->timestamp & 0x0ffffffff;
/*
@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
switch_count = 0;
}
if (switch_count <= 1)
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);
else {
switch_time_in_usec =
vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
ucode_switch_time = iwl_usecs_to_beacons(priv,
switch_time_in_usec,
beacon_interval);
cmd.switch_time = iwl_add_beacon_time(priv,
priv->ucode_beacon_time,
ucode_switch_time,
beacon_interval);
cmd->switch_time = iwl_add_beacon_time(priv,
priv->ucode_beacon_time,
ucode_switch_time,
beacon_interval);
}
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
cmd.switch_time);
cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
cmd->switch_time);
cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
return iwl_dvm_send_cmd(priv, &hcmd);
err = iwl_dvm_send_cmd(priv, &hcmd);
kfree(cmd);
return err;
}
struct iwl_lib_ops iwl6000_lib = {

View File

@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request {
const u8 *ie;
size_t ie_len;
u16 reason_code;
bool local_state_change;
};
/**

View File

@ -32,6 +32,8 @@
#define SMP_TIMEOUT msecs_to_jiffies(30000)
#define AUTH_REQ_MASK 0x07
static inline void swap128(u8 src[16], u8 dst[16])
{
int i;
@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
req->init_key_dist = 0;
req->resp_key_dist = dist_keys;
req->auth_req = authreq;
req->auth_req = (authreq & AUTH_REQ_MASK);
return;
}
@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
rsp->init_key_dist = 0;
rsp->resp_key_dist = req->resp_key_dist & dist_keys;
rsp->auth_req = authreq;
rsp->auth_req = (authreq & AUTH_REQ_MASK);
}
static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)

View File

@ -853,7 +853,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (info->control.vif == &sdata->vif) {
__skb_unlink(skb, &local->pending[i]);
dev_kfree_skb_irq(skb);
ieee80211_free_txskb(&local->hw, skb);
}
}
}

View File

@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
ht_cfreq, ht_oper->primary_chan,
cbss->channel->band);
ht_oper = NULL;
} else {
channel_type = NL80211_CHAN_HT20;
}
}
if (ht_oper) {
channel_type = NL80211_CHAN_HT20;
if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
/*
* cfg80211 already verified that the channel itself can
* be used, but it didn't check that we can do the right
* HT type, so do that here as well. If HT40 isn't allowed
* on this channel, disable 40 MHz operation.
*/
if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
switch (ht_oper->ht_param &
IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
else
channel_type = NL80211_CHAN_HT40PLUS;
break;
case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
break;
case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
else
channel_type = NL80211_CHAN_HT40MINUS;
break;
}
break;
}
}
@ -3549,6 +3559,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
bool tx = !req->local_state_change;
mutex_lock(&ifmgd->mtx);
@ -3565,12 +3576,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
if (ifmgd->associated &&
ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
req->reason_code, true, frame_buf);
req->reason_code, tx, frame_buf);
} else {
drv_mgd_prepare_tx(sdata->local, sdata);
ieee80211_send_deauth_disassoc(sdata, req->bssid,
IEEE80211_STYPE_DEAUTH,
req->reason_code, true,
req->reason_code, tx,
frame_buf);
}

View File

@ -650,7 +650,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,
*/
if (!skb)
break;
dev_kfree_skb(skb);
ieee80211_free_txskb(&local->hw, skb);
}
/*
@ -679,7 +679,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,
local->total_ps_buffered--;
ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n",
sta->sta.addr);
dev_kfree_skb(skb);
ieee80211_free_txskb(&local->hw, skb);
}
/*

View File

@ -406,7 +406,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
int queue = info->hw_queue;
if (WARN_ON(!info->control.vif)) {
kfree_skb(skb);
ieee80211_free_txskb(&local->hw, skb);
return;
}
@ -431,7 +431,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (WARN_ON(!info->control.vif)) {
kfree_skb(skb);
ieee80211_free_txskb(&local->hw, skb);
continue;
}

View File

@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
if (status->flag & RX_FLAG_MMIC_ERROR)
goto mic_fail;
if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key)
if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key &&
rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
goto update_iv;
return RX_CONTINUE;
@ -545,14 +546,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
static void bip_aad(struct sk_buff *skb, u8 *aad)
{
__le16 mask_fc;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
/* BIP AAD: FC(masked) || A1 || A2 || A3 */
/* FC type/subtype */
aad[0] = skb->data[0];
/* Mask FC Retry, PwrMgt, MoreData flags to zero */
aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6));
mask_fc = hdr->frame_control;
mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM |
IEEE80211_FCTL_MOREDATA);
put_unaligned(mask_fc, (__le16 *) &aad[0]);
/* A1 || A2 || A3 */
memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN);
memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN);
}

View File

@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
.reason_code = reason,
.ie = ie,
.ie_len = ie_len,
.local_state_change = local_state_change,
};
ASSERT_WDEV_LOCK(wdev);
if (local_state_change) {
if (wdev->current_bss &&
ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
cfg80211_unhold_bss(wdev->current_bss);
cfg80211_put_bss(&wdev->current_bss->pub);
wdev->current_bss = NULL;
}
if (local_state_change && (!wdev->current_bss ||
!ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
return 0;
}
return rdev->ops->deauth(&rdev->wiphy, dev, &req);
}