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

John W. Linville says:

====================
This is another batch of fixes intended for the 3.11 stream.  FWIW,
this is the first request with fixes from the mac80211 and iwlwifi
trees as well.

Regarding the mac80211 bits, Johannes says:

"Here I have a fix for RSSI thresholds in mesh, two minstrel fixes from
Felix, an nl80211 fix from Michal and four various fixes I did myself."

As for the iwlwifi bits, Johannes says:

"Here I have a fix for debugfs directory creation (causing a spurious
error message), two scanning fixes from David Spinadel, an LED fix and
two patches related to a BA session problem that eventually caused
firmware crashes from Emmanuel and a small BT fix for older devices as
well as a workaround for a firmware problem with APs with very small
beacon intervals from myself."

Along with those:

Arend van Spriel addresses a lock-up and a NULL pointer dereference
in brcmfmac.

Daniel Drake fixes an unhandled interrupt during device tear down
in mwifiex.

Larry Finger corrects a wil6210 build error.

Oleksij Rempel fixes two ath9k_htc problems related to keeping the
driver and firmware in sync.

Solomon Peachy gives us a cw1200 fix to avoid an oops in monitor mode.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jul 25, 2013
2 parents deceb4c + 18e1ccb commit 1df86b4
Show file tree
Hide file tree
Showing 24 changed files with 184 additions and 87 deletions.
4 changes: 3 additions & 1 deletion drivers/net/wireless/ath/ath9k/hif_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1295,7 +1295,9 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)

usb_set_intfdata(interface, NULL);

if (!unplugged && (hif_dev->flags & HIF_USB_START))
/* If firmware was loaded we should drop it
* go back to first stage bootloader. */
if (!unplugged && (hif_dev->flags & HIF_USB_READY))
ath9k_hif_usb_reboot(udev);

kfree(hif_dev);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath9k/htc_drv_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
if (error != 0)
goto err_rx;

ath9k_hw_disable(priv->ah);
#ifdef CONFIG_MAC80211_LEDS
/* must be initialized before ieee80211_register_hw */
priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw,
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/ath/wil6210/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix,
le16_to_cpu(hdr.type), hdr.flags);
if (len <= MAX_MBOXITEM_SIZE) {
int n = 0;
unsigned char printbuf[16 * 3 + 2];
char printbuf[16 * 3 + 2];
unsigned char databuf[MAX_MBOXITEM_SIZE];
void __iomem *src = wmi_buffer(wil, d.addr) +
sizeof(struct wil6210_mbox_hdr);
Expand Down Expand Up @@ -416,7 +416,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
seq_printf(s, " SKB = %p\n", skb);

if (skb) {
unsigned char printbuf[16 * 3 + 2];
char printbuf[16 * 3 + 2];
int i = 0;
int len = le16_to_cpu(d->dma.length);
void *p = skb->data;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp,
{
unsigned long flags;

if (!ifp)
if (!ifp || !ifp->ndev)
return;

brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",
Expand Down
8 changes: 7 additions & 1 deletion drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1744,13 +1744,14 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
ulong flags;
int fifo = BRCMF_FWS_FIFO_BCMC;
bool multicast = is_multicast_ether_addr(eh->h_dest);
bool pae = eh->h_proto == htons(ETH_P_PAE);

/* determine the priority */
if (!skb->priority)
skb->priority = cfg80211_classify8021d(skb);

drvr->tx_multicast += !!multicast;
if (ntohs(eh->h_proto) == ETH_P_PAE)
if (pae)
atomic_inc(&ifp->pend_8021x_cnt);

if (!brcmf_fws_fc_active(fws)) {
Expand Down Expand Up @@ -1781,6 +1782,11 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
brcmf_fws_schedule_deq(fws);
} else {
brcmf_err("drop skb: no hanger slot\n");
if (pae) {
atomic_dec(&ifp->pend_8021x_cnt);
if (waitqueue_active(&ifp->pend_8021x_wait))
wake_up(&ifp->pend_8021x_wait);
}
brcmu_pkt_buf_free_skb(skb);
}
brcmf_fws_unlock(drvr, flags);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/cw1200/txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,7 @@ void cw1200_rx_cb(struct cw1200_common *priv,
if (cw1200_handle_action_rx(priv, skb))
return;
} else if (ieee80211_is_beacon(frame->frame_control) &&
!arg->status &&
!arg->status && priv->vif &&
!memcmp(ieee80211_get_SA(frame), priv->vif->bss_conf.bssid,
ETH_ALEN)) {
const u8 *tim_ie;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/dvm/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ int iwl_alive_start(struct iwl_priv *priv)
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret)
return ret;
} else {
} else if (priv->lib->bt_params) {
/*
* default is 2-wire BT coexexistence support
*/
Expand Down
6 changes: 5 additions & 1 deletion drivers/net/wireless/iwlwifi/mvm/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,11 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
char buf[100];

if (!dbgfs_dir)
/*
* Check if debugfs directory already exist before creating it.
* This may happen when, for example, resetting hw or suspend-resume
*/
if (!dbgfs_dir || mvmvif->dbgfs_dir)
return;

mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
Expand Down
23 changes: 22 additions & 1 deletion drivers/net/wireless/iwlwifi/mvm/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
if (ret)
return ret;

return ieee80211_register_hw(mvm->hw);
ret = ieee80211_register_hw(mvm->hw);
if (ret)
iwl_mvm_leds_exit(mvm);

return ret;
}

static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
Expand Down Expand Up @@ -385,6 +389,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
ieee80211_wake_queues(mvm->hw);

mvm->vif_count = 0;
mvm->rx_ba_sessions = 0;
}

static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
Expand Down Expand Up @@ -1006,6 +1011,21 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
if (old_state == IEEE80211_STA_NOTEXIST &&
new_state == IEEE80211_STA_NONE) {
/*
* Firmware bug - it'll crash if the beacon interval is less
* than 16. We can't avoid connecting at all, so refuse the
* station state change, this will cause mac80211 to abandon
* attempts to connect to this AP, and eventually wpa_s will
* blacklist the AP...
*/
if (vif->type == NL80211_IFTYPE_STATION &&
vif->bss_conf.beacon_int < 16) {
IWL_ERR(mvm,
"AP %pM beacon interval is %d, refusing due to firmware bug!\n",
sta->addr, vif->bss_conf.beacon_int);
ret = -EINVAL;
goto out_unlock;
}
ret = iwl_mvm_add_sta(mvm, vif, sta);
} else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_AUTH) {
Expand Down Expand Up @@ -1038,6 +1058,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
} else {
ret = -EIO;
}
out_unlock:
mutex_unlock(&mvm->mutex);

return ret;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/iwlwifi/mvm/mvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ struct iwl_mvm {
struct work_struct sta_drained_wk;
unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)];
atomic_t pending_frames[IWL_MVM_STATION_COUNT];
u8 rx_ba_sessions;

/* configured by mac80211 */
u32 rts_threshold;
Expand Down
10 changes: 6 additions & 4 deletions drivers/net/wireless/iwlwifi/mvm/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd,
{
int fw_idx, req_idx;

fw_idx = 0;
for (req_idx = req->n_ssids - 1; req_idx > 0; req_idx--) {
for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx > 0;
req_idx--, fw_idx++) {
cmd->direct_scan[fw_idx].id = WLAN_EID_SSID;
cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len;
memcpy(cmd->direct_scan[fw_idx].ssid,
Expand All @@ -153,7 +153,9 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd,
* just to notify that this scan is active and not passive.
* In order to notify the FW of the number of SSIDs we wish to scan (including
* the zero-length one), we need to set the corresponding bits in chan->type,
* one for each SSID, and set the active bit (first).
* one for each SSID, and set the active bit (first). The first SSID is already
* included in the probe template, so we need to set only req->n_ssids - 1 bits
* in addition to the first bit.
*/
static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids)
{
Expand All @@ -179,7 +181,7 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd,
__le32 chan_type_value;

if (req->n_ssids > 0)
chan_type_value = cpu_to_le32(BIT(req->n_ssids + 1) - 1);
chan_type_value = cpu_to_le32(BIT(req->n_ssids) - 1);
else
chan_type_value = SCAN_CHANNEL_TYPE_PASSIVE;

Expand Down
23 changes: 21 additions & 2 deletions drivers/net/wireless/iwlwifi/mvm/sta.c
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,8 @@ int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *bsta)
return ret;
}

#define IWL_MAX_RX_BA_SESSIONS 16

int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int tid, u16 ssn, bool start)
{
Expand All @@ -618,11 +620,20 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,

lockdep_assert_held(&mvm->mutex);

if (start && mvm->rx_ba_sessions >= IWL_MAX_RX_BA_SESSIONS) {
IWL_WARN(mvm, "Not enough RX BA SESSIONS\n");
return -ENOSPC;
}

cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
cmd.sta_id = mvm_sta->sta_id;
cmd.add_modify = STA_MODE_MODIFY;
cmd.add_immediate_ba_tid = (u8) tid;
cmd.add_immediate_ba_ssn = cpu_to_le16(ssn);
if (start) {
cmd.add_immediate_ba_tid = (u8) tid;
cmd.add_immediate_ba_ssn = cpu_to_le16(ssn);
} else {
cmd.remove_immediate_ba_tid = (u8) tid;
}
cmd.modify_mask = start ? STA_MODIFY_ADD_BA_TID :
STA_MODIFY_REMOVE_BA_TID;

Expand All @@ -648,6 +659,14 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
break;
}

if (!ret) {
if (start)
mvm->rx_ba_sessions++;
else if (mvm->rx_ba_sessions > 0)
/* check that restart flow didn't zero the counter */
mvm->rx_ba_sessions--;
}

return ret;
}

Expand Down
10 changes: 2 additions & 8 deletions drivers/net/wireless/mwifiex/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
if (!ret) {
dev_notice(adapter->dev,
"WLAN FW already running! Skip FW dnld\n");
goto done;
return 0;
}

poll_num = MAX_FIRMWARE_POLL_TRIES;
Expand All @@ -719,14 +719,8 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
poll_fw:
/* Check if the firmware is downloaded successfully or not */
ret = adapter->if_ops.check_fw_status(adapter, poll_num);
if (ret) {
if (ret)
dev_err(adapter->dev, "FW failed to be active in time\n");
return -1;
}
done:
/* re-enable host interrupt for mwifiex after fw dnld is successful */
if (adapter->if_ops.enable_int)
adapter->if_ops.enable_int(adapter);

return ret;
}
13 changes: 12 additions & 1 deletion drivers/net/wireless/mwifiex/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,10 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
"Cal data request_firmware() failed\n");
}

/* enable host interrupt after fw dnld is successful */
if (adapter->if_ops.enable_int)
adapter->if_ops.enable_int(adapter);

adapter->init_wait_q_woken = false;
ret = mwifiex_init_fw(adapter);
if (ret == -1) {
Expand Down Expand Up @@ -478,6 +482,8 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
rtnl_unlock();
err_init_fw:
if (adapter->if_ops.disable_int)
adapter->if_ops.disable_int(adapter);
pr_debug("info: %s: unregister device\n", __func__);
adapter->if_ops.unregister_dev(adapter);
done:
Expand Down Expand Up @@ -855,7 +861,7 @@ mwifiex_add_card(void *card, struct semaphore *sem,
INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);

/* Register the device. Fill up the private data structure with relevant
information from the card and request for the required IRQ. */
information from the card. */
if (adapter->if_ops.register_dev(adapter)) {
pr_err("%s: failed to register mwifiex device\n", __func__);
goto err_registerdev;
Expand Down Expand Up @@ -919,6 +925,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
if (!adapter)
goto exit_remove;

/* We can no longer handle interrupts once we start doing the teardown
* below. */
if (adapter->if_ops.disable_int)
adapter->if_ops.disable_int(adapter);

adapter->surprise_removed = true;

/* Stop data */
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/mwifiex/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ struct mwifiex_if_ops {
int (*register_dev) (struct mwifiex_adapter *);
void (*unregister_dev) (struct mwifiex_adapter *);
int (*enable_int) (struct mwifiex_adapter *);
void (*disable_int) (struct mwifiex_adapter *);
int (*process_int_status) (struct mwifiex_adapter *);
int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *,
struct mwifiex_tx_param *);
Expand Down
Loading

0 comments on commit 1df86b4

Please sign in to comment.