Skip to content

Commit

Permalink
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/linville/wireless into wireless

John W. Linville says:

====================
Here are some more fixes intended for the 3.9 stream...

Regarding the mac80211 bits, Johannes says:

"I had changed the idle handling to simplify it, but broken the
sequencing of commands, at least for ath9k-htc, one patch restores the
sequence. The other patch fixes a crash Jouni found while stress-testing
the remain-on-channel code, when an item is deleted the work struct can
run twice and crash the second time."

As for the iwlwifi bits, Johannes says:

"The only fix here is to the passive-no-RX firmware regulatory
enforcement driver support code to not drop auth frames in quick
succession, leading to not being able to connect to APs on passive
channels in certain circumstances."

Don't forget the NFC bits, about which Samuel says:

"This time we have:

- A crash fix for when a DGRAM LLCP socket is listening while the NFC adapter
  is physically removed.
- A potential double skb free when the LLCP socket receive queue is full.
- A fix for properly handling multiple and consecutive LLCP connections, and
  not trash the socket ack log.
- A build failure for the MEI microread physical layer, now that the MEI bus
  APIs have been merged into char-misc-next."

On top of that, Stone Piao provides an mwifiex fix to avoid accessing
beyond the end of a buffer.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 4, 2013
2 parents da241ef + 407ad2b commit 518314f
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 57 deletions.
18 changes: 8 additions & 10 deletions drivers/net/wireless/iwlwifi/dvm/rxon.c
Original file line number Diff line number Diff line change
Expand Up @@ -1419,6 +1419,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,

mutex_lock(&priv->mutex);

if (changes & BSS_CHANGED_IDLE && bss_conf->idle) {
/*
* If we go idle, then clearly no "passive-no-rx"
* workaround is needed any more, this is a reset.
*/
iwlagn_lift_passive_no_rx(priv);
}

if (unlikely(!iwl_is_ready(priv))) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
mutex_unlock(&priv->mutex);
Expand Down Expand Up @@ -1450,16 +1458,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
priv->timestamp = bss_conf->sync_tsf;
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
} else {
/*
* If we disassociate while there are pending
* frames, just wake up the queues and let the
* frames "escape" ... This shouldn't really
* be happening to start with, but we should
* not get stuck in this case either since it
* can happen if userspace gets confused.
*/
iwlagn_lift_passive_no_rx(priv);

ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;

if (ctx->ctxid == IWL_RXON_CTX_BSS)
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/dvm/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
memset(&info->status, 0, sizeof(info->status));

if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
iwl_is_associated_ctx(ctx) && ctx->vif &&
ctx->vif &&
ctx->vif->type == NL80211_IFTYPE_STATION) {
/* block and stop all queues */
priv->passive_no_rx = true;
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/mwifiex/cfg80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -1892,7 +1892,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
}
}

for (i = 0; i < request->n_channels; i++) {
for (i = 0; i < min_t(u32, request->n_channels,
MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
chan = request->channels[i];
priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
priv->user_scan_cfg->chan_list[i].radio_type = chan->band;
Expand Down
38 changes: 17 additions & 21 deletions drivers/nfc/microread/mei.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/mei_bus.h>
#include <linux/mei_cl_bus.h>

#include <linux/nfc.h>
#include <net/nfc/hci.h>
Expand All @@ -32,9 +32,6 @@

#define MICROREAD_DRIVER_NAME "microread"

#define MICROREAD_UUID UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, 0x94, \
0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c)

struct mei_nfc_hdr {
u8 cmd;
u8 status;
Expand All @@ -48,7 +45,7 @@ struct mei_nfc_hdr {
#define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)

struct microread_mei_phy {
struct mei_device *mei_device;
struct mei_cl_device *device;
struct nfc_hci_dev *hdev;

int powered;
Expand Down Expand Up @@ -105,30 +102,30 @@ static int microread_mei_write(void *phy_id, struct sk_buff *skb)

MEI_DUMP_SKB_OUT("mei frame sent", skb);

r = mei_send(phy->device, skb->data, skb->len);
r = mei_cl_send(phy->device, skb->data, skb->len);
if (r > 0)
r = 0;

return r;
}

static void microread_event_cb(struct mei_device *device, u32 events,
static void microread_event_cb(struct mei_cl_device *device, u32 events,
void *context)
{
struct microread_mei_phy *phy = context;

if (phy->hard_fault != 0)
return;

if (events & BIT(MEI_EVENT_RX)) {
if (events & BIT(MEI_CL_EVENT_RX)) {
struct sk_buff *skb;
int reply_size;

skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
if (!skb)
return;

reply_size = mei_recv(device, skb->data, MEI_NFC_MAX_READ);
reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ);
if (reply_size < MEI_NFC_HEADER_SIZE) {
kfree(skb);
return;
Expand All @@ -149,8 +146,8 @@ static struct nfc_phy_ops mei_phy_ops = {
.disable = microread_mei_disable,
};

static int microread_mei_probe(struct mei_device *device,
const struct mei_id *id)
static int microread_mei_probe(struct mei_cl_device *device,
const struct mei_cl_device_id *id)
{
struct microread_mei_phy *phy;
int r;
Expand All @@ -164,9 +161,9 @@ static int microread_mei_probe(struct mei_device *device,
}

phy->device = device;
mei_set_clientdata(device, phy);
mei_cl_set_drvdata(device, phy);

r = mei_register_event_cb(device, microread_event_cb, phy);
r = mei_cl_register_event_cb(device, microread_event_cb, phy);
if (r) {
pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n");
goto err_out;
Expand All @@ -186,9 +183,9 @@ static int microread_mei_probe(struct mei_device *device,
return r;
}

static int microread_mei_remove(struct mei_device *device)
static int microread_mei_remove(struct mei_cl_device *device)
{
struct microread_mei_phy *phy = mei_get_clientdata(device);
struct microread_mei_phy *phy = mei_cl_get_drvdata(device);

pr_info("Removing microread\n");

Expand All @@ -202,16 +199,15 @@ static int microread_mei_remove(struct mei_device *device)
return 0;
}

static struct mei_id microread_mei_tbl[] = {
{ MICROREAD_DRIVER_NAME, MICROREAD_UUID },
static struct mei_cl_device_id microread_mei_tbl[] = {
{ MICROREAD_DRIVER_NAME },

/* required last entry */
{ }
};

MODULE_DEVICE_TABLE(mei, microread_mei_tbl);

static struct mei_driver microread_driver = {
static struct mei_cl_driver microread_driver = {
.id_table = microread_mei_tbl,
.name = MICROREAD_DRIVER_NAME,

Expand All @@ -225,7 +221,7 @@ static int microread_mei_init(void)

pr_debug(DRIVER_DESC ": %s\n", __func__);

r = mei_driver_register(&microread_driver);
r = mei_cl_driver_register(&microread_driver);
if (r) {
pr_err(MICROREAD_DRIVER_NAME ": driver registration failed\n");
return r;
Expand All @@ -236,7 +232,7 @@ static int microread_mei_init(void)

static void microread_mei_exit(void)
{
mei_driver_unregister(&microread_driver);
mei_cl_driver_unregister(&microread_driver);
}

module_init(microread_mei_init);
Expand Down
6 changes: 4 additions & 2 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2582,7 +2582,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
list_del(&dep->list);
mutex_unlock(&local->mtx);

ieee80211_roc_notify_destroy(dep);
ieee80211_roc_notify_destroy(dep, true);
return 0;
}

Expand Down Expand Up @@ -2622,7 +2622,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
ieee80211_start_next_roc(local);
mutex_unlock(&local->mtx);

ieee80211_roc_notify_destroy(found);
ieee80211_roc_notify_destroy(found, true);
} else {
/* work may be pending so use it all the time */
found->abort = true;
Expand All @@ -2632,6 +2632,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,

/* work will clean up etc */
flush_delayed_work(&found->work);
WARN_ON(!found->to_be_freed);
kfree(found);
}

return 0;
Expand Down
17 changes: 14 additions & 3 deletions net/mac80211/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
enum ieee80211_chanctx_mode mode)
{
struct ieee80211_chanctx *ctx;
u32 changed;
int err;

lockdep_assert_held(&local->chanctx_mtx);
Expand All @@ -76,6 +77,13 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
ctx->conf.rx_chains_dynamic = 1;
ctx->mode = mode;

/* acquire mutex to prevent idle from changing */
mutex_lock(&local->mtx);
/* turn idle off *before* setting channel -- some drivers need that */
changed = ieee80211_idle_off(local);
if (changed)
ieee80211_hw_config(local, changed);

if (!local->use_chanctx) {
local->_oper_channel_type =
cfg80211_get_chandef_type(chandef);
Expand All @@ -85,14 +93,17 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
err = drv_add_chanctx(local, ctx);
if (err) {
kfree(ctx);
return ERR_PTR(err);
ctx = ERR_PTR(err);

ieee80211_recalc_idle(local);
goto out;
}
}

/* and keep the mutex held until the new chanctx is on the list */
list_add_rcu(&ctx->list, &local->chanctx_list);

mutex_lock(&local->mtx);
ieee80211_recalc_idle(local);
out:
mutex_unlock(&local->mtx);

return ctx;
Expand Down
4 changes: 3 additions & 1 deletion net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ struct ieee80211_roc_work {
struct ieee80211_channel *chan;

bool started, abort, hw_begun, notified;
bool to_be_freed;

unsigned long hw_start_time;

Expand Down Expand Up @@ -1347,7 +1348,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local);
void ieee80211_roc_setup(struct ieee80211_local *local);
void ieee80211_start_next_roc(struct ieee80211_local *local);
void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc);
void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free);
void ieee80211_sw_roc_work(struct work_struct *work);
void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);

Expand All @@ -1361,6 +1362,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
enum nl80211_iftype type);
void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
void ieee80211_remove_interfaces(struct ieee80211_local *local);
u32 ieee80211_idle_off(struct ieee80211_local *local);
void ieee80211_recalc_idle(struct ieee80211_local *local);
void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
const int offset);
Expand Down
2 changes: 1 addition & 1 deletion net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
}

static u32 ieee80211_idle_off(struct ieee80211_local *local)
u32 ieee80211_idle_off(struct ieee80211_local *local)
{
if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
return 0;
Expand Down
23 changes: 17 additions & 6 deletions net/mac80211/offchannel.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,13 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
}
}

void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free)
{
struct ieee80211_roc_work *dep, *tmp;

if (WARN_ON(roc->to_be_freed))
return;

/* was never transmitted */
if (roc->frame) {
cfg80211_mgmt_tx_status(&roc->sdata->wdev,
Expand All @@ -316,9 +319,12 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
GFP_KERNEL);

list_for_each_entry_safe(dep, tmp, &roc->dependents, list)
ieee80211_roc_notify_destroy(dep);
ieee80211_roc_notify_destroy(dep, true);

kfree(roc);
if (free)
kfree(roc);
else
roc->to_be_freed = true;
}

void ieee80211_sw_roc_work(struct work_struct *work)
Expand All @@ -331,6 +337,9 @@ void ieee80211_sw_roc_work(struct work_struct *work)

mutex_lock(&local->mtx);

if (roc->to_be_freed)
goto out_unlock;

if (roc->abort)
goto finish;

Expand Down Expand Up @@ -370,7 +379,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
finish:
list_del(&roc->list);
started = roc->started;
ieee80211_roc_notify_destroy(roc);
ieee80211_roc_notify_destroy(roc, !roc->abort);

if (started) {
drv_flush(local, false);
Expand Down Expand Up @@ -410,7 +419,7 @@ static void ieee80211_hw_roc_done(struct work_struct *work)

list_del(&roc->list);

ieee80211_roc_notify_destroy(roc);
ieee80211_roc_notify_destroy(roc, true);

/* if there's another roc, start it now */
ieee80211_start_next_roc(local);
Expand Down Expand Up @@ -460,12 +469,14 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
if (local->ops->remain_on_channel) {
list_del(&roc->list);
ieee80211_roc_notify_destroy(roc);
ieee80211_roc_notify_destroy(roc, true);
} else {
ieee80211_queue_delayed_work(&local->hw, &roc->work, 0);

/* work will clean up etc */
flush_delayed_work(&roc->work);
WARN_ON(!roc->to_be_freed);
kfree(roc);
}
}

Expand Down
Loading

0 comments on commit 518314f

Please sign in to comment.