aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/rx.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-12-09 18:12:03 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-09 18:12:03 -0500
commitb5f185f33d0432cef6ff78765e033dfa8f4de068 (patch)
tree33179c016b8fc3b4d57ed7a7786079ba00b6ef4a /drivers/net/wireless/iwlwifi/mvm/rx.c
parentsh_eth: Remove redundant alignment adjustment (diff)
parentMerge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless (diff)
downloadlinux-dev-b5f185f33d0432cef6ff78765e033dfa8f4de068.tar.xz
linux-dev-b5f185f33d0432cef6ff78765e033dfa8f4de068.zip
Merge tag 'master-2014-12-08' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says: ==================== pull request: wireless-next 2014-12-08 Please pull this last batch of pending wireless updates for the 3.19 tree... For the wireless bits, Johannes says: "This time I have Felix's no-status rate control work, which will allow drivers to work better with rate control even if they don't have perfect status reporting. In addition to this, a small hwsim fix from Patrik, one of the regulatory patches from Arik, and a number of cleanups and fixes I did myself. Of note is a patch where I disable CFG80211_WEXT so that compatibility is no longer selectable - this is intended as a wake-up call for anyone who's still using it, and is still easily worked around (it's a one-line patch) before we fully remove the code as well in the future." For the Bluetooth bits, Johan says: "Here's one more bluetooth-next pull request for 3.19: - Minor cleanups for ieee802154 & mac802154 - Fix for the kernel warning with !TASK_RUNNING reported by Kirill A. Shutemov - Support for another ath3k device - Fix for tracking link key based security level - Device tree bindings for btmrvl + a state update fix - Fix for wrong ACL flags on LE links" And... "In addition to the previous one this contains two more cleanups to mac802154 as well as support for some new HCI features from the Bluetooth 4.2 specification. From the original request: 'Here's what should be the last bluetooth-next pull request for 3.19. It's rather large but the majority of it is the Low Energy Secure Connections feature that's part of the Bluetooth 4.2 specification. The specification went public only this week so we couldn't publish the corresponding code before that. The code itself can nevertheless be considered fairly mature as it's been in development for over 6 months and gone through several interoperability test events. Besides LE SC the pull request contains an important fix for command complete events for mgmt sockets which also fixes some leaks of hci_conn objects when powering off or unplugging Bluetooth adapters. A smaller feature that's part of the pull request is service discovery support. This is like normal device discovery except that devices not matching specific UUIDs or strong enough RSSI are filtered out. Other changes that the pull request contains are firmware dump support to the btmrvl driver, firmware download support for Broadcom BCM20702A0 variants, as well as some coding style cleanups in 6lowpan & ieee802154/mac802154 code.'" For the NFC bits, Samuel says: "With this one we get: - NFC digital improvements for DEP support: Chaining, NACK and ATN support added. - NCI improvements: Support for p2p target, SE IO operand addition, SE operands extensions to support proprietary implementations, and a few fixes. - NFC HCI improvements: OPEN_PIPE and NOTIFY_ALL_CLEARED support, and SE IO operand addition. - A bunch of minor improvements and fixes for STMicro st21nfcb and st21nfca" For the iwlwifi bits, Emmanuel says: "Major works are CSA and TDLS. On top of that I have a new firmware API for scan and a few rate control improvements. Johannes find a few tricks to improve our CPU utilization and adds support for a new spin of 7265 called 7265D. Along with this a few random things that don't stand out." And... "I deprecate here -8.ucode since -9 has been published long ago. Along with that I have a new activity, we have now better a infrastructure for firmware debugging. This will allow to have configurable probes insides the firmware. Luca continues his work on NetDetect, this feature is now complete. All the rest is minor fixes here and there." For the Atheros bits, Kalle says: "Only ath10k changes this time and no major changes. Most visible are: o new debugfs interface for runtime firmware debugging (Yanbo) o fix shared WEP (Sujith) o don't rebuild whenever kernel version changes (Johannes) o lots of refactoring to make it easier to add new hw support (Michal) There's also smaller fixes and improvements with no point of listing here." In addition, there are a few last minute updates to ath5k, ath9k, brcmfmac, brcmsmac, mwifiex, rt2x00, rtlwifi, and wil6210. Also included is a pull of the wireless tree to pick-up the fixes originally included in "pull request: wireless 2014-12-03"... Please let me know if there are problems! ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/rx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rx.c150
1 files changed, 73 insertions, 77 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index 3cf40f3f58ec..94b6e7297a1e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -96,27 +96,27 @@ int iwl_mvm_rx_rx_phy_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
* Adds the rxb to a new skb and give it to mac80211
*/
static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
+ struct sk_buff *skb,
struct ieee80211_hdr *hdr, u16 len,
- u32 ampdu_status,
- struct iwl_rx_cmd_buffer *rxb,
- struct ieee80211_rx_status *stats)
+ u32 ampdu_status, u8 crypt_len,
+ struct iwl_rx_cmd_buffer *rxb)
{
- struct sk_buff *skb;
unsigned int hdrlen, fraglen;
- /* Dont use dev_alloc_skb(), we'll have enough headroom once
- * ieee80211_hdr pulled.
- */
- skb = alloc_skb(128, GFP_ATOMIC);
- if (!skb) {
- IWL_ERR(mvm, "alloc_skb failed\n");
- return;
- }
/* If frame is small enough to fit in skb->head, pull it completely.
- * If not, only pull ieee80211_hdr so that splice() or TCP coalesce
- * are more efficient.
+ * If not, only pull ieee80211_hdr (including crypto if present, and
+ * an additional 8 bytes for SNAP/ethertype, see below) so that
+ * splice() or TCP coalesce are more efficient.
+ *
+ * Since, in addition, ieee80211_data_to_8023() always pull in at
+ * least 8 bytes (possibly more for mesh) we can do the same here
+ * to save the cost of doing it later. That still doesn't pull in
+ * the actual IP header since the typical case has a SNAP header.
+ * If the latter changes (there are efforts in the standards group
+ * to do so) we should revisit this and ieee80211_data_to_8023().
*/
- hdrlen = (len <= skb_tailroom(skb)) ? len : sizeof(*hdr);
+ hdrlen = (len <= skb_tailroom(skb)) ? len :
+ sizeof(*hdr) + crypt_len + 8;
memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
fraglen = len - hdrlen;
@@ -129,8 +129,6 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
fraglen, rxb->truesize);
}
- memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
-
ieee80211_rx(mvm->hw, skb);
}
@@ -185,7 +183,8 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *stats,
- u32 rx_pkt_status)
+ u32 rx_pkt_status,
+ u8 *crypt_len)
{
if (!ieee80211_has_protected(hdr->frame_control) ||
(rx_pkt_status & RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==
@@ -205,12 +204,14 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
stats->flag |= RX_FLAG_DECRYPTED;
IWL_DEBUG_WEP(mvm, "hw decrypted CCMP successfully\n");
+ *crypt_len = IEEE80211_CCMP_HDR_LEN;
return 0;
case RX_MPDU_RES_STATUS_SEC_TKIP_ENC:
/* Don't drop the frame and decrypt it in SW */
if (!(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK))
return 0;
+ *crypt_len = IEEE80211_TKIP_IV_LEN;
/* fall through if TTAK OK */
case RX_MPDU_RES_STATUS_SEC_WEP_ENC:
@@ -218,6 +219,9 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
return -1;
stats->flag |= RX_FLAG_DECRYPTED;
+ if ((rx_pkt_status & RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==
+ RX_MPDU_RES_STATUS_SEC_WEP_ENC)
+ *crypt_len = IEEE80211_WEP_IV_LEN;
return 0;
case RX_MPDU_RES_STATUS_SEC_EXT_ENC:
@@ -242,15 +246,17 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct ieee80211_hdr *hdr;
- struct ieee80211_rx_status rx_status = {};
+ struct ieee80211_rx_status *rx_status;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_rx_phy_info *phy_info;
struct iwl_rx_mpdu_res_start *rx_res;
struct ieee80211_sta *sta;
+ struct sk_buff *skb;
u32 len;
u32 ampdu_status;
u32 rate_n_flags;
u32 rx_pkt_status;
+ u8 crypt_len = 0;
phy_info = &mvm->last_phy_info;
rx_res = (struct iwl_rx_mpdu_res_start *)pkt->data;
@@ -259,20 +265,32 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
rx_pkt_status = le32_to_cpup((__le32 *)
(pkt->data + sizeof(*rx_res) + len));
- memset(&rx_status, 0, sizeof(rx_status));
+ /* Dont use dev_alloc_skb(), we'll have enough headroom once
+ * ieee80211_hdr pulled.
+ */
+ skb = alloc_skb(128, GFP_ATOMIC);
+ if (!skb) {
+ IWL_ERR(mvm, "alloc_skb failed\n");
+ return 0;
+ }
+
+ rx_status = IEEE80211_SKB_RXCB(skb);
/*
* drop the packet if it has failed being decrypted by HW
*/
- if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, &rx_status, rx_pkt_status)) {
+ if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, rx_status, rx_pkt_status,
+ &crypt_len)) {
IWL_DEBUG_DROP(mvm, "Bad decryption results 0x%08x\n",
rx_pkt_status);
+ kfree_skb(skb);
return 0;
}
if ((unlikely(phy_info->cfg_phy_cnt > 20))) {
IWL_DEBUG_DROP(mvm, "dsp size out of range [0,20]: %d\n",
phy_info->cfg_phy_cnt);
+ kfree_skb(skb);
return 0;
}
@@ -283,31 +301,31 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
if (!(rx_pkt_status & RX_MPDU_RES_STATUS_CRC_OK) ||
!(rx_pkt_status & RX_MPDU_RES_STATUS_OVERRUN_OK)) {
IWL_DEBUG_RX(mvm, "Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status);
- rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
}
/* This will be used in several places later */
rate_n_flags = le32_to_cpu(phy_info->rate_n_flags);
/* rx_status carries information about the packet to mac80211 */
- rx_status.mactime = le64_to_cpu(phy_info->timestamp);
- rx_status.device_timestamp = le32_to_cpu(phy_info->system_timestamp);
- rx_status.band =
+ rx_status->mactime = le64_to_cpu(phy_info->timestamp);
+ rx_status->device_timestamp = le32_to_cpu(phy_info->system_timestamp);
+ rx_status->band =
(phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ?
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
- rx_status.freq =
+ rx_status->freq =
ieee80211_channel_to_frequency(le16_to_cpu(phy_info->channel),
- rx_status.band);
+ rx_status->band);
/*
* TSF as indicated by the fw is at INA time, but mac80211 expects the
* TSF at the beginning of the MPDU.
*/
- /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
+ /*rx_status->flag |= RX_FLAG_MACTIME_MPDU;*/
- iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status);
+ iwl_mvm_get_signal_strength(mvm, phy_info, rx_status);
- IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal,
- (unsigned long long)rx_status.mactime);
+ IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status->signal,
+ (unsigned long long)rx_status->mactime);
rcu_read_lock();
/*
@@ -326,15 +344,14 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
if (sta) {
struct iwl_mvm_sta *mvmsta;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
- rs_update_last_rssi(mvm, &mvmsta->lq_sta,
- &rx_status);
+ rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status);
}
rcu_read_unlock();
/* set the preamble flag if appropriate */
if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE))
- rx_status.flag |= RX_FLAG_SHORTPRE;
+ rx_status->flag |= RX_FLAG_SHORTPRE;
if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_AGG)) {
/*
@@ -342,8 +359,8 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
* together since we get a single PHY response
* from the firmware for all of them
*/
- rx_status.flag |= RX_FLAG_AMPDU_DETAILS;
- rx_status.ampdu_reference = mvm->ampdu_ref;
+ rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
+ rx_status->ampdu_reference = mvm->ampdu_ref;
}
/* Set up the HT phy flags */
@@ -351,50 +368,50 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
case RATE_MCS_CHAN_WIDTH_20:
break;
case RATE_MCS_CHAN_WIDTH_40:
- rx_status.flag |= RX_FLAG_40MHZ;
+ rx_status->flag |= RX_FLAG_40MHZ;
break;
case RATE_MCS_CHAN_WIDTH_80:
- rx_status.vht_flag |= RX_VHT_FLAG_80MHZ;
+ rx_status->vht_flag |= RX_VHT_FLAG_80MHZ;
break;
case RATE_MCS_CHAN_WIDTH_160:
- rx_status.vht_flag |= RX_VHT_FLAG_160MHZ;
+ rx_status->vht_flag |= RX_VHT_FLAG_160MHZ;
break;
}
if (rate_n_flags & RATE_MCS_SGI_MSK)
- rx_status.flag |= RX_FLAG_SHORT_GI;
+ rx_status->flag |= RX_FLAG_SHORT_GI;
if (rate_n_flags & RATE_HT_MCS_GF_MSK)
- rx_status.flag |= RX_FLAG_HT_GF;
+ rx_status->flag |= RX_FLAG_HT_GF;
if (rate_n_flags & RATE_MCS_LDPC_MSK)
- rx_status.flag |= RX_FLAG_LDPC;
+ rx_status->flag |= RX_FLAG_LDPC;
if (rate_n_flags & RATE_MCS_HT_MSK) {
u8 stbc = (rate_n_flags & RATE_MCS_HT_STBC_MSK) >>
RATE_MCS_STBC_POS;
- rx_status.flag |= RX_FLAG_HT;
- rx_status.rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
- rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT;
+ rx_status->flag |= RX_FLAG_HT;
+ rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
+ rx_status->flag |= stbc << RX_FLAG_STBC_SHIFT;
} else if (rate_n_flags & RATE_MCS_VHT_MSK) {
u8 stbc = (rate_n_flags & RATE_MCS_VHT_STBC_MSK) >>
RATE_MCS_STBC_POS;
- rx_status.vht_nss =
+ rx_status->vht_nss =
((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
RATE_VHT_MCS_NSS_POS) + 1;
- rx_status.rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
- rx_status.flag |= RX_FLAG_VHT;
- rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT;
+ rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
+ rx_status->flag |= RX_FLAG_VHT;
+ rx_status->flag |= stbc << RX_FLAG_STBC_SHIFT;
if (rate_n_flags & RATE_MCS_BF_MSK)
- rx_status.vht_flag |= RX_VHT_FLAG_BF;
+ rx_status->vht_flag |= RX_VHT_FLAG_BF;
} else {
- rx_status.rate_idx =
+ rx_status->rate_idx =
iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
- rx_status.band);
+ rx_status->band);
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_mvm_update_frame_stats(mvm, &mvm->drv_rx_stats, rate_n_flags,
- rx_status.flag & RX_FLAG_AMPDU_DETAILS);
+ rx_status->flag & RX_FLAG_AMPDU_DETAILS);
#endif
- iwl_mvm_pass_packet_to_mac80211(mvm, hdr, len, ampdu_status,
- rxb, &rx_status);
+ iwl_mvm_pass_packet_to_mac80211(mvm, skb, hdr, len, ampdu_status,
+ crypt_len, rxb);
return 0;
}
@@ -500,29 +517,8 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
.mvm = mvm,
};
- /*
- * set temperature debug enabled - ignore FW temperature updates
- * and use the user set temperature.
- */
- if (mvm->temperature_test) {
- if (mvm->temperature < le32_to_cpu(common->temperature))
- IWL_DEBUG_TEMP(mvm,
- "Ignoring FW temperature update that is greater than the debug set temperature (debug temp = %d, fw temp = %d)\n",
- mvm->temperature,
- le32_to_cpu(common->temperature));
- /*
- * skip iwl_mvm_tt_handler since we are in
- * temperature debug mode and we are ignoring
- * the new temperature value
- */
- goto update;
- }
+ iwl_mvm_tt_temp_changed(mvm, le32_to_cpu(common->temperature));
- if (mvm->temperature != le32_to_cpu(common->temperature)) {
- mvm->temperature = le32_to_cpu(common->temperature);
- iwl_mvm_tt_handler(mvm);
- }
-update:
iwl_mvm_update_rx_statistics(mvm, stats);
ieee80211_iterate_active_interfaces(mvm->hw,