Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless

This commit is contained in:
John W. Linville 2013-07-25 16:48:01 -04:00
commit 9d55911e8f
40 changed files with 379 additions and 200 deletions

View File

@ -325,7 +325,7 @@ ath5k_prepare_multicast(struct ieee80211_hw *hw,
struct netdev_hw_addr *ha; struct netdev_hw_addr *ha;
mfilt[0] = 0; mfilt[0] = 0;
mfilt[1] = 1; mfilt[1] = 0;
netdev_hw_addr_list_for_each(ha, mc_list) { netdev_hw_addr_list_for_each(ha, mc_list) {
/* calculate XOR of eight 6-bit values */ /* calculate XOR of eight 6-bit values */

View File

@ -610,7 +610,15 @@ static void ar5008_hw_override_ini(struct ath_hw *ah,
REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
if (AR_SREV_9280_20_OR_LATER(ah)) { if (AR_SREV_9280_20_OR_LATER(ah)) {
val = REG_READ(ah, AR_PCU_MISC_MODE2); /*
* For AR9280 and above, there is a new feature that allows
* Multicast search based on both MAC Address and Key ID.
* By default, this feature is enabled. But since the driver
* is not using this feature, we switch it off; otherwise
* multicast search based on MAC addr only will fail.
*/
val = REG_READ(ah, AR_PCU_MISC_MODE2) &
(~AR_ADHOC_MCAST_KEYID_ENABLE);
if (!AR_SREV_9271(ah)) if (!AR_SREV_9271(ah))
val &= ~AR_PCU_MISC_MODE2_HWWAR1; val &= ~AR_PCU_MISC_MODE2_HWWAR1;

View File

@ -1082,7 +1082,7 @@ static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev)
struct device *dev = &hif_dev->udev->dev; struct device *dev = &hif_dev->udev->dev;
struct device *parent = dev->parent; struct device *parent = dev->parent;
complete(&hif_dev->fw_done); complete_all(&hif_dev->fw_done);
if (parent) if (parent)
device_lock(parent); device_lock(parent);
@ -1131,7 +1131,7 @@ static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context)
release_firmware(fw); release_firmware(fw);
hif_dev->flags |= HIF_USB_READY; hif_dev->flags |= HIF_USB_READY;
complete(&hif_dev->fw_done); complete_all(&hif_dev->fw_done);
return; return;
@ -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);
@ -1316,7 +1318,10 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface,
if (!(hif_dev->flags & HIF_USB_START)) if (!(hif_dev->flags & HIF_USB_START))
ath9k_htc_suspend(hif_dev->htc_handle); ath9k_htc_suspend(hif_dev->htc_handle);
ath9k_hif_usb_dealloc_urbs(hif_dev); wait_for_completion(&hif_dev->fw_done);
if (hif_dev->flags & HIF_USB_READY)
ath9k_hif_usb_dealloc_urbs(hif_dev);
return 0; return 0;
} }

View File

@ -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,

View File

@ -146,6 +146,28 @@ static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
ARRAY_SIZE(bf->rates)); ARRAY_SIZE(bf->rates));
} }
static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
struct sk_buff *skb)
{
int q;
q = skb_get_queue_mapping(skb);
if (txq == sc->tx.uapsdq)
txq = sc->tx.txq_map[q];
if (txq != sc->tx.txq_map[q])
return;
if (WARN_ON(--txq->pending_frames < 0))
txq->pending_frames = 0;
if (txq->stopped &&
txq->pending_frames < sc->tx.txq_max_pending[q]) {
ieee80211_wake_queue(sc->hw, q);
txq->stopped = false;
}
}
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{ {
struct ath_txq *txq = tid->ac->txq; struct ath_txq *txq = tid->ac->txq;
@ -167,6 +189,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
if (!bf) { if (!bf) {
bf = ath_tx_setup_buffer(sc, txq, tid, skb); bf = ath_tx_setup_buffer(sc, txq, tid, skb);
if (!bf) { if (!bf) {
ath_txq_skb_done(sc, txq, skb);
ieee80211_free_txskb(sc->hw, skb); ieee80211_free_txskb(sc->hw, skb);
continue; continue;
} }
@ -811,6 +834,7 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
if (!bf) { if (!bf) {
__skb_unlink(skb, &tid->buf_q); __skb_unlink(skb, &tid->buf_q);
ath_txq_skb_done(sc, txq, skb);
ieee80211_free_txskb(sc->hw, skb); ieee80211_free_txskb(sc->hw, skb);
continue; continue;
} }
@ -1852,6 +1876,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_txq *txq,
bf = ath_tx_setup_buffer(sc, txq, tid, skb); bf = ath_tx_setup_buffer(sc, txq, tid, skb);
if (!bf) { if (!bf) {
ath_txq_skb_done(sc, txq, skb);
ieee80211_free_txskb(sc->hw, skb); ieee80211_free_txskb(sc->hw, skb);
return; return;
} }
@ -2118,6 +2143,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
bf = ath_tx_setup_buffer(sc, txq, tid, skb); bf = ath_tx_setup_buffer(sc, txq, tid, skb);
if (!bf) { if (!bf) {
ath_txq_skb_done(sc, txq, skb);
if (txctl->paprd) if (txctl->paprd)
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
else else
@ -2217,7 +2243,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
int q, padpos, padsize; int padpos, padsize;
unsigned long flags; unsigned long flags;
ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
@ -2253,21 +2279,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
spin_unlock_irqrestore(&sc->sc_pm_lock, flags); spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
__skb_queue_tail(&txq->complete_q, skb); __skb_queue_tail(&txq->complete_q, skb);
ath_txq_skb_done(sc, txq, skb);
q = skb_get_queue_mapping(skb);
if (txq == sc->tx.uapsdq)
txq = sc->tx.txq_map[q];
if (txq == sc->tx.txq_map[q]) {
if (WARN_ON(--txq->pending_frames < 0))
txq->pending_frames = 0;
if (txq->stopped &&
txq->pending_frames < sc->tx.txq_max_pending[q]) {
ieee80211_wake_queue(sc->hw, q);
txq->stopped = false;
}
}
} }
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,

View File

@ -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)
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;

View File

@ -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",

View File

@ -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)
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);

View File

@ -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;

View File

@ -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
*/ */

View File

@ -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);

View File

@ -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)
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,
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,
} else { } else {
ret = -EIO; ret = -EIO;
} }
out_unlock:
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
return ret; return ret;

View File

@ -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;

View File

@ -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,
* 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,
__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;

View File

@ -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,
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;
cmd.add_immediate_ba_tid = (u8) tid; if (start) {
cmd.add_immediate_ba_ssn = cpu_to_le16(ssn); 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 : 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,
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;
} }

View File

@ -682,7 +682,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;
@ -707,14 +707,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;
} }

View File

@ -431,6 +431,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) {
@ -482,6 +486,8 @@ err_add_intf:
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:
@ -859,7 +865,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;
@ -923,6 +929,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 */

View File

@ -602,6 +602,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 *);

View File

@ -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 = {
} }
}; };
/* 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
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)
* 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 */ sdio_claim_host(func);
if (mwifiex_read_reg(adapter, HOST_INT_MASK_REG, &host_int_mask)) mwifiex_write_reg_locked(func, HOST_INT_MASK_REG, 0);
return -1; sdio_release_irq(func);
sdio_release_host(func);
/* 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;
} }
/* /*
@ -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)
} }
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)
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)
*/ */
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)
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)
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)
*/ */
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 = {
.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,

View File

@ -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 */

View File

@ -1,6 +1,6 @@
menuconfig RT2X00 menuconfig RT2X00
tristate "Ralink driver support" tristate "Ralink driver support"
depends on MAC80211 depends on MAC80211 && HAS_DMA
---help--- ---help---
This will enable the support for the Ralink drivers, This will enable the support for the Ralink drivers,
developed in the rt2x00 project <http://rt2x00.serialmonkey.com>. developed in the rt2x00 project <http://rt2x00.serialmonkey.com>.

View File

@ -1,13 +1,91 @@
config RTLWIFI menuconfig RTL_CARDS
tristate "Realtek wireless card support" tristate "Realtek rtlwifi family of devices"
depends on MAC80211 depends on MAC80211 && (PCI || USB)
select FW_LOADER default y
---help--- ---help---
This is common code for RTL8192CE/RTL8192CU/RTL8192SE/RTL8723AE This option will enable support for the Realtek mac80211-based
drivers. This module does nothing by itself - the various front-end wireless drivers. Drivers rtl8192ce, rtl8192cu, rtl8192se, rtl8192de,
drivers need to be enabled to support any desired devices. rtl8723eu, and rtl8188eu share some common code.
If you choose to build as a module, it'll be called rtlwifi. if RTL_CARDS
config RTL8192CE
tristate "Realtek RTL8192CE/RTL8188CE Wireless Network Adapter"
depends on PCI
select RTL8192C_COMMON
select RTLWIFI
select RTLWIFI_PCI
---help---
This is the driver for Realtek RTL8192CE/RTL8188CE 802.11n PCIe
wireless network adapters.
If you choose to build it as a module, it will be called rtl8192ce
config RTL8192SE
tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter"
depends on PCI
select RTLWIFI
select RTLWIFI_PCI
---help---
This is the driver for Realtek RTL8192SE/RTL8191SE 802.11n PCIe
wireless network adapters.
If you choose to build it as a module, it will be called rtl8192se
config RTL8192DE
tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter"
depends on PCI
select RTLWIFI
select RTLWIFI_PCI
---help---
This is the driver for Realtek RTL8192DE/RTL8188DE 802.11n PCIe
wireless network adapters.
If you choose to build it as a module, it will be called rtl8192de
config RTL8723AE
tristate "Realtek RTL8723AE PCIe Wireless Network Adapter"
depends on PCI
select RTLWIFI
select RTLWIFI_PCI
---help---
This is the driver for Realtek RTL8723AE 802.11n PCIe
wireless network adapters.
If you choose to build it as a module, it will be called rtl8723ae
config RTL8188EE
tristate "Realtek RTL8188EE Wireless Network Adapter"
depends on PCI
select RTLWIFI
select RTLWIFI_PCI
---help---
This is the driver for Realtek RTL8188EE 802.11n PCIe
wireless network adapters.
If you choose to build it as a module, it will be called rtl8188ee
config RTL8192CU
tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
depends on USB
select RTLWIFI
select RTLWIFI_USB
select RTL8192C_COMMON
---help---
This is the driver for Realtek RTL8192CU/RTL8188CU 802.11n USB
wireless network adapters.
If you choose to build it as a module, it will be called rtl8192cu
config RTLWIFI
tristate
select FW_LOADER
config RTLWIFI_PCI
tristate
config RTLWIFI_USB
tristate
config RTLWIFI_DEBUG config RTLWIFI_DEBUG
bool "Debugging output for rtlwifi driver family" bool "Debugging output for rtlwifi driver family"
@ -18,63 +96,9 @@ config RTLWIFI_DEBUG
the front-end driver, this parameter must be "Y". For memory-limited the front-end driver, this parameter must be "Y". For memory-limited
systems, choose "N". If in doubt, choose "Y". systems, choose "N". If in doubt, choose "Y".
config RTL8192CE
tristate "Realtek RTL8192CE/RTL8188CE Wireless Network Adapter"
depends on RTLWIFI && PCI
select RTL8192C_COMMON
---help---
This is the driver for Realtek RTL8192CE/RTL8188CE 802.11n PCIe
wireless network adapters.
If you choose to build it as a module, it will be called rtl8192ce
config RTL8192SE
tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter"
depends on RTLWIFI && PCI
---help---
This is the driver for Realtek RTL8192SE/RTL8191SE 802.11n PCIe
wireless network adapters.
If you choose to build it as a module, it will be called rtl8192se
config RTL8192DE
tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter"
depends on RTLWIFI && PCI
---help---
This is the driver for Realtek RTL8192DE/RTL8188DE 802.11n PCIe
wireless network adapters.
If you choose to build it as a module, it will be called rtl8192de
config RTL8723AE
tristate "Realtek RTL8723AE PCIe Wireless Network Adapter"
depends on RTLWIFI && PCI
---help---
This is the driver for Realtek RTL8723AE 802.11n PCIe
wireless network adapters.
If you choose to build it as a module, it will be called rtl8723ae
config RTL8188EE
tristate "Realtek RTL8188EE Wireless Network Adapter"
depends on RTLWIFI && PCI
---help---
This is the driver for Realtek RTL8188EE 802.11n PCIe
wireless network adapters.
If you choose to build it as a module, it will be called rtl8188ee
config RTL8192CU
tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
depends on RTLWIFI && USB
select RTL8192C_COMMON
---help---
This is the driver for Realtek RTL8192CU/RTL8188CU 802.11n USB
wireless network adapters.
If you choose to build it as a module, it will be called rtl8192cu
config RTL8192C_COMMON config RTL8192C_COMMON
tristate tristate
depends on RTL8192CE || RTL8192CU depends on RTL8192CE || RTL8192CU
default m default y
endif

View File

@ -12,13 +12,11 @@ rtlwifi-objs := \
rtl8192c_common-objs += \ rtl8192c_common-objs += \
ifneq ($(CONFIG_PCI),) obj-$(CONFIG_RTLWIFI_PCI) += rtl_pci.o
rtlwifi-objs += pci.o rtl_pci-objs := pci.o
endif
ifneq ($(CONFIG_USB),) obj-$(CONFIG_RTLWIFI_USB) += rtl_usb.o
rtlwifi-objs += usb.o rtl_usb-objs := usb.o
endif
obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c/ obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c/
obj-$(CONFIG_RTL8192CE) += rtl8192ce/ obj-$(CONFIG_RTL8192CE) += rtl8192ce/

View File

@ -172,6 +172,7 @@ u8 rtl_tid_to_ac(u8 tid)
{ {
return tid_to_ac[tid]; return tid_to_ac[tid];
} }
EXPORT_SYMBOL_GPL(rtl_tid_to_ac);
static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw,
struct ieee80211_sta_ht_cap *ht_cap) struct ieee80211_sta_ht_cap *ht_cap)
@ -406,6 +407,7 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw)
cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); cancel_delayed_work(&rtlpriv->works.ps_rfon_wq);
cancel_delayed_work(&rtlpriv->works.fwevt_wq); cancel_delayed_work(&rtlpriv->works.fwevt_wq);
} }
EXPORT_SYMBOL_GPL(rtl_deinit_deferred_work);
void rtl_init_rfkill(struct ieee80211_hw *hw) void rtl_init_rfkill(struct ieee80211_hw *hw)
{ {
@ -439,6 +441,7 @@ void rtl_deinit_rfkill(struct ieee80211_hw *hw)
{ {
wiphy_rfkill_stop_polling(hw->wiphy); wiphy_rfkill_stop_polling(hw->wiphy);
} }
EXPORT_SYMBOL_GPL(rtl_deinit_rfkill);
int rtl_init_core(struct ieee80211_hw *hw) int rtl_init_core(struct ieee80211_hw *hw)
{ {
@ -489,10 +492,12 @@ int rtl_init_core(struct ieee80211_hw *hw)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rtl_init_core);
void rtl_deinit_core(struct ieee80211_hw *hw) void rtl_deinit_core(struct ieee80211_hw *hw)
{ {
} }
EXPORT_SYMBOL_GPL(rtl_deinit_core);
void rtl_init_rx_config(struct ieee80211_hw *hw) void rtl_init_rx_config(struct ieee80211_hw *hw)
{ {
@ -501,6 +506,7 @@ void rtl_init_rx_config(struct ieee80211_hw *hw)
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf));
} }
EXPORT_SYMBOL_GPL(rtl_init_rx_config);
/********************************************************* /*********************************************************
* *
@ -879,6 +885,7 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb)
return true; return true;
} }
EXPORT_SYMBOL_GPL(rtl_tx_mgmt_proc);
void rtl_get_tcb_desc(struct ieee80211_hw *hw, void rtl_get_tcb_desc(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info, struct ieee80211_tx_info *info,
@ -1052,6 +1059,7 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
return true; return true;
} }
EXPORT_SYMBOL_GPL(rtl_action_proc);
/*should call before software enc*/ /*should call before software enc*/
u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
@ -1125,6 +1133,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
return false; return false;
} }
EXPORT_SYMBOL_GPL(rtl_is_special_data);
/********************************************************* /*********************************************************
* *
@ -1300,6 +1309,7 @@ void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb)
rtlpriv->link_info.bcn_rx_inperiod++; rtlpriv->link_info.bcn_rx_inperiod++;
} }
EXPORT_SYMBOL_GPL(rtl_beacon_statistic);
void rtl_watchdog_wq_callback(void *data) void rtl_watchdog_wq_callback(void *data)
{ {
@ -1793,6 +1803,7 @@ void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len)
mac->vendor = vendor; mac->vendor = vendor;
} }
EXPORT_SYMBOL_GPL(rtl_recognize_peer);
/********************************************************* /*********************************************************
* *
@ -1849,6 +1860,7 @@ struct attribute_group rtl_attribute_group = {
.name = "rtlsysfs", .name = "rtlsysfs",
.attrs = rtl_sysfs_entries, .attrs = rtl_sysfs_entries,
}; };
EXPORT_SYMBOL_GPL(rtl_attribute_group);
MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>"); MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
@ -1856,7 +1868,8 @@ MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
struct rtl_global_var global_var = {}; struct rtl_global_var rtl_global_var = {};
EXPORT_SYMBOL_GPL(rtl_global_var);
static int __init rtl_core_module_init(void) static int __init rtl_core_module_init(void)
{ {
@ -1864,8 +1877,8 @@ static int __init rtl_core_module_init(void)
pr_err("Unable to register rtl_rc, use default RC !!\n"); pr_err("Unable to register rtl_rc, use default RC !!\n");
/* init some global vars */ /* init some global vars */
INIT_LIST_HEAD(&global_var.glb_priv_list); INIT_LIST_HEAD(&rtl_global_var.glb_priv_list);
spin_lock_init(&global_var.glb_list_lock); spin_lock_init(&rtl_global_var.glb_list_lock);
return 0; return 0;
} }

View File

@ -147,7 +147,7 @@ void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len);
u8 rtl_tid_to_ac(u8 tid); u8 rtl_tid_to_ac(u8 tid);
extern struct attribute_group rtl_attribute_group; extern struct attribute_group rtl_attribute_group;
void rtl_easy_concurrent_retrytimer_callback(unsigned long data); void rtl_easy_concurrent_retrytimer_callback(unsigned long data);
extern struct rtl_global_var global_var; extern struct rtl_global_var rtl_global_var;
int rtlwifi_rate_mapping(struct ieee80211_hw *hw, int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
bool isht, u8 desc_rate, bool first_ampdu); bool isht, u8 desc_rate, bool first_ampdu);
bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb);

View File

@ -1330,3 +1330,4 @@ const struct ieee80211_ops rtl_ops = {
.rfkill_poll = rtl_op_rfkill_poll, .rfkill_poll = rtl_op_rfkill_poll,
.flush = rtl_op_flush, .flush = rtl_op_flush,
}; };
EXPORT_SYMBOL_GPL(rtl_ops);

View File

@ -51,3 +51,4 @@ void rtl_dbgp_flag_init(struct ieee80211_hw *hw)
/*Init Debug flag enable condition */ /*Init Debug flag enable condition */
} }
EXPORT_SYMBOL_GPL(rtl_dbgp_flag_init);

View File

@ -229,6 +229,7 @@ void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf)
*pbuf = (u8) (value32 & 0xff); *pbuf = (u8) (value32 & 0xff);
} }
EXPORT_SYMBOL_GPL(read_efuse_byte);
void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf)
{ {

View File

@ -35,6 +35,13 @@
#include "efuse.h" #include "efuse.h"
#include <linux/export.h> #include <linux/export.h>
#include <linux/kmemleak.h> #include <linux/kmemleak.h>
#include <linux/module.h>
MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PCI basic driver for rtlwifi");
static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = {
PCI_VENDOR_ID_INTEL, PCI_VENDOR_ID_INTEL,
@ -1008,19 +1015,6 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
return; return;
} }
static void rtl_lps_change_work_callback(struct work_struct *work)
{
struct rtl_works *rtlworks =
container_of(work, struct rtl_works, lps_change_work);
struct ieee80211_hw *hw = rtlworks->hw;
struct rtl_priv *rtlpriv = rtl_priv(hw);
if (rtlpriv->enter_ps)
rtl_lps_enter(hw);
else
rtl_lps_leave(hw);
}
static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw)
{ {
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
@ -1899,7 +1893,7 @@ int rtl_pci_probe(struct pci_dev *pdev,
rtlpriv->rtlhal.interface = INTF_PCI; rtlpriv->rtlhal.interface = INTF_PCI;
rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data);
rtlpriv->intf_ops = &rtl_pci_ops; rtlpriv->intf_ops = &rtl_pci_ops;
rtlpriv->glb_var = &global_var; rtlpriv->glb_var = &rtl_global_var;
/* /*
*init dbgp flags before all *init dbgp flags before all

View File

@ -269,6 +269,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags); spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags);
} }
EXPORT_SYMBOL_GPL(rtl_ips_nic_on);
/*for FW LPS*/ /*for FW LPS*/
@ -518,6 +519,7 @@ void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
"u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed); "u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed);
} }
} }
EXPORT_SYMBOL_GPL(rtl_swlps_beacon);
void rtl_swlps_rf_awake(struct ieee80211_hw *hw) void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
{ {
@ -611,6 +613,19 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40)); MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40));
} }
void rtl_lps_change_work_callback(struct work_struct *work)
{
struct rtl_works *rtlworks =
container_of(work, struct rtl_works, lps_change_work);
struct ieee80211_hw *hw = rtlworks->hw;
struct rtl_priv *rtlpriv = rtl_priv(hw);
if (rtlpriv->enter_ps)
rtl_lps_enter(hw);
else
rtl_lps_leave(hw);
}
EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback);
void rtl_swlps_wq_callback(void *data) void rtl_swlps_wq_callback(void *data)
{ {
@ -922,3 +937,4 @@ void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len)
else else
rtl_p2p_noa_ie(hw, data, len - FCS_LEN); rtl_p2p_noa_ie(hw, data, len - FCS_LEN);
} }
EXPORT_SYMBOL_GPL(rtl_p2p_info);

View File

@ -49,5 +49,6 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw);
void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); void rtl_swlps_rf_sleep(struct ieee80211_hw *hw);
void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len); void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len);
void rtl_lps_change_work_callback(struct work_struct *work);
#endif #endif

View File

@ -32,6 +32,13 @@
#include "ps.h" #include "ps.h"
#include "rtl8192c/fw_common.h" #include "rtl8192c/fw_common.h"
#include <linux/export.h> #include <linux/export.h>
#include <linux/module.h>
MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("USB basic driver for rtlwifi");
#define REALTEK_USB_VENQT_READ 0xC0 #define REALTEK_USB_VENQT_READ 0xC0
#define REALTEK_USB_VENQT_WRITE 0x40 #define REALTEK_USB_VENQT_WRITE 0x40
@ -1070,6 +1077,8 @@ int rtl_usb_probe(struct usb_interface *intf,
spin_lock_init(&rtlpriv->locks.usb_lock); spin_lock_init(&rtlpriv->locks.usb_lock);
INIT_WORK(&rtlpriv->works.fill_h2c_cmd, INIT_WORK(&rtlpriv->works.fill_h2c_cmd,
rtl_fill_h2c_cmd_work_callback); rtl_fill_h2c_cmd_work_callback);
INIT_WORK(&rtlpriv->works.lps_change_work,
rtl_lps_change_work_callback);
rtlpriv->usb_data_index = 0; rtlpriv->usb_data_index = 0;
init_completion(&rtlpriv->firmware_loading_complete); init_completion(&rtlpriv->firmware_loading_complete);

View File

@ -361,7 +361,8 @@ struct ssb_device_id {
__u16 vendor; __u16 vendor;
__u16 coreid; __u16 coreid;
__u8 revision; __u8 revision;
}; __u8 __pad;
} __attribute__((packed, aligned(2)));
#define SSB_DEVICE(_vendor, _coreid, _revision) \ #define SSB_DEVICE(_vendor, _coreid, _revision) \
{ .vendor = _vendor, .coreid = _coreid, .revision = _revision, } { .vendor = _vendor, .coreid = _coreid, .revision = _revision, }
#define SSB_DEVTABLE_END \ #define SSB_DEVTABLE_END \
@ -377,7 +378,7 @@ struct bcma_device_id {
__u16 id; __u16 id;
__u8 rev; __u8 rev;
__u8 class; __u8 class;
}; } __attribute__((packed,aligned(2)));
#define BCMA_CORE(_manuf, _id, _rev, _class) \ #define BCMA_CORE(_manuf, _id, _rev, _class) \
{ .manuf = _manuf, .id = _id, .rev = _rev, .class = _class, } { .manuf = _manuf, .id = _id, .rev = _rev, .class = _class, }
#define BCMA_CORETABLE_END \ #define BCMA_CORETABLE_END \

View File

@ -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);
} }

View File

@ -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,
(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;

View File

@ -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

View File

@ -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)) {

View File

@ -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);
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,
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:

View File

@ -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)

View File

@ -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)
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)
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)
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)
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)
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,