2014-01-29 19:05:28

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 00/13] eliminate some ath9k_htc code

This patch set moves most common RX code from ath9k/recv.c to
common.c without any additional changes and reworks ath9k_htc RX code
to make use of new common functions.
Since ath9k_htc part was more intrusive I made tests in STA and AP modes. No noticeable regressions was introduced.
Last patch is important for debugging FW crashes.

Oleksij Rempel (13):
ath: add last_rssi to ath_common
ath9k: move ath9k_process_rssi to common.c
ath9k: move ath9k_process_rate to common.c
ath9k: move ath9k_rx_accept to common.c
ath9k_htc: add rx header converter to make it usable by ath9k
ath9k_htc: use ath9k_cmn_process_rssi
ath9k_htc: use ath9k_cmn_process_rate
ath9k_htc: use ath9k_cmn_rx_accept
ath9k_htc: sync rx_status-> related code with ath9k
ath9k: move ath9k_rx_skb_postprocess to common.c
ath9k_htc: use ath9k_cmn_rx_skb_postprocess
ath9k_htc: remove useless memcpy
ath9k_htc: catch fw panic pattern

drivers/net/wireless/ath/ath.h | 2 +
drivers/net/wireless/ath/ath9k/ath9k.h | 1 -
drivers/net/wireless/ath/ath9k/common.c | 244 +++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/common.h | 19 ++
drivers/net/wireless/ath/ath9k/htc.h | 1 -
drivers/net/wireless/ath/ath9k/htc_drv_init.c | 1 +
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 1 +
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 180 ++++++-----------
drivers/net/wireless/ath/ath9k/htc_hst.c | 36 ++++
drivers/net/wireless/ath/ath9k/htc_hst.h | 12 ++
drivers/net/wireless/ath/ath9k/init.c | 2 +-
drivers/net/wireless/ath/ath9k/mac.h | 9 +-
drivers/net/wireless/ath/ath9k/main.c | 2 +-
drivers/net/wireless/ath/ath9k/recv.c | 266 ++------------------------
14 files changed, 392 insertions(+), 384 deletions(-)

--
1.8.5.3



2014-01-29 19:08:42

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 12/13] ath9k_htc: remove useless memcpy

after switch to common fucntions we do not need this memcpy any more.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index c4368c4..17e4d83 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -994,8 +994,6 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
ath9k_htc_err_stat_rx(priv, rxstatus);

/* Get the RX status information */
- memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
- skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);

memset(rx_status, 0, sizeof(struct ieee80211_rx_status));

@@ -1004,7 +1002,11 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
ath_err(common, "rx_stats allocation filed!\n");
goto err_nofree;
}
- rx_status_htc_to_ath(rx_stats, &rxbuf->rxstatus);
+ /* Copy everything from ath_htc_rx_status (HTC_RX_FRAME_HEADER).
+ * After this, we can drop this part of skb. */
+ rx_status_htc_to_ath(rx_stats, rxstatus);
+ rx_status->mactime = be64_to_cpu(rxstatus->rs_tstamp);
+ skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);

/*
* everything but the rate is checked here, the rate check is done
@@ -1024,8 +1026,6 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
rx_stats->is_mybeacon = ath_is_mybeacon(common, hdr);
ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status);

- rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
-
rx_status->band = ah->curchan->chan->band;
rx_status->freq = ah->curchan->chan->center_freq;
rx_status->antenna = rx_stats->rs_antenna;
--
1.8.5.3


2014-01-29 19:08:03

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 07/13] ath9k_htc: use ath9k_cmn_process_rate

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 40 ++-------------------------
1 file changed, 2 insertions(+), 38 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 99d5118..de75224 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -929,42 +929,6 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv)
ath9k_hw_startpcureceive(priv->ah, test_bit(OP_SCANNING, &priv->op_flags));
}

-static void ath9k_process_rate(struct ieee80211_hw *hw,
- struct ieee80211_rx_status *rxs,
- u8 rx_rate, u8 rs_flags)
-{
- struct ieee80211_supported_band *sband;
- enum ieee80211_band band;
- unsigned int i = 0;
-
- if (rx_rate & 0x80) {
- /* HT rate */
- rxs->flag |= RX_FLAG_HT;
- if (rs_flags & ATH9K_RX_2040)
- rxs->flag |= RX_FLAG_40MHZ;
- if (rs_flags & ATH9K_RX_GI)
- rxs->flag |= RX_FLAG_SHORT_GI;
- rxs->rate_idx = rx_rate & 0x7f;
- return;
- }
-
- band = hw->conf.chandef.chan->band;
- sband = hw->wiphy->bands[band];
-
- for (i = 0; i < sband->n_bitrates; i++) {
- if (sband->bitrates[i].hw_value == rx_rate) {
- rxs->rate_idx = i;
- return;
- }
- if (sband->bitrates[i].hw_value_short == rx_rate) {
- rxs->rate_idx = i;
- rxs->flag |= RX_FLAG_SHORTPRE;
- return;
- }
- }
-
-}
-
static inline void conver_htc_flag(struct ath_rx_status *rx_stats,
struct ath_htc_rx_status *rxstatus)
{
@@ -1103,9 +1067,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
}
}

- ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate,
- rxbuf->rxstatus.rs_flags);

+ if (ath9k_cmn_process_rate(common, hw, rx_stats, rx_status))
+ goto rx_next;

rx_stats->is_mybeacon = ath_is_mybeacon(common, hdr);
ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status);
--
1.8.5.3


2014-01-29 19:08:49

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 13/13] ath9k_htc: catch fw panic pattern

... and print what we get.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/htc_hst.c | 36 ++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/htc_hst.h | 12 +++++++++++
2 files changed, 48 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index aac4a40..a0ff5b6 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -358,6 +358,36 @@ ret:
kfree_skb(skb);
}

+static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle,
+ struct sk_buff *skb)
+{
+ uint32_t *pattern = (uint32_t *)skb->data;
+
+ switch (*pattern) {
+ case 0x33221199:
+ {
+ struct htc_panic_bad_vaddr *htc_panic;
+ htc_panic = (struct htc_panic_bad_vaddr *) skb->data;
+ dev_err(htc_handle->dev, "ath: firmware panic! "
+ "exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n",
+ htc_panic->exccause, htc_panic->pc,
+ htc_panic->badvaddr);
+ break;
+ }
+ case 0x33221299:
+ {
+ struct htc_panic_bad_epid *htc_panic;
+ htc_panic = (struct htc_panic_bad_epid *) skb->data;
+ dev_err(htc_handle->dev, "ath: firmware panic! "
+ "bad epid: 0x%08x\n", htc_panic->epid);
+ break;
+ }
+ default:
+ dev_err(htc_handle->dev, "ath: uknown panic pattern!\n");
+ break;
+ }
+}
+
/*
* HTC Messages are handled directly here and the obtained SKB
* is freed.
@@ -379,6 +409,12 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
htc_hdr = (struct htc_frame_hdr *) skb->data;
epid = htc_hdr->endpoint_id;

+ if (epid == 0x99) {
+ ath9k_htc_fw_panic_report(htc_handle, skb);
+ kfree_skb(skb);
+ return;
+ }
+
if (epid >= ENDPOINT_MAX) {
if (pipe_id != USB_REG_IN_PIPE)
dev_kfree_skb_any(skb);
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h
index e1ffbb6..06474cc 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.h
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.h
@@ -77,6 +77,18 @@ struct htc_config_pipe_msg {
u8 credits;
} __packed;

+struct htc_panic_bad_vaddr {
+ __be32 pattern;
+ __be32 exccause;
+ __be32 pc;
+ __be32 badvaddr;
+} __packed;
+
+struct htc_panic_bad_epid {
+ __be32 pattern;
+ __be32 epid;
+} __packed;
+
struct htc_ep_callbacks {
void *priv;
void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok);
--
1.8.5.3


2014-01-29 19:08:17

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 09/13] ath9k_htc: sync rx_status-> related code with ath9k

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index e55659b..7321b64 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -970,6 +970,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
struct ieee80211_hw *hw = priv->hw;
struct sk_buff *skb = rxbuf->skb;
struct ath_common *common = ath9k_hw_common(priv->ah);
+ struct ath_hw *ah = common->ah;
struct ath_htc_rx_status *rxstatus;
struct ath_rx_status *rx_stats;
int hdrlen, padsize;
@@ -1046,10 +1047,10 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status);

rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
- rx_status->band = hw->conf.chandef.chan->band;
- rx_status->freq = hw->conf.chandef.chan->center_freq;
- rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
- rx_status->antenna = rxbuf->rxstatus.rs_antenna;
+
+ rx_status->band = ah->curchan->chan->band;
+ rx_status->freq = ah->curchan->chan->center_freq;
+ rx_status->antenna = rx_stats->rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_END;

kfree(rx_stats);
--
1.8.5.3


2014-01-29 19:07:33

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 03/13] ath9k: move ath9k_process_rate to common.c

we can reuse this function in ath9k_htc

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/common.c | 42 +++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/common.h | 4 +++
drivers/net/wireless/ath/ath9k/recv.c | 59 +++++----------------------------
3 files changed, 54 insertions(+), 51 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 7028c52..120fd46 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -27,6 +27,48 @@ MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
MODULE_LICENSE("Dual BSD/GPL");

+int ath9k_cmn_process_rate(struct ath_common *common,
+ struct ieee80211_hw *hw,
+ struct ath_rx_status *rx_stats,
+ struct ieee80211_rx_status *rxs)
+{
+ struct ieee80211_supported_band *sband;
+ enum ieee80211_band band;
+ unsigned int i = 0;
+ struct ath_hw *ah = common->ah;
+
+ band = ah->curchan->chan->band;
+ sband = hw->wiphy->bands[band];
+
+ if (IS_CHAN_QUARTER_RATE(ah->curchan))
+ rxs->flag |= RX_FLAG_5MHZ;
+ else if (IS_CHAN_HALF_RATE(ah->curchan))
+ rxs->flag |= RX_FLAG_10MHZ;
+
+ if (rx_stats->rs_rate & 0x80) {
+ /* HT rate */
+ rxs->flag |= RX_FLAG_HT;
+ rxs->flag |= rx_stats->flag;
+ rxs->rate_idx = rx_stats->rs_rate & 0x7f;
+ return 0;
+ }
+
+ for (i = 0; i < sband->n_bitrates; i++) {
+ if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
+ rxs->rate_idx = i;
+ return 0;
+ }
+ if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
+ rxs->flag |= RX_FLAG_SHORTPRE;
+ rxs->rate_idx = i;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(ath9k_cmn_process_rate);
+
void ath9k_cmn_process_rssi(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index aaf4a9b5..729482f 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -42,6 +42,10 @@
#define ATH_EP_RND(x, mul) \
(((x) + ((mul)/2)) / (mul))

+int ath9k_cmn_process_rate(struct ath_common *common,
+ struct ieee80211_hw *hw,
+ struct ath_rx_status *rx_stats,
+ struct ieee80211_rx_status *rxs);
void ath9k_cmn_process_rssi(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 5229e63..ab6a86c 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -841,56 +841,6 @@ static bool ath9k_rx_accept(struct ath_common *common,
return true;
}

-static int ath9k_process_rate(struct ath_common *common,
- struct ieee80211_hw *hw,
- struct ath_rx_status *rx_stats,
- struct ieee80211_rx_status *rxs)
-{
- struct ieee80211_supported_band *sband;
- enum ieee80211_band band;
- unsigned int i = 0;
- struct ath_softc __maybe_unused *sc = common->priv;
- struct ath_hw *ah = sc->sc_ah;
-
- band = ah->curchan->chan->band;
- sband = hw->wiphy->bands[band];
-
- if (IS_CHAN_QUARTER_RATE(ah->curchan))
- rxs->flag |= RX_FLAG_5MHZ;
- else if (IS_CHAN_HALF_RATE(ah->curchan))
- rxs->flag |= RX_FLAG_10MHZ;
-
- if (rx_stats->rs_rate & 0x80) {
- /* HT rate */
- rxs->flag |= RX_FLAG_HT;
- rxs->flag |= rx_stats->flag;
- rxs->rate_idx = rx_stats->rs_rate & 0x7f;
- return 0;
- }
-
- for (i = 0; i < sband->n_bitrates; i++) {
- if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
- rxs->rate_idx = i;
- return 0;
- }
- if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
- rxs->flag |= RX_FLAG_SHORTPRE;
- rxs->rate_idx = i;
- return 0;
- }
- }
-
- /*
- * No valid hardware bitrate found -- we should not get here
- * because hardware has already validated this frame as OK.
- */
- ath_dbg(common, ANY,
- "unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
- rx_stats->rs_rate);
- RX_STAT_INC(rx_rate_err);
- return -EINVAL;
-}
-
static void ath9k_process_tsf(struct ath_rx_status *rs,
struct ieee80211_rx_status *rxs,
u64 tsf)
@@ -1007,7 +957,14 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
goto exit;
}

- if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
+ if (ath9k_cmn_process_rate(common, hw, rx_stats, rx_status)) {
+ /*
+ * No valid hardware bitrate found -- we should not get here
+ * because hardware has already validated this frame as OK.
+ */
+ ath_dbg(common, ANY, "unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
+ rx_stats->rs_rate);
+ RX_STAT_INC(rx_rate_err);
ret =-EINVAL;
goto exit;
}
--
1.8.5.3


2014-01-29 19:07:48

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 05/13] ath9k_htc: add rx header converter to make it usable by ath9k

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 43 +++++++++++++++++++++++++++
1 file changed, 43 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 12e0f32..8a63f67 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -966,6 +966,38 @@ static void ath9k_process_rate(struct ieee80211_hw *hw,

}

+static inline void conver_htc_flag(struct ath_rx_status *rx_stats,
+ struct ath_htc_rx_status *rxstatus)
+{
+ if (rxstatus->rs_flags & ATH9K_RX_2040)
+ rx_stats->flag |= RX_FLAG_40MHZ;
+ if (rxstatus->rs_flags & ATH9K_RX_GI)
+ rx_stats->flag |= RX_FLAG_SHORT_GI;
+}
+
+static void rx_status_htc_to_ath(struct ath_rx_status *rx_stats,
+ struct ath_htc_rx_status *rxstatus)
+{
+ rx_stats->rs_datalen = rxstatus->rs_datalen;
+ rx_stats->rs_status = rxstatus->rs_status;
+ rx_stats->rs_phyerr = rxstatus->rs_phyerr;
+ rx_stats->rs_rssi = rxstatus->rs_rssi;
+ rx_stats->rs_keyix = rxstatus->rs_keyix;
+ rx_stats->rs_rate = rxstatus->rs_rate;
+ rx_stats->rs_antenna = rxstatus->rs_antenna;
+ rx_stats->rs_more = rxstatus->rs_more;
+
+ memcpy(rx_stats->rs_rssi_ctl, rxstatus->rs_rssi_ctl,
+ sizeof(rx_stats->rs_rssi_ctl));
+ memcpy(rx_stats->rs_rssi_ext, rxstatus->rs_rssi_ext,
+ sizeof(rx_stats->rs_rssi_ext));
+
+ rx_stats->rs_isaggr = rxstatus->rs_isaggr;
+ rx_stats->rs_moreaggr = rxstatus->rs_moreaggr;
+ rx_stats->rs_num_delims = rxstatus->rs_num_delims;
+ conver_htc_flag(rx_stats, rxstatus);
+}
+
static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
struct ath9k_htc_rxbuf *rxbuf,
struct ieee80211_rx_status *rx_status)
@@ -976,6 +1008,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
struct sk_buff *skb = rxbuf->skb;
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath_htc_rx_status *rxstatus;
+ struct ath_rx_status *rx_stats;
int hdrlen, padsize;
int last_rssi = ATH_RSSI_DUMMY_MARKER;
__le16 fc;
@@ -1014,6 +1047,13 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,

memset(rx_status, 0, sizeof(struct ieee80211_rx_status));

+ rx_stats = kzalloc(sizeof(struct ath_rx_status), GFP_KERNEL);
+ if (unlikely(rx_stats == NULL)) {
+ ath_err(common, "rx_stats allocation filed!\n");
+ goto err_nofree;
+ }
+ rx_status_htc_to_ath(rx_stats, &rxbuf->rxstatus);
+
if (rxbuf->rxstatus.rs_status != 0) {
if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_CRC)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
@@ -1094,9 +1134,12 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
rx_status->antenna = rxbuf->rxstatus.rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_END;

+ kfree(rx_stats);
return true;

rx_next:
+ kfree(rx_stats);
+err_nofree:
return false;
}

--
1.8.5.3


2014-01-29 19:08:34

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 11/13] ath9k_htc: use ath9k_cmn_rx_skb_postprocess

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 28 +++------------------------
1 file changed, 3 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 7321b64..c4368c4 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -973,9 +973,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
struct ath_hw *ah = common->ah;
struct ath_htc_rx_status *rxstatus;
struct ath_rx_status *rx_stats;
- int hdrlen, padsize;
bool decrypt_error;
- __le16 fc;

if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
ath_err(common, "Corrupted RX frame, dropping (len: %d)\n",
@@ -999,16 +997,6 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);

- hdr = (struct ieee80211_hdr *)skb->data;
- fc = hdr->frame_control;
- hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-
- padsize = hdrlen & 3;
- if (padsize && skb->len >= hdrlen+padsize+FCS_LEN) {
- memmove(skb->data + padsize, skb->data, hdrlen);
- skb_pull(skb, padsize);
- }
-
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));

rx_stats = kzalloc(sizeof(struct ath_rx_status), GFP_KERNEL);
@@ -1022,23 +1010,13 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
* everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame.
*/
+ hdr = (struct ieee80211_hdr *)skb->data;
if (!ath9k_cmn_rx_accept(common, hdr, rx_status, rx_stats,
&decrypt_error, priv->rxfilter))
goto rx_next;

- if (!(rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT)) {
- u8 keyix;
- keyix = rxbuf->rxstatus.rs_keyix;
- if (keyix != ATH9K_RXKEYIX_INVALID) {
- rx_status->flag |= RX_FLAG_DECRYPTED;
- } else if (ieee80211_has_protected(fc) &&
- skb->len >= hdrlen + 4) {
- keyix = skb->data[hdrlen + 3] >> 6;
- if (test_bit(keyix, common->keymap))
- rx_status->flag |= RX_FLAG_DECRYPTED;
- }
- }
-
+ ath9k_cmn_rx_skb_postprocess(common, skb, rx_stats,
+ rx_status, decrypt_error);

if (ath9k_cmn_process_rate(common, hw, rx_stats, rx_status))
goto rx_next;
--
1.8.5.3


2014-01-29 19:07:23

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 02/13] ath9k: move ath9k_process_rssi to common.c

we can reuse this fucntion on ath9k_htc.
Now we will need to use common version last_rssi, so switch
it too.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/ath9k.h | 1 -
drivers/net/wireless/ath/ath9k/common.c | 62 ++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/common.h | 4 +++
drivers/net/wireless/ath/ath9k/init.c | 2 +-
drivers/net/wireless/ath/ath9k/main.c | 2 +-
drivers/net/wireless/ath/ath9k/recv.c | 64 +--------------------------------
6 files changed, 69 insertions(+), 66 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index b5ac32c..4ce3787 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -757,7 +757,6 @@ struct ath_softc {
#endif

struct ath9k_hw_cal_data caldata;
- int last_rssi;

#ifdef CONFIG_ATH9K_DEBUGFS
struct ath9k_debug debug;
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 768c733..7028c52 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -27,6 +27,68 @@ MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
MODULE_LICENSE("Dual BSD/GPL");

+void ath9k_cmn_process_rssi(struct ath_common *common,
+ struct ieee80211_hw *hw,
+ struct ath_rx_status *rx_stats,
+ struct ieee80211_rx_status *rxs)
+{
+ struct ath_hw *ah = common->ah;
+ int last_rssi;
+ int rssi = rx_stats->rs_rssi;
+ int i, j;
+
+ /*
+ * RSSI is not available for subframes in an A-MPDU.
+ */
+ if (rx_stats->rs_moreaggr) {
+ rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
+ return;
+ }
+
+ /*
+ * Check if the RSSI for the last subframe in an A-MPDU
+ * or an unaggregated frame is valid.
+ */
+ if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
+ rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
+ return;
+ }
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
+ s8 rssi;
+
+ if (!(ah->rxchainmask & BIT(i)))
+ continue;
+
+ rssi = rx_stats->rs_rssi_ctl[i];
+ if (rssi != ATH9K_RSSI_BAD) {
+ rxs->chains |= BIT(j);
+ rxs->chain_signal[j] = ah->noise + rssi;
+ }
+ j++;
+ }
+
+ /*
+ * Update Beacon RSSI, this is used by ANI.
+ */
+ if (rx_stats->is_mybeacon &&
+ ((ah->opmode == NL80211_IFTYPE_STATION) ||
+ (ah->opmode == NL80211_IFTYPE_ADHOC))) {
+ ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi);
+ last_rssi = common->last_rssi;
+
+ if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+ rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
+ if (rssi < 0)
+ rssi = 0;
+
+ ah->stats.avgbrssi = rssi;
+ }
+
+ rxs->signal = ah->noise + rx_stats->rs_rssi;
+}
+EXPORT_SYMBOL(ath9k_cmn_process_rssi);
+
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index eb85e1b..aaf4a9b5 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -42,6 +42,10 @@
#define ATH_EP_RND(x, mul) \
(((x) + ((mul)/2)) / (mul))

+void ath9k_cmn_process_rssi(struct ath_common *common,
+ struct ieee80211_hw *hw,
+ struct ath_rx_status *rx_stats,
+ struct ieee80211_rx_status *rxs);
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw,
struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index c36de30..00e0f60 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -534,7 +534,7 @@ static void ath9k_init_misc(struct ath_softc *sc)

setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);

- sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+ common->last_rssi = ATH_RSSI_DUMMY_MARKER;
sc->config.txpowlimit = ATH_TXPOWER_MAX;
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
sc->beacon.slottime = ATH9K_SLOT_TIME_9;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 5924f72..c3e15f8 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1609,7 +1609,7 @@ static void ath9k_set_assoc_state(struct ath_softc *sc,
common->curaid = bss_conf->aid;
ath9k_hw_write_associd(sc->sc_ah);

- sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+ common->last_rssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;

spin_lock_irqsave(&sc->sc_pm_lock, flags);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index a0ebdd0..5229e63 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -891,68 +891,6 @@ static int ath9k_process_rate(struct ath_common *common,
return -EINVAL;
}

-static void ath9k_process_rssi(struct ath_common *common,
- struct ieee80211_hw *hw,
- struct ath_rx_status *rx_stats,
- struct ieee80211_rx_status *rxs)
-{
- struct ath_softc *sc = hw->priv;
- struct ath_hw *ah = common->ah;
- int last_rssi;
- int rssi = rx_stats->rs_rssi;
- int i, j;
-
- /*
- * RSSI is not available for subframes in an A-MPDU.
- */
- if (rx_stats->rs_moreaggr) {
- rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
- return;
- }
-
- /*
- * Check if the RSSI for the last subframe in an A-MPDU
- * or an unaggregated frame is valid.
- */
- if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
- rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
- return;
- }
-
- for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
- s8 rssi;
-
- if (!(ah->rxchainmask & BIT(i)))
- continue;
-
- rssi = rx_stats->rs_rssi_ctl[i];
- if (rssi != ATH9K_RSSI_BAD) {
- rxs->chains |= BIT(j);
- rxs->chain_signal[j] = ah->noise + rssi;
- }
- j++;
- }
-
- /*
- * Update Beacon RSSI, this is used by ANI.
- */
- if (rx_stats->is_mybeacon &&
- ((ah->opmode == NL80211_IFTYPE_STATION) ||
- (ah->opmode == NL80211_IFTYPE_ADHOC))) {
- ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi);
- last_rssi = sc->last_rssi;
-
- if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
- rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
- if (rssi < 0)
- rssi = 0;
-
- ah->stats.avgbrssi = rssi;
- }
-
- rxs->signal = ah->noise + rx_stats->rs_rssi;
-}
-
static void ath9k_process_tsf(struct ath_rx_status *rs,
struct ieee80211_rx_status *rxs,
u64 tsf)
@@ -1074,7 +1012,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
goto exit;
}

- ath9k_process_rssi(common, hw, rx_stats, rx_status);
+ ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status);

rx_status->band = ah->curchan->chan->band;
rx_status->freq = ah->curchan->chan->center_freq;
--
1.8.5.3


2014-01-29 19:07:40

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 04/13] ath9k: move ath9k_rx_accept to common.c

we can reuse it on ath9k_htc

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/common.c | 88 +++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/common.h | 6 +++
drivers/net/wireless/ath/ath9k/recv.c | 88 +--------------------------------
3 files changed, 95 insertions(+), 87 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 120fd46..5c0d949 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -27,6 +27,94 @@ MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
MODULE_LICENSE("Dual BSD/GPL");

+/* Assumes you've already done the endian to CPU conversion */
+bool ath9k_cmn_rx_accept(struct ath_common *common,
+ struct ieee80211_hdr *hdr,
+ struct ieee80211_rx_status *rxs,
+ struct ath_rx_status *rx_stats,
+ bool *decrypt_error,
+ unsigned int rxfilter)
+{
+ struct ath_hw *ah = common->ah;
+ bool is_mc, is_valid_tkip, strip_mic, mic_error;
+ __le16 fc;
+
+ fc = hdr->frame_control;
+
+ is_mc = !!is_multicast_ether_addr(hdr->addr1);
+ is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
+ test_bit(rx_stats->rs_keyix, common->tkip_keymap);
+ strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
+ ieee80211_has_protected(fc) &&
+ !(rx_stats->rs_status &
+ (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
+ ATH9K_RXERR_KEYMISS));
+
+ /*
+ * Key miss events are only relevant for pairwise keys where the
+ * descriptor does contain a valid key index. This has been observed
+ * mostly with CCMP encryption.
+ */
+ if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
+ !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
+ rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
+
+ mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
+ !ieee80211_has_morefrags(fc) &&
+ !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
+ (rx_stats->rs_status & ATH9K_RXERR_MIC);
+
+ /*
+ * The rx_stats->rs_status will not be set until the end of the
+ * chained descriptors so it can be ignored if rs_more is set. The
+ * rs_more will be false at the last element of the chained
+ * descriptors.
+ */
+ if (rx_stats->rs_status != 0) {
+ u8 status_mask;
+
+ if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
+ rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
+ mic_error = false;
+ }
+
+ if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
+ (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
+ *decrypt_error = true;
+ mic_error = false;
+ }
+
+
+ /*
+ * Reject error frames with the exception of
+ * decryption and MIC failures. For monitor mode,
+ * we also ignore the CRC error.
+ */
+ status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
+ ATH9K_RXERR_KEYMISS;
+
+ if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL))
+ status_mask |= ATH9K_RXERR_CRC;
+
+ if (rx_stats->rs_status & ~status_mask)
+ return false;
+ }
+
+ /*
+ * For unicast frames the MIC error bit can have false positives,
+ * so all MIC error reports need to be validated in software.
+ * False negatives are not common, so skip software verification
+ * if the hardware considers the MIC valid.
+ */
+ if (strip_mic)
+ rxs->flag |= RX_FLAG_MMIC_STRIPPED;
+ else if (is_mc && mic_error)
+ rxs->flag |= RX_FLAG_MMIC_ERROR;
+
+ return true;
+}
+EXPORT_SYMBOL(ath9k_cmn_rx_accept);
+
int ath9k_cmn_process_rate(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 729482f..c59d3f5 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -42,6 +42,12 @@
#define ATH_EP_RND(x, mul) \
(((x) + ((mul)/2)) / (mul))

+bool ath9k_cmn_rx_accept(struct ath_common *common,
+ struct ieee80211_hdr *hdr,
+ struct ieee80211_rx_status *rxs,
+ struct ath_rx_status *rx_stats,
+ bool *decrypt_error,
+ unsigned int rxfilter);
int ath9k_cmn_process_rate(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index ab6a86c..4dedbc2 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -755,92 +755,6 @@ static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc,
return bf;
}

-/* Assumes you've already done the endian to CPU conversion */
-static bool ath9k_rx_accept(struct ath_common *common,
- struct ieee80211_hdr *hdr,
- struct ieee80211_rx_status *rxs,
- struct ath_rx_status *rx_stats,
- bool *decrypt_error)
-{
- struct ath_softc *sc = (struct ath_softc *) common->priv;
- bool is_mc, is_valid_tkip, strip_mic, mic_error;
- struct ath_hw *ah = common->ah;
- __le16 fc;
-
- fc = hdr->frame_control;
-
- is_mc = !!is_multicast_ether_addr(hdr->addr1);
- is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
- test_bit(rx_stats->rs_keyix, common->tkip_keymap);
- strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
- ieee80211_has_protected(fc) &&
- !(rx_stats->rs_status &
- (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
- ATH9K_RXERR_KEYMISS));
-
- /*
- * Key miss events are only relevant for pairwise keys where the
- * descriptor does contain a valid key index. This has been observed
- * mostly with CCMP encryption.
- */
- if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
- !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
- rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
-
- mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
- !ieee80211_has_morefrags(fc) &&
- !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
- (rx_stats->rs_status & ATH9K_RXERR_MIC);
-
- /*
- * The rx_stats->rs_status will not be set until the end of the
- * chained descriptors so it can be ignored if rs_more is set. The
- * rs_more will be false at the last element of the chained
- * descriptors.
- */
- if (rx_stats->rs_status != 0) {
- u8 status_mask;
-
- if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
- rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
- mic_error = false;
- }
-
- if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
- (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
- *decrypt_error = true;
- mic_error = false;
- }
-
- /*
- * Reject error frames with the exception of
- * decryption and MIC failures. For monitor mode,
- * we also ignore the CRC error.
- */
- status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
- ATH9K_RXERR_KEYMISS;
-
- if (ah->is_monitoring && (sc->rx.rxfilter & FIF_FCSFAIL))
- status_mask |= ATH9K_RXERR_CRC;
-
- if (rx_stats->rs_status & ~status_mask)
- return false;
- }
-
- /*
- * For unicast frames the MIC error bit can have false positives,
- * so all MIC error reports need to be validated in software.
- * False negatives are not common, so skip software verification
- * if the hardware considers the MIC valid.
- */
- if (strip_mic)
- rxs->flag |= RX_FLAG_MMIC_STRIPPED;
- else if (is_mc && mic_error)
- rxs->flag |= RX_FLAG_MMIC_ERROR;
-
- return true;
-}
-
static void ath9k_process_tsf(struct ath_rx_status *rs,
struct ieee80211_rx_status *rxs,
u64 tsf)
@@ -939,7 +853,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
* everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame.
*/
- if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) {
+ if (!ath9k_cmn_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error, sc->rx.rxfilter)) {
ret = -EINVAL;
goto exit;
}
--
1.8.5.3


2014-01-29 19:08:24

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 10/13] ath9k: move ath9k_rx_skb_postprocess to common.c

and rename it to ath9k_cmn_rx_skb_postprocess. We will use it
on ath9k_htc.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/common.c | 52 +++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/common.h | 5 +++
drivers/net/wireless/ath/ath9k/recv.c | 55 ++-------------------------------
3 files changed, 59 insertions(+), 53 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 5c0d949..c6dd7f1 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -115,6 +115,58 @@ bool ath9k_cmn_rx_accept(struct ath_common *common,
}
EXPORT_SYMBOL(ath9k_cmn_rx_accept);

+void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
+ struct sk_buff *skb,
+ struct ath_rx_status *rx_stats,
+ struct ieee80211_rx_status *rxs,
+ bool decrypt_error)
+{
+ struct ath_hw *ah = common->ah;
+ struct ieee80211_hdr *hdr;
+ int hdrlen, padpos, padsize;
+ u8 keyix;
+ __le16 fc;
+
+ /* see if any padding is done by the hw and remove it */
+ hdr = (struct ieee80211_hdr *) skb->data;
+ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+ fc = hdr->frame_control;
+ padpos = ieee80211_hdrlen(fc);
+
+ /* The MAC header is padded to have 32-bit boundary if the
+ * packet payload is non-zero. The general calculation for
+ * padsize would take into account odd header lengths:
+ * padsize = (4 - padpos % 4) % 4; However, since only
+ * even-length headers are used, padding can only be 0 or 2
+ * bytes and we can optimize this a bit. In addition, we must
+ * not try to remove padding from short control frames that do
+ * not have payload. */
+ padsize = padpos & 3;
+ if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
+ memmove(skb->data + padsize, skb->data, padpos);
+ skb_pull(skb, padsize);
+ }
+
+ keyix = rx_stats->rs_keyix;
+
+ if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
+ ieee80211_has_protected(fc)) {
+ rxs->flag |= RX_FLAG_DECRYPTED;
+ } else if (ieee80211_has_protected(fc)
+ && !decrypt_error && skb->len >= hdrlen + 4) {
+ keyix = skb->data[hdrlen + 3] >> 6;
+
+ if (test_bit(keyix, common->keymap))
+ rxs->flag |= RX_FLAG_DECRYPTED;
+ }
+ if (ah->sw_mgmt_crypto &&
+ (rxs->flag & RX_FLAG_DECRYPTED) &&
+ ieee80211_is_mgmt(fc))
+ /* Use software decrypt for management frames. */
+ rxs->flag &= ~RX_FLAG_DECRYPTED;
+}
+EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
+
int ath9k_cmn_process_rate(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index c59d3f5..38b5609 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -48,6 +48,11 @@ bool ath9k_cmn_rx_accept(struct ath_common *common,
struct ath_rx_status *rx_stats,
bool *decrypt_error,
unsigned int rxfilter);
+void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
+ struct sk_buff *skb,
+ struct ath_rx_status *rx_stats,
+ struct ieee80211_rx_status *rxs,
+ bool decrypt_error);
int ath9k_cmn_process_rate(struct ath_common *common,
struct ieee80211_hw *hw,
struct ath_rx_status *rx_stats,
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 4dedbc2..076dae1 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -901,57 +901,6 @@ exit:
return ret;
}

-static void ath9k_rx_skb_postprocess(struct ath_common *common,
- struct sk_buff *skb,
- struct ath_rx_status *rx_stats,
- struct ieee80211_rx_status *rxs,
- bool decrypt_error)
-{
- struct ath_hw *ah = common->ah;
- struct ieee80211_hdr *hdr;
- int hdrlen, padpos, padsize;
- u8 keyix;
- __le16 fc;
-
- /* see if any padding is done by the hw and remove it */
- hdr = (struct ieee80211_hdr *) skb->data;
- hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- fc = hdr->frame_control;
- padpos = ieee80211_hdrlen(fc);
-
- /* The MAC header is padded to have 32-bit boundary if the
- * packet payload is non-zero. The general calculation for
- * padsize would take into account odd header lengths:
- * padsize = (4 - padpos % 4) % 4; However, since only
- * even-length headers are used, padding can only be 0 or 2
- * bytes and we can optimize this a bit. In addition, we must
- * not try to remove padding from short control frames that do
- * not have payload. */
- padsize = padpos & 3;
- if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
- memmove(skb->data + padsize, skb->data, padpos);
- skb_pull(skb, padsize);
- }
-
- keyix = rx_stats->rs_keyix;
-
- if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
- ieee80211_has_protected(fc)) {
- rxs->flag |= RX_FLAG_DECRYPTED;
- } else if (ieee80211_has_protected(fc)
- && !decrypt_error && skb->len >= hdrlen + 4) {
- keyix = skb->data[hdrlen + 3] >> 6;
-
- if (test_bit(keyix, common->keymap))
- rxs->flag |= RX_FLAG_DECRYPTED;
- }
- if (ah->sw_mgmt_crypto &&
- (rxs->flag & RX_FLAG_DECRYPTED) &&
- ieee80211_is_mgmt(fc))
- /* Use software decrypt for management frames. */
- rxs->flag &= ~RX_FLAG_DECRYPTED;
-}
-
/*
* Run the LNA combining algorithm only in these cases:
*
@@ -1101,8 +1050,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
skb_pull(skb, ah->caps.rx_status_len);

if (!rs.rs_more)
- ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
- rxs, decrypt_error);
+ ath9k_cmn_rx_skb_postprocess(common, hdr_skb, &rs,
+ rxs, decrypt_error);

if (rs.rs_more) {
RX_STAT_INC(rx_frags);
--
1.8.5.3


2014-01-29 19:07:55

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 06/13] ath9k_htc: use ath9k_cmn_process_rssi

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/htc.h | 1 -
drivers/net/wireless/ath/ath9k/htc_drv_init.c | 1 +
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 1 +
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 21 ++-------------------
drivers/net/wireless/ath/ath9k/mac.h | 9 +++------
5 files changed, 7 insertions(+), 26 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 58da346..c75493f 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -275,7 +275,6 @@ struct ath9k_htc_rxbuf {
};

struct ath9k_htc_rx {
- int last_rssi; /* FIXME: per-STA */
struct list_head rxbuf;
spinlock_t rxbuflock;
};
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index f4e1de2..9db8aef 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -607,6 +607,7 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)

memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);

+ common->last_rssi = ATH_RSSI_DUMMY_MARKER;
priv->ah->opmode = NL80211_IFTYPE_STATION;
}

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 608d739..228549a 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1457,6 +1457,7 @@ static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)

if ((vif->type == NL80211_IFTYPE_STATION) && bss_conf->assoc) {
common->curaid = bss_conf->aid;
+ common->last_rssi = ATH_RSSI_DUMMY_MARKER;
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
}
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 8a63f67..99d5118 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -927,7 +927,6 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv)
ath9k_hw_rxena(priv->ah);
ath9k_htc_opmode_init(priv);
ath9k_hw_startpcureceive(priv->ah, test_bit(OP_SCANNING, &priv->op_flags));
- priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER;
}

static void ath9k_process_rate(struct ieee80211_hw *hw,
@@ -1010,7 +1009,6 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
struct ath_htc_rx_status *rxstatus;
struct ath_rx_status *rx_stats;
int hdrlen, padsize;
- int last_rssi = ATH_RSSI_DUMMY_MARKER;
__le16 fc;

if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
@@ -1108,24 +1106,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate,
rxbuf->rxstatus.rs_flags);

- if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD &&
- !rxbuf->rxstatus.rs_moreaggr)
- ATH_RSSI_LPF(priv->rx.last_rssi,
- rxbuf->rxstatus.rs_rssi);

- last_rssi = priv->rx.last_rssi;
-
- if (ath_is_mybeacon(common, hdr)) {
- s8 rssi = rxbuf->rxstatus.rs_rssi;
-
- if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
- rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
-
- if (rssi < 0)
- rssi = 0;
-
- priv->ah->stats.avgbrssi = rssi;
- }
+ rx_stats->is_mybeacon = ath_is_mybeacon(common, hdr);
+ ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status);

rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
rx_status->band = hw->conf.chandef.chan->band;
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 1027137..89df634 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -155,12 +155,8 @@ struct ath_htc_rx_status {
u8 rs_status;
u8 rs_phyerr;
int8_t rs_rssi;
- int8_t rs_rssi_ctl0;
- int8_t rs_rssi_ctl1;
- int8_t rs_rssi_ctl2;
- int8_t rs_rssi_ext0;
- int8_t rs_rssi_ext1;
- int8_t rs_rssi_ext2;
+ int8_t rs_rssi_ctl[3];
+ int8_t rs_rssi_ext[3];
u8 rs_keyix;
u8 rs_rate;
u8 rs_antenna;
@@ -170,6 +166,7 @@ struct ath_htc_rx_status {
u8 rs_num_delims;
u8 rs_flags;
u8 rs_dummy;
+ /* FIXME: evm* never used? */
__be32 evm0;
__be32 evm1;
__be32 evm2;
--
1.8.5.3


2014-01-29 19:05:32

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 01/13] ath: add last_rssi to ath_common

we need access to this variable from common functions.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index b59cfbe..6260b83 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -161,6 +161,8 @@ struct ath_common {
bool btcoex_enabled;
bool disable_ani;
bool bt_ant_diversity;
+
+ int last_rssi;
};

struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
--
1.8.5.3


2014-01-29 19:08:09

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH 08/13] ath9k_htc: use ath9k_cmn_rx_accept

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 45 +++++----------------------
1 file changed, 8 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index de75224..e55659b 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -973,6 +973,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
struct ath_htc_rx_status *rxstatus;
struct ath_rx_status *rx_stats;
int hdrlen, padsize;
+ bool decrypt_error;
__le16 fc;

if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
@@ -1016,43 +1017,13 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
}
rx_status_htc_to_ath(rx_stats, &rxbuf->rxstatus);

- if (rxbuf->rxstatus.rs_status != 0) {
- if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_CRC)
- rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_PHY)
- goto rx_next;
-
- if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT) {
- /* FIXME */
- } else if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_MIC) {
- if (ieee80211_is_ctl(fc))
- /*
- * Sometimes, we get invalid
- * MIC failures on valid control frames.
- * Remove these mic errors.
- */
- rxbuf->rxstatus.rs_status &= ~ATH9K_RXERR_MIC;
- else
- rx_status->flag |= RX_FLAG_MMIC_ERROR;
- }
-
- /*
- * Reject error frames with the exception of
- * decryption and MIC failures. For monitor mode,
- * we also ignore the CRC error.
- */
- if (priv->ah->opmode == NL80211_IFTYPE_MONITOR) {
- if (rxbuf->rxstatus.rs_status &
- ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
- ATH9K_RXERR_CRC))
- goto rx_next;
- } else {
- if (rxbuf->rxstatus.rs_status &
- ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
- goto rx_next;
- }
- }
- }
+ /*
+ * everything but the rate is checked here, the rate check is done
+ * separately to avoid doing two lookups for a rate for each frame.
+ */
+ if (!ath9k_cmn_rx_accept(common, hdr, rx_status, rx_stats,
+ &decrypt_error, priv->rxfilter))
+ goto rx_next;

if (!(rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT)) {
u8 keyix;
--
1.8.5.3


2014-02-03 02:10:11

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [PATCH 05/13] ath9k_htc: add rx header converter to make it usable by ath9k

Oleksij Rempel wrote:
> + rx_stats = kzalloc(sizeof(struct ath_rx_status), GFP_KERNEL);
> + if (unlikely(rx_stats == NULL)) {
> + ath_err(common, "rx_stats allocation filed!\n");
> + goto err_nofree;
> + }
> + rx_status_htc_to_ath(rx_stats, &rxbuf->rxstatus);
> +

This seems a little expensive, since this would happen for every packet,
and a memcpy is already done earlier, for storing the RX status in
rxbuf->rxstatus. Instead of using 'struct ath_htc_rx_status' in
'struct ath9k_htc_rxbuf', why can't 'struct ath_rx_status' be used ?
The values can be converted and stored directly, avoiding this alloc.

Sujith


2014-02-03 13:12:00

by Oleksij Rempel

[permalink] [raw]
Subject: Re: [PATCH 05/13] ath9k_htc: add rx header converter to make it usable by ath9k

Am 03.02.2014 13:07, schrieb Felix Fietkau:
> On 2014-02-03 12:22, Oleksij Rempel wrote:
>> Am 03.02.2014 03:09, schrieb Sujith Manoharan:
>>> Oleksij Rempel wrote:
>>>> + rx_stats = kzalloc(sizeof(struct ath_rx_status), GFP_KERNEL);
>>>> + if (unlikely(rx_stats == NULL)) {
>>>> + ath_err(common, "rx_stats allocation filed!\n");
>>>> + goto err_nofree;
>>>> + }
>>>> + rx_status_htc_to_ath(rx_stats, &rxbuf->rxstatus);
>>>> +
>>
>>> This seems a little expensive, since this would happen for every packet,
>>> and a memcpy is already done earlier, for storing the RX status in
>>> rxbuf->rxstatus. Instead of using 'struct ath_htc_rx_status' in
>>> 'struct ath9k_htc_rxbuf', why can't 'struct ath_rx_status' be used ?
>>> The values can be converted and stored directly, avoiding this alloc.
>>
>> Do you mean kzalloc or converter?
>> then memcpy is removed by patch 12/13. Converter is not effective but it
>> should prevent from confusions. At least until FW use same flags and
>> struct ath_rx_status do.
>> But i'm open for other ideas too.
> You should at least keep rx_stats on stack instead of using kzalloc,
> that would make it much faster.

You right, i'll do it.

Beside what is the smallest stack size in kernel i need to count on?


--
Regards,
Oleksij


Attachments:
signature.asc (278.00 B)
OpenPGP digital signature

2014-02-03 12:08:13

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 05/13] ath9k_htc: add rx header converter to make it usable by ath9k

On 2014-02-03 12:22, Oleksij Rempel wrote:
> Am 03.02.2014 03:09, schrieb Sujith Manoharan:
>> Oleksij Rempel wrote:
>>> + rx_stats = kzalloc(sizeof(struct ath_rx_status), GFP_KERNEL);
>>> + if (unlikely(rx_stats == NULL)) {
>>> + ath_err(common, "rx_stats allocation filed!\n");
>>> + goto err_nofree;
>>> + }
>>> + rx_status_htc_to_ath(rx_stats, &rxbuf->rxstatus);
>>> +
>
>> This seems a little expensive, since this would happen for every packet,
>> and a memcpy is already done earlier, for storing the RX status in
>> rxbuf->rxstatus. Instead of using 'struct ath_htc_rx_status' in
>> 'struct ath9k_htc_rxbuf', why can't 'struct ath_rx_status' be used ?
>> The values can be converted and stored directly, avoiding this alloc.
>
> Do you mean kzalloc or converter?
> then memcpy is removed by patch 12/13. Converter is not effective but it
> should prevent from confusions. At least until FW use same flags and
> struct ath_rx_status do.
> But i'm open for other ideas too.
You should at least keep rx_stats on stack instead of using kzalloc,
that would make it much faster.

- Felix

2014-02-03 11:22:49

by Oleksij Rempel

[permalink] [raw]
Subject: Re: [PATCH 05/13] ath9k_htc: add rx header converter to make it usable by ath9k

Am 03.02.2014 03:09, schrieb Sujith Manoharan:
> Oleksij Rempel wrote:
>> + rx_stats = kzalloc(sizeof(struct ath_rx_status), GFP_KERNEL);
>> + if (unlikely(rx_stats == NULL)) {
>> + ath_err(common, "rx_stats allocation filed!\n");
>> + goto err_nofree;
>> + }
>> + rx_status_htc_to_ath(rx_stats, &rxbuf->rxstatus);
>> +

> This seems a little expensive, since this would happen for every packet,
> and a memcpy is already done earlier, for storing the RX status in
> rxbuf->rxstatus. Instead of using 'struct ath_htc_rx_status' in
> 'struct ath9k_htc_rxbuf', why can't 'struct ath_rx_status' be used ?
> The values can be converted and stored directly, avoiding this alloc.

Do you mean kzalloc or converter?
then memcpy is removed by patch 12/13. Converter is not effective but it
should prevent from confusions. At least until FW use same flags and
struct ath_rx_status do.
But i'm open for other ideas too.

--
Regards,
Oleksij


Attachments:
signature.asc (278.00 B)
OpenPGP digital signature