Commit 18e1ccb6 authored by John W. Linville's avatar John W. Linville

Merge branch 'master' of...

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem
parents f8c0aca9 23d412a2
...@@ -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