From: Reinette Chatre <reinette.chatre@intel.com>
To: linville@tuxdriver.com
Cc: linux-wireless@vger.kernel.org,
ipw3945-devel@lists.sourceforge.net,
Daniel C Halperin <daniel.c.halperin@intel.com>,
Reinette Chatre <reinette.chatre@intel.com>
Subject: [PATCH 07/13] iwlwifi: refactor packet reception code
Date: Thu, 13 Aug 2009 13:30:56 -0700 [thread overview]
Message-ID: <1250195462-15811-8-git-send-email-reinette.chatre@intel.com> (raw)
In-Reply-To: <1250195462-15811-1-git-send-email-reinette.chatre@intel.com>
From: Daniel C Halperin <daniel.c.halperin@intel.com>
This patch fixes a number of issues in iwl_rx_reply_rx and
iwl_pass_packet_to_mac80211. These issues stem from the complexities of
managing two different types of packet commands for different hardware.
- Unify code handling rx_phy_res in SKB or cached to eliminate redundancy and
remove potential NULL pointer accesses
- Replace magic number with proper constant
- Optimize functions by moving early exit conditions before computation
- Comment code and improve some variable names
- Remove redundant computation in iwl_pass_packet_to_mac80211 by passing in the
correct, already-computed arguments.
Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-commands.h | 1 +
drivers/net/wireless/iwlwifi/iwl-rx.c | 204 ++++++++++-----------------
2 files changed, 78 insertions(+), 127 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 68d7719..9398ad7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -1156,6 +1156,7 @@ struct iwl_wep_cmd {
#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2)
#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3)
#define RX_RES_PHY_FLAGS_ANTENNA_MSK cpu_to_le16(0xf0)
+#define RX_RES_PHY_FLAGS_ANTENNA_POS 4
#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 43b2fce..092d327 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -853,61 +853,12 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
}
static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
- int include_phy,
- struct iwl_rx_mem_buffer *rxb,
- struct ieee80211_rx_status *stats)
+ struct ieee80211_hdr *hdr,
+ u16 len,
+ u32 ampdu_status,
+ struct iwl_rx_mem_buffer *rxb,
+ struct ieee80211_rx_status *stats)
{
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- struct iwl_rx_phy_res *rx_start = (include_phy) ?
- (struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : NULL;
- struct ieee80211_hdr *hdr;
- u16 len;
- __le32 *rx_end;
- unsigned int skblen;
- u32 ampdu_status;
- u32 ampdu_status_legacy;
-
- if (!include_phy && priv->last_phy_res[0])
- rx_start = (struct iwl_rx_phy_res *)&priv->last_phy_res[1];
-
- if (!rx_start) {
- IWL_ERR(priv, "MPDU frame without a PHY data\n");
- return;
- }
- if (include_phy) {
- hdr = (struct ieee80211_hdr *)((u8 *) &rx_start[1] +
- rx_start->cfg_phy_cnt);
-
- len = le16_to_cpu(rx_start->byte_count);
-
- rx_end = (__le32 *)((u8 *) &pkt->u.raw[0] +
- sizeof(struct iwl_rx_phy_res) +
- rx_start->cfg_phy_cnt + len);
-
- } else {
- struct iwl4965_rx_mpdu_res_start *amsdu =
- (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
-
- hdr = (struct ieee80211_hdr *)(pkt->u.raw +
- sizeof(struct iwl4965_rx_mpdu_res_start));
- len = le16_to_cpu(amsdu->byte_count);
- rx_start->byte_count = amsdu->byte_count;
- rx_end = (__le32 *) (((u8 *) hdr) + len);
- }
-
- ampdu_status = le32_to_cpu(*rx_end);
- skblen = ((u8 *) rx_end - (u8 *) &pkt->u.raw[0]) + sizeof(u32);
-
- if (!include_phy) {
- /* New status scheme, need to translate */
- ampdu_status_legacy = ampdu_status;
- ampdu_status = iwl_translate_rx_status(priv, ampdu_status);
- }
-
- /* start from MAC */
- skb_reserve(rxb->skb, (void *)hdr - (void *)pkt);
- skb_put(rxb->skb, len); /* end where data ends */
-
/* We only process data packets if the interface is open */
if (unlikely(!priv->is_open)) {
IWL_DEBUG_DROP_LIMIT(priv,
@@ -915,13 +866,15 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
return;
}
- hdr = (struct ieee80211_hdr *)rxb->skb->data;
-
- /* in case of HW accelerated crypto and bad decryption, drop */
+ /* In case of HW accelerated crypto and bad decryption, drop */
if (!priv->cfg->mod_params->sw_crypto &&
iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
return;
+ /* Resize SKB from mac header to end of packet */
+ skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data);
+ skb_put(rxb->skb, len);
+
iwl_update_stats(priv, false, hdr->frame_control, len);
memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
ieee80211_rx_irqsafe(priv->hw, rxb->skb);
@@ -955,25 +908,66 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
struct ieee80211_hdr *header;
struct ieee80211_rx_status rx_status;
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- /* Use phy data (Rx signal strength, etc.) contained within
- * this rx packet for legacy frames,
- * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */
- int include_phy = (pkt->hdr.cmd == REPLY_RX);
- struct iwl_rx_phy_res *rx_start = (include_phy) ?
- (struct iwl_rx_phy_res *)&(pkt->u.raw[0]) :
- (struct iwl_rx_phy_res *)&priv->last_phy_res[1];
- __le32 *rx_end;
- unsigned int len = 0;
+ struct iwl_rx_phy_res *phy_res;
+ __le32 rx_pkt_status;
+ struct iwl4965_rx_mpdu_res_start *amsdu;
+ u32 len;
+ u32 ampdu_status;
u16 fc;
- u8 network_packet;
- rx_status.mactime = le64_to_cpu(rx_start->timestamp);
+ /**
+ * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
+ * REPLY_RX: physical layer info is in this buffer
+ * REPLY_RX_MPDU_CMD: physical layer info was sent in separate
+ * command and cached in priv->last_phy_res
+ *
+ * Here we set up local variables depending on which command is
+ * received.
+ */
+ if (pkt->hdr.cmd == REPLY_RX) {
+ phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
+ header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
+ + phy_res->cfg_phy_cnt);
+
+ len = le16_to_cpu(phy_res->byte_count);
+ rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
+ phy_res->cfg_phy_cnt + len);
+ ampdu_status = le32_to_cpu(rx_pkt_status);
+ } else {
+ if (!priv->last_phy_res[0]) {
+ IWL_ERR(priv, "MPDU frame without cached PHY data\n");
+ return;
+ }
+ phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1];
+ amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
+ header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
+ len = le16_to_cpu(amsdu->byte_count);
+ rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
+ ampdu_status = iwl_translate_rx_status(priv,
+ le32_to_cpu(rx_pkt_status));
+ }
+
+ if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
+ IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
+ phy_res->cfg_phy_cnt);
+ return;
+ }
+
+ if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
+ !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
+ IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
+ le32_to_cpu(rx_pkt_status));
+ return;
+ }
+
+ /* rx_status carries information about the packet to mac80211 */
+ rx_status.mactime = le64_to_cpu(phy_res->timestamp);
rx_status.freq =
- ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel));
- rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+ ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel));
+ rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
rx_status.rate_idx =
- iwl_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags));
+ iwl_hwrate_to_plcp_idx(le32_to_cpu(phy_res->rate_n_flags));
if (rx_status.band == IEEE80211_BAND_5GHZ)
rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
@@ -983,54 +977,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
* this W/A doesn't propagate it to the mac80211 */
/*rx_status.flag |= RX_FLAG_TSFT;*/
- if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
- IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
- rx_start->cfg_phy_cnt);
- return;
- }
-
- if (!include_phy) {
- if (priv->last_phy_res[0])
- rx_start = (struct iwl_rx_phy_res *)
- &priv->last_phy_res[1];
- else
- rx_start = NULL;
- }
-
- if (!rx_start) {
- IWL_ERR(priv, "MPDU frame without a PHY data\n");
- return;
- }
-
- if (include_phy) {
- header = (struct ieee80211_hdr *)((u8 *) &rx_start[1]
- + rx_start->cfg_phy_cnt);
-
- len = le16_to_cpu(rx_start->byte_count);
- rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt +
- sizeof(struct iwl_rx_phy_res) + len);
- } else {
- struct iwl4965_rx_mpdu_res_start *amsdu =
- (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
-
- header = (void *)(pkt->u.raw +
- sizeof(struct iwl4965_rx_mpdu_res_start));
- len = le16_to_cpu(amsdu->byte_count);
- rx_end = (__le32 *) (pkt->u.raw +
- sizeof(struct iwl4965_rx_mpdu_res_start) + len);
- }
-
- if (!(*rx_end & RX_RES_STATUS_NO_CRC32_ERROR) ||
- !(*rx_end & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
- IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
- le32_to_cpu(*rx_end));
- return;
- }
-
- priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
+ priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
/* Find max signal strength (dBm) among 3 antenna/receiver chains */
- rx_status.signal = iwl_calc_rssi(priv, rx_start);
+ rx_status.signal = iwl_calc_rssi(priv, phy_res);
/* Meaningful noise values are available only from beacon statistics,
* which are gathered only when associated, and indicate noise
@@ -1050,10 +1000,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
if (!iwl_is_associated(priv))
priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
- /* Set "1" to report good data frames in groups of 100 */
#ifdef CONFIG_IWLWIFI_DEBUG
+ /* Set "1" to report good data frames in groups of 100 */
if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX))
- iwl_dbg_report_frame(priv, rx_start, len, header, 1);
+ iwl_dbg_report_frame(priv, phy_res, len, header, 1);
#endif
iwl_dbg_log_rx_data_frame(priv, len, header);
IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n",
@@ -1073,18 +1023,18 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
* new 802.11n radiotap field "RX chains" that is defined
* as a bitmask.
*/
- rx_status.antenna = le16_to_cpu(rx_start->phy_flags &
- RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
+ rx_status.antenna =
+ le16_to_cpu(phy_res->phy_flags & RX_RES_PHY_FLAGS_ANTENNA_MSK)
+ >> RX_RES_PHY_FLAGS_ANTENNA_POS;
/* set the preamble flag if appropriate */
- if (rx_start->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+ if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
rx_status.flag |= RX_FLAG_SHORTPRE;
- network_packet = iwl_is_network_packet(priv, header);
- if (network_packet) {
+ if (iwl_is_network_packet(priv, header)) {
priv->last_rx_rssi = rx_status.signal;
priv->last_beacon_time = priv->ucode_beacon_time;
- priv->last_tsf = le64_to_cpu(rx_start->timestamp);
+ priv->last_tsf = le64_to_cpu(phy_res->timestamp);
}
fc = le16_to_cpu(header->frame_control);
@@ -1096,8 +1046,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
header->addr2);
/* fall through */
default:
- iwl_pass_packet_to_mac80211(priv, include_phy, rxb,
- &rx_status);
+ iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
+ rxb, &rx_status);
break;
}
--
1.5.6.3
next prev parent reply other threads:[~2009-08-13 20:31 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
2009-08-13 20:30 ` [PATCH 01/13] iwlwifi: prevent read outside array bounds Reinette Chatre
2009-08-13 20:30 ` [PATCH 02/13] iwlwifi: remove unused HT configuration entry tx_chan_width Reinette Chatre
2009-08-13 20:30 ` [PATCH 03/13] iwlwifi: include HT configuration when adding stations through rs_rate_init Reinette Chatre
2009-08-13 20:30 ` [PATCH 04/13] iwlwifi: cleanup HT40 extension channels setup Reinette Chatre
2009-08-13 20:30 ` [PATCH 05/13] iwlwifi: traverse linklist to find the valid OTP block Reinette Chatre
2009-08-13 20:30 ` [PATCH 06/13] iwlwifi: remove unused members of iwl_ht_info Reinette Chatre
2009-08-13 20:30 ` Reinette Chatre [this message]
2009-08-13 20:30 ` [PATCH 08/13] iwlwifi: configure HT40 channels in iwl_mac_config Reinette Chatre
2009-08-13 20:30 ` [PATCH 09/13] iwlwifi: check short GI support per-station rather than globally Reinette Chatre
2009-08-13 20:30 ` [PATCH 10/13] iwlwifi: use station HT capabilities and BSS operating mode for Green-field Reinette Chatre
2009-08-13 20:31 ` [PATCH 11/13] iwlwifi: add thermal throttling support to 5150 Reinette Chatre
2009-08-13 20:31 ` [PATCH 12/13] iwlwifi: fix erroneous use of iwl_rx_packet.len as a length Reinette Chatre
2009-08-13 20:31 ` [PATCH 13/13] iwlwifi: disable PS by default Reinette Chatre
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1250195462-15811-8-git-send-email-reinette.chatre@intel.com \
--to=reinette.chatre@intel.com \
--cc=daniel.c.halperin@intel.com \
--cc=ipw3945-devel@lists.sourceforge.net \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox