Commit 1df86b4c authored by David S. Miller's avatar David S. Miller

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/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: default avatarDavid S. Miller <davem@davemloft.net>
parents deceb4c0 18e1ccb6
...@@ -1295,7 +1295,9 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) ...@@ -1295,7 +1295,9 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
usb_set_intfdata(interface, NULL); 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); ath9k_hif_usb_reboot(udev);
kfree(hif_dev); kfree(hif_dev);
......
...@@ -861,6 +861,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, ...@@ -861,6 +861,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
if (error != 0) if (error != 0)
goto err_rx; goto err_rx;
ath9k_hw_disable(priv->ah);
#ifdef CONFIG_MAC80211_LEDS #ifdef CONFIG_MAC80211_LEDS
/* must be initialized before ieee80211_register_hw */ /* must be initialized before ieee80211_register_hw */
priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw, priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw,
......
...@@ -145,7 +145,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, ...@@ -145,7 +145,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix,
le16_to_cpu(hdr.type), hdr.flags); le16_to_cpu(hdr.type), hdr.flags);
if (len <= MAX_MBOXITEM_SIZE) { if (len <= MAX_MBOXITEM_SIZE) {
int n = 0; int n = 0;
unsigned char printbuf[16 * 3 + 2]; char printbuf[16 * 3 + 2];
unsigned char databuf[MAX_MBOXITEM_SIZE]; unsigned char databuf[MAX_MBOXITEM_SIZE];
void __iomem *src = wmi_buffer(wil, d.addr) + void __iomem *src = wmi_buffer(wil, d.addr) +
sizeof(struct wil6210_mbox_hdr); sizeof(struct wil6210_mbox_hdr);
...@@ -416,7 +416,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) ...@@ -416,7 +416,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
seq_printf(s, " SKB = %p\n", skb); seq_printf(s, " SKB = %p\n", skb);
if (skb) { if (skb) {
unsigned char printbuf[16 * 3 + 2]; char printbuf[16 * 3 + 2];
int i = 0; int i = 0;
int len = le16_to_cpu(d->dma.length); int len = le16_to_cpu(d->dma.length);
void *p = skb->data; void *p = skb->data;
......
...@@ -242,7 +242,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, ...@@ -242,7 +242,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp,
{ {
unsigned long flags; unsigned long flags;
if (!ifp) if (!ifp || !ifp->ndev)
return; return;
brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n", brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",
......
...@@ -1744,13 +1744,14 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) ...@@ -1744,13 +1744,14 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
ulong flags; ulong flags;
int fifo = BRCMF_FWS_FIFO_BCMC; int fifo = BRCMF_FWS_FIFO_BCMC;
bool multicast = is_multicast_ether_addr(eh->h_dest); bool multicast = is_multicast_ether_addr(eh->h_dest);
bool pae = eh->h_proto == htons(ETH_P_PAE);
/* determine the priority */ /* determine the priority */
if (!skb->priority) if (!skb->priority)
skb->priority = cfg80211_classify8021d(skb); skb->priority = cfg80211_classify8021d(skb);
drvr->tx_multicast += !!multicast; drvr->tx_multicast += !!multicast;
if (ntohs(eh->h_proto) == ETH_P_PAE) if (pae)
atomic_inc(&ifp->pend_8021x_cnt); atomic_inc(&ifp->pend_8021x_cnt);
if (!brcmf_fws_fc_active(fws)) { if (!brcmf_fws_fc_active(fws)) {
...@@ -1781,6 +1782,11 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) ...@@ -1781,6 +1782,11 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
brcmf_fws_schedule_deq(fws); brcmf_fws_schedule_deq(fws);
} else { } else {
brcmf_err("drop skb: no hanger slot\n"); 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); brcmu_pkt_buf_free_skb(skb);
} }
brcmf_fws_unlock(drvr, flags); brcmf_fws_unlock(drvr, flags);
......
...@@ -1165,7 +1165,7 @@ void cw1200_rx_cb(struct cw1200_common *priv, ...@@ -1165,7 +1165,7 @@ void cw1200_rx_cb(struct cw1200_common *priv,
if (cw1200_handle_action_rx(priv, skb)) if (cw1200_handle_action_rx(priv, skb))
return; return;
} else if (ieee80211_is_beacon(frame->frame_control) && } else if (ieee80211_is_beacon(frame->frame_control) &&
!arg->status && !arg->status && priv->vif &&
!memcmp(ieee80211_get_SA(frame), priv->vif->bss_conf.bssid, !memcmp(ieee80211_get_SA(frame), priv->vif->bss_conf.bssid,
ETH_ALEN)) { ETH_ALEN)) {
const u8 *tim_ie; const u8 *tim_ie;
......
...@@ -758,7 +758,7 @@ int iwl_alive_start(struct iwl_priv *priv) ...@@ -758,7 +758,7 @@ int iwl_alive_start(struct iwl_priv *priv)
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret) if (ret)
return ret; return ret;
} else { } else if (priv->lib->bt_params) {
/* /*
* default is 2-wire BT coexexistence support * default is 2-wire BT coexexistence support
*/ */
......
...@@ -988,7 +988,11 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -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); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
char buf[100]; 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; return;
mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir); mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
......
...@@ -257,7 +257,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -257,7 +257,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
if (ret) if (ret)
return 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, static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
...@@ -385,6 +389,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) ...@@ -385,6 +389,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
ieee80211_wake_queues(mvm->hw); ieee80211_wake_queues(mvm->hw);
mvm->vif_count = 0; mvm->vif_count = 0;
mvm->rx_ba_sessions = 0;
} }
static int iwl_mvm_mac_start(struct ieee80211_hw *hw) static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
...@@ -1006,6 +1011,21 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, ...@@ -1006,6 +1011,21 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
if (old_state == IEEE80211_STA_NOTEXIST && if (old_state == IEEE80211_STA_NOTEXIST &&
new_state == IEEE80211_STA_NONE) { 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); ret = iwl_mvm_add_sta(mvm, vif, sta);
} else if (old_state == IEEE80211_STA_NONE && } else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_AUTH) { new_state == IEEE80211_STA_AUTH) {
...@@ -1038,6 +1058,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, ...@@ -1038,6 +1058,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
} else { } else {
ret = -EIO; ret = -EIO;
} }
out_unlock:
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
return ret; return ret;
......
...@@ -419,6 +419,7 @@ struct iwl_mvm { ...@@ -419,6 +419,7 @@ struct iwl_mvm {
struct work_struct sta_drained_wk; struct work_struct sta_drained_wk;
unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)]; unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)];
atomic_t pending_frames[IWL_MVM_STATION_COUNT]; atomic_t pending_frames[IWL_MVM_STATION_COUNT];
u8 rx_ba_sessions;
/* configured by mac80211 */ /* configured by mac80211 */
u32 rts_threshold; u32 rts_threshold;
......
...@@ -137,8 +137,8 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd, ...@@ -137,8 +137,8 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd,
{ {
int fw_idx, req_idx; int fw_idx, req_idx;
fw_idx = 0; for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx > 0;
for (req_idx = req->n_ssids - 1; req_idx > 0; req_idx--) { req_idx--, fw_idx++) {
cmd->direct_scan[fw_idx].id = WLAN_EID_SSID; cmd->direct_scan[fw_idx].id = WLAN_EID_SSID;
cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len; cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len;
memcpy(cmd->direct_scan[fw_idx].ssid, memcpy(cmd->direct_scan[fw_idx].ssid,
...@@ -153,7 +153,9 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd, ...@@ -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. * 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 * 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, * 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) static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids)
{ {
...@@ -179,7 +181,7 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, ...@@ -179,7 +181,7 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd,
__le32 chan_type_value; __le32 chan_type_value;
if (req->n_ssids > 0) 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 else
chan_type_value = SCAN_CHANNEL_TYPE_PASSIVE; chan_type_value = SCAN_CHANNEL_TYPE_PASSIVE;
......
...@@ -608,6 +608,8 @@ int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *bsta) ...@@ -608,6 +608,8 @@ int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *bsta)
return ret; return ret;
} }
#define IWL_MAX_RX_BA_SESSIONS 16
int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int tid, u16 ssn, bool start) int tid, u16 ssn, bool start)
{ {
...@@ -618,11 +620,20 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -618,11 +620,20 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
lockdep_assert_held(&mvm->mutex); 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.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
cmd.sta_id = mvm_sta->sta_id; cmd.sta_id = mvm_sta->sta_id;
cmd.add_modify = STA_MODE_MODIFY; cmd.add_modify = STA_MODE_MODIFY;
if (start) {
cmd.add_immediate_ba_tid = (u8) tid; cmd.add_immediate_ba_tid = (u8) tid;
cmd.add_immediate_ba_ssn = cpu_to_le16(ssn); 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 : cmd.modify_mask = start ? STA_MODIFY_ADD_BA_TID :
STA_MODIFY_REMOVE_BA_TID; STA_MODIFY_REMOVE_BA_TID;
...@@ -648,6 +659,14 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -648,6 +659,14 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
break; 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; return ret;
} }
......
...@@ -693,7 +693,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, ...@@ -693,7 +693,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
if (!ret) { if (!ret) {
dev_notice(adapter->dev, dev_notice(adapter->dev,
"WLAN FW already running! Skip FW dnld\n"); "WLAN FW already running! Skip FW dnld\n");
goto done; return 0;
} }
poll_num = MAX_FIRMWARE_POLL_TRIES; poll_num = MAX_FIRMWARE_POLL_TRIES;
...@@ -719,14 +719,8 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, ...@@ -719,14 +719,8 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
poll_fw: poll_fw:
/* Check if the firmware is downloaded successfully or not */ /* Check if the firmware is downloaded successfully or not */
ret = adapter->if_ops.check_fw_status(adapter, poll_num); 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"); 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; return ret;
} }
...@@ -427,6 +427,10 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) ...@@ -427,6 +427,10 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
"Cal data request_firmware() failed\n"); "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; adapter->init_wait_q_woken = false;
ret = mwifiex_init_fw(adapter); ret = mwifiex_init_fw(adapter);
if (ret == -1) { if (ret == -1) {
...@@ -478,6 +482,8 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) ...@@ -478,6 +482,8 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev); mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
rtnl_unlock(); rtnl_unlock();
err_init_fw: err_init_fw:
if (adapter->if_ops.disable_int)
adapter->if_ops.disable_int(adapter);
pr_debug("info: %s: unregister device\n", __func__); pr_debug("info: %s: unregister device\n", __func__);
adapter->if_ops.unregister_dev(adapter); adapter->if_ops.unregister_dev(adapter);
done: done:
...@@ -855,7 +861,7 @@ mwifiex_add_card(void *card, struct semaphore *sem, ...@@ -855,7 +861,7 @@ mwifiex_add_card(void *card, struct semaphore *sem,
INIT_WORK(&adapter->main_work, mwifiex_main_work_queue); INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
/* Register the device. Fill up the private data structure with relevant /* 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)) { if (adapter->if_ops.register_dev(adapter)) {
pr_err("%s: failed to register mwifiex device\n", __func__); pr_err("%s: failed to register mwifiex device\n", __func__);
goto err_registerdev; goto err_registerdev;
...@@ -919,6 +925,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) ...@@ -919,6 +925,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
if (!adapter) if (!adapter)
goto exit_remove; 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; adapter->surprise_removed = true;
/* Stop data */ /* Stop data */
......
...@@ -601,6 +601,7 @@ struct mwifiex_if_ops { ...@@ -601,6 +601,7 @@ struct mwifiex_if_ops {
int (*register_dev) (struct mwifiex_adapter *); int (*register_dev) (struct mwifiex_adapter *);
void (*unregister_dev) (struct mwifiex_adapter *); void (*unregister_dev) (struct mwifiex_adapter *);
int (*enable_int) (struct mwifiex_adapter *); int (*enable_int) (struct mwifiex_adapter *);
void (*disable_int) (struct mwifiex_adapter *);
int (*process_int_status) (struct mwifiex_adapter *); int (*process_int_status) (struct mwifiex_adapter *);
int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *, int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *,
struct mwifiex_tx_param *); struct mwifiex_tx_param *);
......
...@@ -51,6 +51,7 @@ static struct mwifiex_if_ops sdio_ops; ...@@ -51,6 +51,7 @@ static struct mwifiex_if_ops sdio_ops;
static struct semaphore add_remove_card_sem; static struct semaphore add_remove_card_sem;
static int mwifiex_sdio_resume(struct device *dev); static int mwifiex_sdio_resume(struct device *dev);
static void mwifiex_sdio_interrupt(struct sdio_func *func);
/* /*
* SDIO probe. * SDIO probe.
...@@ -296,6 +297,15 @@ static struct sdio_driver mwifiex_sdio = { ...@@ -296,6 +297,15 @@ static struct sdio_driver mwifiex_sdio = {
} }
}; };
/* Write data into SDIO card register. Caller claims SDIO device. */
static int
mwifiex_write_reg_locked(struct sdio_func *func, u32 reg, u8 data)
{
int ret = -1;
sdio_writeb(func, data, reg, &ret);
return ret;
}
/* /*
* This function writes data into SDIO card register. * This function writes data into SDIO card register.
*/ */
...@@ -303,10 +313,10 @@ static int ...@@ -303,10 +313,10 @@ static int
mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data) mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data)
{ {
struct sdio_mmc_card *card = adapter->card; struct sdio_mmc_card *card = adapter->card;
int ret = -1; int ret;
sdio_claim_host(card->func); sdio_claim_host(card->func);
sdio_writeb(card->func, data, reg, &ret); ret = mwifiex_write_reg_locked(card->func, reg, data);
sdio_release_host(card->func); sdio_release_host(card->func);
return ret; return ret;
...@@ -685,23 +695,15 @@ mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) ...@@ -685,23 +695,15 @@ mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat)
* The host interrupt mask is read, the disable bit is reset and * The host interrupt mask is read, the disable bit is reset and
* written back to the card host interrupt mask register. * written back to the card host interrupt mask register.
*/ */
static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) static void mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter)
{ {
u8 host_int_mask, host_int_disable = HOST_INT_DISABLE; struct sdio_mmc_card *card = adapter->card;
struct sdio_func *func = card->func;
/* Read back the host_int_mask register */
if (mwifiex_read_reg(adapter, HOST_INT_MASK_REG, &host_int_mask))
return -1;
/* Update with the mask and write back to the register */
host_int_mask &= ~host_int_disable;
if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, host_int_mask)) {
dev_err(adapter->dev, "disable host interrupt failed\n");
return -1;
}
return 0; sdio_claim_host(func);
mwifiex_write_reg_locked(func, HOST_INT_MASK_REG, 0);
sdio_release_irq(func);
sdio_release_host(func);
} }
/* /*
...@@ -713,14 +715,29 @@ static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) ...@@ -713,14 +715,29 @@ static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter)
static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter) static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter)
{ {
struct sdio_mmc_card *card = adapter->card; struct sdio_mmc_card *card = adapter->card;
struct sdio_func *func = card->func;
int ret;
sdio_claim_host(func);
/* Request the SDIO IRQ */
ret = sdio_claim_irq(func, mwifiex_sdio_interrupt);
if (ret) {
dev_err(adapter->dev, "claim irq failed: ret=%d\n", ret);
goto out;
}
/* Simply write the mask to the register */ /* Simply write the mask to the register */
if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, ret = mwifiex_write_reg_locked(func, HOST_INT_MASK_REG,
card->reg->host_int_enable)) { card->reg->host_int_enable);
if (ret) {
dev_err(adapter->dev, "enable host interrupt failed\n"); dev_err(adapter->dev, "enable host interrupt failed\n");
return -1; sdio_release_irq(func);
} }
return 0;
out:
sdio_release_host(func);
return ret;
} }
/* /*
...@@ -997,9 +1014,6 @@ mwifiex_sdio_interrupt(struct sdio_func *func) ...@@ -997,9 +1014,6 @@ mwifiex_sdio_interrupt(struct sdio_func *func)
} }
adapter = card->adapter; adapter = card->adapter;
if (adapter->surprise_removed)
return;
if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP) if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP)
adapter->ps_state = PS_STATE_AWAKE; adapter->ps_state = PS_STATE_AWAKE;
...@@ -1728,9 +1742,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter) ...@@ -1728,9 +1742,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
struct sdio_mmc_card *card = adapter->card; struct sdio_mmc_card *card = adapter->card;
if (adapter->card) { if (adapter->card) {
/* Release the SDIO IRQ */
sdio_claim_host(card->func); sdio_claim_host(card->func);
sdio_release_irq(card->func);
sdio_disable_func(card->func); sdio_disable_func(card->func);
sdio_release_host(card->func); sdio_release_host(card->func);
sdio_set_drvdata(card->func, NULL); sdio_set_drvdata(card->func, NULL);
...@@ -1744,7 +1756,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter) ...@@ -1744,7 +1756,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
*/ */
static int mwifiex_register_dev(struct mwifiex_adapter *adapter) static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
{ {
int ret = 0; int ret;
struct sdio_mmc_card *card = adapter->card; struct sdio_mmc_card *card = adapter->card;
struct sdio_func *func = card->func; struct sdio_func *func = card->func;
...@@ -1753,22 +1765,14 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) ...@@ -1753,22 +1765,14 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
sdio_claim_host(func); sdio_claim_host(func);
/* Request the SDIO IRQ */
ret = sdio_claim_irq(func, mwifiex_sdio_interrupt);
if (ret) {
pr_err("claim irq failed: ret=%d\n", ret);
goto disable_func;
}
/* Set block size */ /* Set block size */
ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE); ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE);
sdio_release_host(func);
if (ret) { if (ret) {
pr_err("cannot set SDIO block size\n"); pr_err("cannot set SDIO block size\n");
ret = -1; return ret;
goto release_irq;
} }
sdio_release_host(func);
sdio_set_drvdata(func, card); sdio_set_drvdata(func, card);
adapter->dev = &func->dev; adapter->dev = &func->dev;
...@@ -1776,15 +1780,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) ...@@ -1776,15 +1780,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
strcpy(adapter->fw_name, card->firmware); strcpy(adapter->fw_name, card->firmware);
return 0; return 0;
release_irq:
sdio_release_irq(func);
disable_func:
sdio_disable_func(func);
sdio_release_host(func);
adapter->card = NULL;
return -1;
} }
/* /*
...@@ -1813,9 +1808,6 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) ...@@ -1813,9 +1808,6 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
*/ */
mwifiex_read_reg(adapter, HOST_INTSTATUS_REG, &sdio_ireg); mwifiex_read_reg(adapter, HOST_INTSTATUS_REG, &sdio_ireg);
/* Disable host interrupt mask register for SDIO */
mwifiex_sdio_disable_host_int(adapter);
/* Get SDIO ioport */ /* Get SDIO ioport */
mwifiex_init_sdio_ioport(adapter); mwifiex_init_sdio_ioport(adapter);
...@@ -1957,6 +1949,7 @@ static struct mwifiex_if_ops sdio_ops = { ...@@ -1957,6 +1949,7 @@ static struct mwifiex_if_ops sdio_ops = {
.register_dev = mwifiex_register_dev, .register_dev = mwifiex_register_dev,
.unregister_dev = mwifiex_unregister_dev, .unregister_dev = mwifiex_unregister_dev,
.enable_int = mwifiex_sdio_enable_host_int, .enable_int = mwifiex_sdio_enable_host_int,
.disable_int = mwifiex_sdio_disable_host_int,
.process_int_status = mwifiex_process_int_status, .process_int_status = mwifiex_process_int_status,
.host_to_card = mwifiex_sdio_host_to_card, .host_to_card = mwifiex_sdio_host_to_card,
.wakeup = mwifiex_pm_wakeup_card, .wakeup = mwifiex_pm_wakeup_card,
......
...@@ -92,9 +92,6 @@ ...@@ -92,9 +92,6 @@
/* Host Control Registers : Download host interrupt mask */ /* Host Control Registers : Download host interrupt mask */
#define DN_LD_HOST_INT_MASK (0x2U) #define DN_LD_HOST_INT_MASK (0x2U)
/* Disable Host interrupt mask */
#define HOST_INT_DISABLE 0xff
/* Host Control Registers : Host interrupt status */ /* Host Control Registers : Host interrupt status */
#define HOST_INTSTATUS_REG 0x03 #define HOST_INTSTATUS_REG 0x03
/* Host Control Registers : Upload host interrupt status */ /* Host Control Registers : Upload host interrupt status */
......
...@@ -666,6 +666,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, ...@@ -666,6 +666,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
if (sta->sdata->dev != dev) if (sta->sdata->dev != dev)
continue; continue;
sinfo.filled = 0;
sta_set_sinfo(sta, &sinfo);
i = 0; i = 0;
ADD_STA_STATS(sta); ADD_STA_STATS(sta);
} }
......
...@@ -290,7 +290,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, ...@@ -290,7 +290,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
struct minstrel_rate *msr, *mr; struct minstrel_rate *msr, *mr;
unsigned int ndx; unsigned int ndx;
bool mrr_capable; bool mrr_capable;
bool prev_sample = mi->prev_sample; bool prev_sample;
int delta; int delta;
int sampling_ratio; int sampling_ratio;
...@@ -314,6 +314,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, ...@@ -314,6 +314,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
(mi->sample_count + mi->sample_deferred / 2); (mi->sample_count + mi->sample_deferred / 2);
/* delta < 0: no sampling required */ /* delta < 0: no sampling required */
prev_sample = mi->prev_sample;
mi->prev_sample = false; mi->prev_sample = false;
if (delta < 0 || (!mrr_capable && prev_sample)) if (delta < 0 || (!mrr_capable && prev_sample))
return; return;
......
...@@ -804,10 +804,18 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, ...@@ -804,10 +804,18 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES]; sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
rate->count = 1;
if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
rate->idx = mp->cck_rates[idx];
rate->flags = 0;
return;
}
rate->idx = sample_idx % MCS_GROUP_RATES + rate->idx = sample_idx % MCS_GROUP_RATES +
(sample_group->streams - 1) * MCS_GROUP_RATES; (sample_group->streams - 1) * MCS_GROUP_RATES;
rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags; rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
rate->count = 1;
} }
static void static void
......
...@@ -936,8 +936,14 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) ...@@ -936,8 +936,14 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
/* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ /*
if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { * Drop duplicate 802.11 retransmissions
* (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
*/
if (rx->skb->len >= 24 && rx->sta &&
!ieee80211_is_ctl(hdr->frame_control) &&
!ieee80211_is_qos_nullfunc(hdr->frame_control) &&
!is_multicast_ether_addr(hdr->addr1)) {
if (unlikely(ieee80211_has_retry(hdr->frame_control) && if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
rx->sta->last_seq_ctrl[rx->seqno_idx] == rx->sta->last_seq_ctrl[rx->seqno_idx] ==
hdr->seq_ctrl)) { hdr->seq_ctrl)) {
......
...@@ -4770,9 +4770,9 @@ do { \ ...@@ -4770,9 +4770,9 @@ do { \
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1, FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1,
mask, NL80211_MESHCONF_FORWARDING, mask, NL80211_MESHCONF_FORWARDING,
nla_get_u8); nla_get_u8);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, 1, 255, FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,
mask, NL80211_MESHCONF_RSSI_THRESHOLD, mask, NL80211_MESHCONF_RSSI_THRESHOLD,
nla_get_u32); nla_get_s32);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16, FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16,
mask, NL80211_MESHCONF_HT_OPMODE, mask, NL80211_MESHCONF_HT_OPMODE,
nla_get_u16); nla_get_u16);
...@@ -6613,12 +6613,14 @@ EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb); ...@@ -6613,12 +6613,14 @@ EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb);
void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
{ {
struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
void *hdr = ((void **)skb->cb)[1]; void *hdr = ((void **)skb->cb)[1];
struct nlattr *data = ((void **)skb->cb)[2]; struct nlattr *data = ((void **)skb->cb)[2];
nla_nest_end(skb, data); nla_nest_end(skb, data);
genlmsg_end(skb, hdr); genlmsg_end(skb, hdr);
genlmsg_multicast(skb, 0, nl80211_testmode_mcgrp.id, gfp); genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), skb, 0,
nl80211_testmode_mcgrp.id, gfp);
} }
EXPORT_SYMBOL(cfg80211_testmode_event); EXPORT_SYMBOL(cfg80211_testmode_event);
#endif #endif
...@@ -10064,7 +10066,8 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, ...@@ -10064,7 +10066,8 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
genlmsg_end(msg, hdr); genlmsg_end(msg, hdr);
genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return; return;
nla_put_failure: nla_put_failure:
......
...@@ -2279,7 +2279,9 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy) ...@@ -2279,7 +2279,9 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy)
static void reg_timeout_work(struct work_struct *work) static void reg_timeout_work(struct work_struct *work)
{ {
REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n"); REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n");
rtnl_lock();
restore_regulatory_settings(true); restore_regulatory_settings(true);
rtnl_unlock();
} }
int __init regulatory_init(void) int __init regulatory_init(void)
......
...@@ -34,8 +34,10 @@ struct cfg80211_conn { ...@@ -34,8 +34,10 @@ struct cfg80211_conn {
CFG80211_CONN_SCAN_AGAIN, CFG80211_CONN_SCAN_AGAIN,
CFG80211_CONN_AUTHENTICATE_NEXT, CFG80211_CONN_AUTHENTICATE_NEXT,
CFG80211_CONN_AUTHENTICATING, CFG80211_CONN_AUTHENTICATING,
CFG80211_CONN_AUTH_FAILED,
CFG80211_CONN_ASSOCIATE_NEXT, CFG80211_CONN_ASSOCIATE_NEXT,
CFG80211_CONN_ASSOCIATING, CFG80211_CONN_ASSOCIATING,
CFG80211_CONN_ASSOC_FAILED,
CFG80211_CONN_DEAUTH, CFG80211_CONN_DEAUTH,
CFG80211_CONN_CONNECTED, CFG80211_CONN_CONNECTED,
} state; } state;
...@@ -164,6 +166,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) ...@@ -164,6 +166,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
NULL, 0, NULL, 0,
params->key, params->key_len, params->key, params->key_len,
params->key_idx, NULL, 0); params->key_idx, NULL, 0);
case CFG80211_CONN_AUTH_FAILED:
return -ENOTCONN;
case CFG80211_CONN_ASSOCIATE_NEXT: case CFG80211_CONN_ASSOCIATE_NEXT:
BUG_ON(!rdev->ops->assoc); BUG_ON(!rdev->ops->assoc);
wdev->conn->state = CFG80211_CONN_ASSOCIATING; wdev->conn->state = CFG80211_CONN_ASSOCIATING;
...@@ -188,10 +192,17 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) ...@@ -188,10 +192,17 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
WLAN_REASON_DEAUTH_LEAVING, WLAN_REASON_DEAUTH_LEAVING,
false); false);
return err; return err;
case CFG80211_CONN_ASSOC_FAILED:
cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
NULL, 0,
WLAN_REASON_DEAUTH_LEAVING, false);
return -ENOTCONN;
case CFG80211_CONN_DEAUTH: case CFG80211_CONN_DEAUTH:
cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
NULL, 0, NULL, 0,
WLAN_REASON_DEAUTH_LEAVING, false); WLAN_REASON_DEAUTH_LEAVING, false);
/* free directly, disconnected event already sent */
cfg80211_sme_free(wdev);
return 0; return 0;
default: default:
return 0; return 0;
...@@ -371,7 +382,7 @@ bool cfg80211_sme_rx_assoc_resp(struct wireless_dev *wdev, u16 status) ...@@ -371,7 +382,7 @@ bool cfg80211_sme_rx_assoc_resp(struct wireless_dev *wdev, u16 status)
return true; return true;
} }
wdev->conn->state = CFG80211_CONN_DEAUTH; wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
schedule_work(&rdev->conn_work); schedule_work(&rdev->conn_work);
return false; return false;
} }
...@@ -383,7 +394,13 @@ void cfg80211_sme_deauth(struct wireless_dev *wdev) ...@@ -383,7 +394,13 @@ void cfg80211_sme_deauth(struct wireless_dev *wdev)
void cfg80211_sme_auth_timeout(struct wireless_dev *wdev) void cfg80211_sme_auth_timeout(struct wireless_dev *wdev)
{ {
cfg80211_sme_free(wdev); struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
if (!wdev->conn)
return;
wdev->conn->state = CFG80211_CONN_AUTH_FAILED;
schedule_work(&rdev->conn_work);
} }
void cfg80211_sme_disassoc(struct wireless_dev *wdev) void cfg80211_sme_disassoc(struct wireless_dev *wdev)
...@@ -399,7 +416,13 @@ void cfg80211_sme_disassoc(struct wireless_dev *wdev) ...@@ -399,7 +416,13 @@ void cfg80211_sme_disassoc(struct wireless_dev *wdev)
void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev) void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
{ {
cfg80211_sme_disassoc(wdev); struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
if (!wdev->conn)
return;
wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
schedule_work(&rdev->conn_work);
} }
static int cfg80211_sme_connect(struct wireless_dev *wdev, static int cfg80211_sme_connect(struct wireless_dev *wdev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment