* [PATCH 08/10] rt2800: status based rate flags for nomatch case
From: Stanislaw Gruszka @ 2017-02-14 12:46 UTC (permalink / raw)
To: linux-wireless; +Cc: Helmut Schaa, Felix Fietkau
In-Reply-To: <1487076368-7020-1-git-send-email-sgruszka@redhat.com>
We use skb_desc->tx_rate_flags from entry as rate[].flags even if
skb does not match status. Patch corrects flags and also fixes
mcs for legacy rates.
rt2800_rate_from_status() is based on Felix's mt76
mt76x2_mac_process_tx_rate() function.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/ralink/rt2x00/rt2800.h | 2 ++
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 35 +++++++++++++++++++++++++-
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h
index 0e7051d..480b086 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
@@ -1760,6 +1760,8 @@
#define TX_STA_FIFO_WCID FIELD32(0x0000ff00)
#define TX_STA_FIFO_SUCCESS_RATE FIELD32(0xffff0000)
#define TX_STA_FIFO_MCS FIELD32(0x007f0000)
+#define TX_STA_FIFO_BW FIELD32(0x00800000)
+#define TX_STA_FIFO_SGI FIELD32(0x01000000)
#define TX_STA_FIFO_PHYMODE FIELD32(0xc0000000)
/*
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 8a76b27..b806ff1 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -852,6 +852,39 @@ void rt2800_process_rxwi(struct queue_entry *entry,
}
EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
+static void rt2800_rate_from_status(struct skb_frame_desc *skbdesc,
+ u32 status, enum nl80211_band band)
+{
+ u8 flags = 0;
+ u8 idx = rt2x00_get_field32(status, TX_STA_FIFO_MCS);
+
+ switch (rt2x00_get_field32(status, TX_STA_FIFO_PHYMODE)) {
+ case RATE_MODE_HT_GREENFIELD:
+ flags |= IEEE80211_TX_RC_GREEN_FIELD;
+ /* fall through */
+ case RATE_MODE_HT_MIX:
+ flags |= IEEE80211_TX_RC_MCS;
+ break;
+ case RATE_MODE_OFDM:
+ if (band == NL80211_BAND_2GHZ)
+ idx += 4;
+ break;
+ case RATE_MODE_CCK:
+ if (idx >= 8)
+ idx -= 8;
+ break;
+ }
+
+ if (rt2x00_get_field32(status, TX_STA_FIFO_BW))
+ flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+
+ if (rt2x00_get_field32(status, TX_STA_FIFO_SGI))
+ flags |= IEEE80211_TX_RC_SHORT_GI;
+
+ skbdesc->tx_rate_idx = idx;
+ skbdesc->tx_rate_flags = flags;
+}
+
void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
bool match)
{
@@ -898,7 +931,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
* and provide retry count.
*/
if (unlikely((aggr == 1 && ampdu == 0 && real_mcs != mcs)) || !match) {
- skbdesc->tx_rate_idx = real_mcs;
+ rt2800_rate_from_status(skbdesc, status, rt2x00dev->curr_band);
mcs = real_mcs;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH 07/10] rt2x00: use txdone_nomatch on rt2800usb
From: Stanislaw Gruszka @ 2017-02-14 12:46 UTC (permalink / raw)
To: linux-wireless; +Cc: Helmut Schaa, Felix Fietkau
In-Reply-To: <1487076368-7020-1-git-send-email-sgruszka@redhat.com>
If we do not match skb entry, provide tx status via nomatch procedure.
Currently in that case we do rt2x00lib_txdone_noinfo(TXDONE_NOINFO),
which actually assume that entry->skb was posted without retries and
provide rate saved in skb desc as successful. Patch changed that to
rate read from TX_STAT_FIFO, however still do not provide correct
number of retries.
On SoC/PCI devices we keep providing status via standard txdone
procedure, no change in those devices, though we should thing about it.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 32 ++++++++++++++++++-------
drivers/net/wireless/ralink/rt2x00/rt2800lib.h | 3 ++-
drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 2 +-
drivers/net/wireless/ralink/rt2x00/rt2800usb.c | 18 ++++++--------
4 files changed, 34 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 5de21d2..8a76b27 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -852,7 +852,8 @@ void rt2800_process_rxwi(struct queue_entry *entry,
}
EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
+ bool match)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
@@ -860,8 +861,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
struct txdone_entry_desc txdesc;
u32 word;
u16 mcs, real_mcs;
- int aggr, ampdu;
- int wcid;
+ int aggr, ampdu, wcid, ack_req;
/*
* Obtain the status about this packet.
@@ -875,6 +875,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
real_mcs = rt2x00_get_field32(status, TX_STA_FIFO_MCS);
aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE);
wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
+ ack_req = rt2x00_get_field32(status, TX_STA_FIFO_TX_ACK_REQUIRED);
/*
* If a frame was meant to be sent as a single non-aggregated MPDU
@@ -891,18 +892,22 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
* Hence, replace the requested rate with the real tx rate to not
* confuse the rate control algortihm by providing clearly wrong
* data.
+ *
+ * FIXME: if we do not find matching entry, we tell that frame was
+ * posted without any retries. We need to find a way to fix that
+ * and provide retry count.
*/
- if (unlikely(aggr == 1 && ampdu == 0 && real_mcs != mcs)) {
+ if (unlikely((aggr == 1 && ampdu == 0 && real_mcs != mcs)) || !match) {
skbdesc->tx_rate_idx = real_mcs;
mcs = real_mcs;
}
- if (likely(wcid >= WCID_START && wcid <= WCID_END))
- skbdesc->sta = drv_data->wcid_to_sta[wcid - WCID_START];
-
if (aggr == 1 || ampdu == 1)
__set_bit(TXDONE_AMPDU, &txdesc.flags);
+ if (ack_req)
+ __set_bit(TXDONE_ACK_REQ, &txdesc.flags);
+
/*
* Ralink has a retry mechanism using a global fallback
* table. We setup this fallback table to try the immediate
@@ -934,7 +939,18 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
if (txdesc.retry)
__set_bit(TXDONE_FALLBACK, &txdesc.flags);
- rt2x00lib_txdone(entry, &txdesc);
+ if (!match) {
+ /* RCU assures non-null sta will not be freed by mac80211. */
+ rcu_read_lock();
+ if (likely(wcid >= WCID_START && wcid <= WCID_END))
+ skbdesc->sta = drv_data->wcid_to_sta[wcid - WCID_START];
+ else
+ skbdesc->sta = NULL;
+ rt2x00lib_txdone_nomatch(entry, &txdesc);
+ rcu_read_unlock();
+ } else {
+ rt2x00lib_txdone(entry, &txdesc);
+ }
}
EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index 6811d67..d9ef260 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -191,7 +191,8 @@ void rt2800_write_tx_data(struct queue_entry *entry,
struct txentry_desc *txdesc);
void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32* txwi);
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
+ bool match);
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
void rt2800_clear_beacon(struct queue_entry *entry);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
index de4790b..3ab3b53 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
@@ -239,7 +239,7 @@ static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
{
if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
rt2800_txdone_entry(entry, entry->status,
- rt2800mmio_get_txwi(entry));
+ rt2800mmio_get_txwi(entry), true);
return false;
}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
index 205a7b8..f11e3f5 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
@@ -501,8 +501,7 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
/*
* TX control handlers
*/
-static enum txdone_entry_desc_flags
-rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
+static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
{
__le32 *txwi;
u32 word;
@@ -515,7 +514,7 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
* frame.
*/
if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
- return TXDONE_FAILURE;
+ return false;
wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
@@ -537,10 +536,10 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
rt2x00_dbg(entry->queue->rt2x00dev,
"TX status report missed for queue %d entry %d\n",
entry->queue->qid, entry->entry_idx);
- return TXDONE_UNKNOWN;
+ return false;
}
- return TXDONE_SUCCESS;
+ return true;
}
static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
@@ -549,7 +548,7 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
struct queue_entry *entry;
u32 reg;
u8 qid;
- enum txdone_entry_desc_flags done_status;
+ bool match;
while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
/*
@@ -574,11 +573,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
break;
}
- done_status = rt2800usb_txdone_entry_check(entry, reg);
- if (likely(done_status == TXDONE_SUCCESS))
- rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry));
- else
- rt2x00lib_txdone_noinfo(entry, done_status);
+ match = rt2800usb_txdone_entry_check(entry, reg);
+ rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry), match);
}
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH 06/10] rt2x00: fixup fill_tx_status for nomatch case
From: Stanislaw Gruszka @ 2017-02-14 12:46 UTC (permalink / raw)
To: linux-wireless; +Cc: Helmut Schaa, Felix Fietkau
In-Reply-To: <1487076368-7020-1-git-send-email-sgruszka@redhat.com>
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 6 +++++-
drivers/net/wireless/ralink/rt2x00/rt2x00queue.h | 1 +
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index 90fc259..258d94d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -357,6 +357,9 @@ static void rt2x00lib_fill_tx_status(struct rt2x00_dev *rt2x00dev,
if (i < (IEEE80211_TX_MAX_RATES - 1))
tx_info->status.rates[i].idx = -1; /* terminate */
+ if (!test_bit(TXDONE_ACK_REQ, &txdesc->flags))
+ tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
+
if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
if (success)
tx_info->flags |= IEEE80211_TX_STAT_ACK;
@@ -375,7 +378,8 @@ static void rt2x00lib_fill_tx_status(struct rt2x00_dev *rt2x00dev,
*/
if (test_bit(TXDONE_AMPDU, &txdesc->flags) ||
tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
- tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU |
+ IEEE80211_TX_CTL_AMPDU;
tx_info->status.ampdu_len = 1;
tx_info->status.ampdu_ack_len = success ? 1 : 0;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
index 9b297fc..921f768 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
@@ -215,6 +215,7 @@ enum txdone_entry_desc_flags {
TXDONE_FAILURE,
TXDONE_EXCESSIVE_RETRY,
TXDONE_AMPDU,
+ TXDONE_ACK_REQ,
};
/**
--
1.8.3.1
^ permalink raw reply related
* [PATCH 05/10] rt2x00: add txdone nomatch function
From: Stanislaw Gruszka @ 2017-02-14 12:46 UTC (permalink / raw)
To: linux-wireless; +Cc: Helmut Schaa, Felix Fietkau
In-Reply-To: <1487076368-7020-1-git-send-email-sgruszka@redhat.com>
This txdone nomatch function will be used when we get status from the HW,
but we could not match it with any sent skb.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 2 ++
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 50 ++++++++++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 26869b3..efd6914 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -1425,6 +1425,8 @@ u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
void rt2x00lib_dmadone(struct queue_entry *entry);
void rt2x00lib_txdone(struct queue_entry *entry,
struct txdone_entry_desc *txdesc);
+void rt2x00lib_txdone_nomatch(struct queue_entry *entry,
+ struct txdone_entry_desc *txdesc);
void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status);
void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index 03b368a..90fc259 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -417,6 +417,56 @@ static void rt2x00lib_clear_entry(struct rt2x00_dev *rt2x00dev,
spin_unlock_bh(&entry->queue->tx_lock);
}
+void rt2x00lib_txdone_nomatch(struct queue_entry *entry,
+ struct txdone_entry_desc *txdesc)
+{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ struct ieee80211_tx_info txinfo = {};
+ bool success;
+
+ /*
+ * Unmap the skb.
+ */
+ rt2x00queue_unmap_skb(entry);
+
+ /*
+ * Signal that the TX descriptor is no longer in the skb.
+ */
+ skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
+
+ /*
+ * Send frame to debugfs immediately, after this call is completed
+ * we are going to overwrite the skb->cb array.
+ */
+ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry);
+
+ /*
+ * Determine if the frame has been successfully transmitted and
+ * remove BARs from our check list while checking for their
+ * TX status.
+ */
+ success =
+ rt2x00lib_txdone_bar_status(entry) ||
+ test_bit(TXDONE_SUCCESS, &txdesc->flags);
+
+ if (!test_bit(TXDONE_UNKNOWN, &txdesc->flags)) {
+ /*
+ * Update TX statistics.
+ */
+ rt2x00dev->link.qual.tx_success += success;
+ rt2x00dev->link.qual.tx_failed += !success;
+
+ rt2x00lib_fill_tx_status(rt2x00dev, &txinfo, skbdesc, txdesc,
+ success);
+ ieee80211_tx_status_noskb(rt2x00dev->hw, skbdesc->sta, &txinfo);
+ }
+
+ dev_kfree_skb_any(entry->skb);
+ rt2x00lib_clear_entry(rt2x00dev, entry);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_txdone_nomatch);
+
void rt2x00lib_txdone(struct queue_entry *entry,
struct txdone_entry_desc *txdesc)
{
--
1.8.3.1
^ permalink raw reply related
* [PATCH 04/10] rt2x00: separte clearing entry from rt2x00lib_txdone
From: Stanislaw Gruszka @ 2017-02-14 12:46 UTC (permalink / raw)
To: linux-wireless; +Cc: Helmut Schaa, Felix Fietkau
In-Reply-To: <1487076368-7020-1-git-send-email-sgruszka@redhat.com>
This makes rt2x00lib_txdone a bit simpler and will allow to reuse
code in different variant of txdone which I'm preparing.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 51 +++++++++++++++-----------
1 file changed, 29 insertions(+), 22 deletions(-)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index b5d90fe..03b368a 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -391,6 +391,32 @@ static void rt2x00lib_fill_tx_status(struct rt2x00_dev *rt2x00dev,
}
}
+static void rt2x00lib_clear_entry(struct rt2x00_dev *rt2x00dev,
+ struct queue_entry *entry)
+{
+ /*
+ * Make this entry available for reuse.
+ */
+ entry->skb = NULL;
+ entry->flags = 0;
+
+ rt2x00dev->ops->lib->clear_entry(entry);
+
+ rt2x00queue_index_inc(entry, Q_INDEX_DONE);
+
+ /*
+ * If the data queue was below the threshold before the txdone
+ * handler we must make sure the packet queue in the mac80211 stack
+ * is reenabled when the txdone handler has finished. This has to be
+ * serialized with rt2x00mac_tx(), otherwise we can wake up queue
+ * before it was stopped.
+ */
+ spin_lock_bh(&entry->queue->tx_lock);
+ if (!rt2x00queue_threshold(entry->queue))
+ rt2x00queue_unpause_queue(entry->queue);
+ spin_unlock_bh(&entry->queue->tx_lock);
+}
+
void rt2x00lib_txdone(struct queue_entry *entry,
struct txdone_entry_desc *txdesc)
{
@@ -471,30 +497,11 @@ void rt2x00lib_txdone(struct queue_entry *entry,
ieee80211_tx_status(rt2x00dev->hw, entry->skb);
else
ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
- } else
+ } else {
dev_kfree_skb_any(entry->skb);
+ }
- /*
- * Make this entry available for reuse.
- */
- entry->skb = NULL;
- entry->flags = 0;
-
- rt2x00dev->ops->lib->clear_entry(entry);
-
- rt2x00queue_index_inc(entry, Q_INDEX_DONE);
-
- /*
- * If the data queue was below the threshold before the txdone
- * handler we must make sure the packet queue in the mac80211 stack
- * is reenabled when the txdone handler has finished. This has to be
- * serialized with rt2x00mac_tx(), otherwise we can wake up queue
- * before it was stopped.
- */
- spin_lock_bh(&entry->queue->tx_lock);
- if (!rt2x00queue_threshold(entry->queue))
- rt2x00queue_unpause_queue(entry->queue);
- spin_unlock_bh(&entry->queue->tx_lock);
+ rt2x00lib_clear_entry(rt2x00dev, entry);
}
EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 03/10] rt2x00: separte filling tx status from rt2x00lib_txdone
From: Stanislaw Gruszka @ 2017-02-14 12:46 UTC (permalink / raw)
To: linux-wireless; +Cc: Helmut Schaa, Felix Fietkau
In-Reply-To: <1487076368-7020-1-git-send-email-sgruszka@redhat.com>
This makes rt2x00lib_txdone a bit simpler and will allow to reuse code
in different variant of txdone which I'm preparing.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 141 +++++++++++++------------
1 file changed, 76 insertions(+), 65 deletions(-)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index dd66781..b5d90fe 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -313,73 +313,14 @@ static inline int rt2x00lib_txdone_bar_status(struct queue_entry *entry)
return ret;
}
-void rt2x00lib_txdone(struct queue_entry *entry,
- struct txdone_entry_desc *txdesc)
+static void rt2x00lib_fill_tx_status(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_tx_info *tx_info,
+ struct skb_frame_desc *skbdesc,
+ struct txdone_entry_desc *txdesc,
+ bool success)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- unsigned int header_length, i;
u8 rate_idx, rate_flags, retry_rates;
- u8 skbdesc_flags = skbdesc->flags;
- bool success;
-
- /*
- * Unmap the skb.
- */
- rt2x00queue_unmap_skb(entry);
-
- /*
- * Remove the extra tx headroom from the skb.
- */
- skb_pull(entry->skb, rt2x00dev->extra_tx_headroom);
-
- /*
- * Signal that the TX descriptor is no longer in the skb.
- */
- skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
-
- /*
- * Determine the length of 802.11 header.
- */
- header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
-
- /*
- * Remove L2 padding which was added during
- */
- if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_L2PAD))
- rt2x00queue_remove_l2pad(entry->skb, header_length);
-
- /*
- * If the IV/EIV data was stripped from the frame before it was
- * passed to the hardware, we should now reinsert it again because
- * mac80211 will expect the same data to be present it the
- * frame as it was passed to us.
- */
- if (rt2x00_has_cap_hw_crypto(rt2x00dev))
- rt2x00crypto_tx_insert_iv(entry->skb, header_length);
-
- /*
- * Send frame to debugfs immediately, after this call is completed
- * we are going to overwrite the skb->cb array.
- */
- rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry);
-
- /*
- * Determine if the frame has been successfully transmitted and
- * remove BARs from our check list while checking for their
- * TX status.
- */
- success =
- rt2x00lib_txdone_bar_status(entry) ||
- test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
- test_bit(TXDONE_UNKNOWN, &txdesc->flags);
-
- /*
- * Update TX statistics.
- */
- rt2x00dev->link.qual.tx_success += success;
- rt2x00dev->link.qual.tx_failed += !success;
+ int i;
rate_idx = skbdesc->tx_rate_idx;
rate_flags = skbdesc->tx_rate_flags;
@@ -448,6 +389,76 @@ void rt2x00lib_txdone(struct queue_entry *entry,
else
rt2x00dev->low_level_stats.dot11RTSFailureCount++;
}
+}
+
+void rt2x00lib_txdone(struct queue_entry *entry,
+ struct txdone_entry_desc *txdesc)
+{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ u8 skbdesc_flags = skbdesc->flags;
+ unsigned int header_length;
+ bool success;
+
+ /*
+ * Unmap the skb.
+ */
+ rt2x00queue_unmap_skb(entry);
+
+ /*
+ * Remove the extra tx headroom from the skb.
+ */
+ skb_pull(entry->skb, rt2x00dev->extra_tx_headroom);
+
+ /*
+ * Signal that the TX descriptor is no longer in the skb.
+ */
+ skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
+
+ /*
+ * Determine the length of 802.11 header.
+ */
+ header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+
+ /*
+ * Remove L2 padding which was added during
+ */
+ if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_L2PAD))
+ rt2x00queue_remove_l2pad(entry->skb, header_length);
+
+ /*
+ * If the IV/EIV data was stripped from the frame before it was
+ * passed to the hardware, we should now reinsert it again because
+ * mac80211 will expect the same data to be present it the
+ * frame as it was passed to us.
+ */
+ if (rt2x00_has_cap_hw_crypto(rt2x00dev))
+ rt2x00crypto_tx_insert_iv(entry->skb, header_length);
+
+ /*
+ * Send frame to debugfs immediately, after this call is completed
+ * we are going to overwrite the skb->cb array.
+ */
+ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry);
+
+ /*
+ * Determine if the frame has been successfully transmitted and
+ * remove BARs from our check list while checking for their
+ * TX status.
+ */
+ success =
+ rt2x00lib_txdone_bar_status(entry) ||
+ test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
+ test_bit(TXDONE_UNKNOWN, &txdesc->flags);
+
+ /*
+ * Update TX statistics.
+ */
+ rt2x00dev->link.qual.tx_success += success;
+ rt2x00dev->link.qual.tx_failed += !success;
+
+ rt2x00lib_fill_tx_status(rt2x00dev, tx_info, skbdesc, txdesc, success);
/*
* Only send the status report to mac80211 when it's a frame
--
1.8.3.1
^ permalink raw reply related
* [PATCH 02/10] rt2800: identify station based on status WCID
From: Stanislaw Gruszka @ 2017-02-14 12:46 UTC (permalink / raw)
To: linux-wireless; +Cc: Helmut Schaa, Felix Fietkau
In-Reply-To: <1487076368-7020-1-git-send-email-sgruszka@redhat.com>
Add station field to skb_frame_desc and assign it according to status
WCID. This field will be used in the future.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 8 ++++++++
drivers/net/wireless/ralink/rt2x00/rt2800lib.h | 1 +
drivers/net/wireless/ralink/rt2x00/rt2x00queue.h | 3 ++-
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 8223a15..5de21d2 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -855,11 +855,13 @@ void rt2800_process_rxwi(struct queue_entry *entry,
void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
struct txdone_entry_desc txdesc;
u32 word;
u16 mcs, real_mcs;
int aggr, ampdu;
+ int wcid;
/*
* Obtain the status about this packet.
@@ -872,6 +874,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
real_mcs = rt2x00_get_field32(status, TX_STA_FIFO_MCS);
aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE);
+ wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
/*
* If a frame was meant to be sent as a single non-aggregated MPDU
@@ -894,6 +897,9 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
mcs = real_mcs;
}
+ if (likely(wcid >= WCID_START && wcid <= WCID_END))
+ skbdesc->sta = drv_data->wcid_to_sta[wcid - WCID_START];
+
if (aggr == 1 || ampdu == 1)
__set_bit(TXDONE_AMPDU, &txdesc.flags);
@@ -1468,6 +1474,7 @@ int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
return 0;
__set_bit(wcid - WCID_START, drv_data->sta_ids);
+ drv_data->wcid_to_sta[wcid - WCID_START] = sta;
/*
* Clean up WCID attributes and write STA address to the device.
@@ -1498,6 +1505,7 @@ int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, struct ieee80211_sta *sta)
* get renewed when the WCID is reused.
*/
rt2800_config_wcid(rt2x00dev, NULL, wcid);
+ drv_data->wcid_to_sta[wcid - WCID_START] = NULL;
__clear_bit(wcid - WCID_START, drv_data->sta_ids);
return 0;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index 8e1ae13..6811d67 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -41,6 +41,7 @@ struct rt2800_drv_data {
unsigned int tbtt_tick;
unsigned int ampdu_factor_cnt[4];
DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+ struct ieee80211_sta *wcid_to_sta[STA_IDS_SIZE];
};
struct rt2800_ops {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
index 22d1881..9b297fc 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
@@ -102,7 +102,7 @@ enum skb_frame_desc_flags {
* of the scope of the skb->data pointer.
* @iv: IV/EIV data used during encryption/decryption.
* @skb_dma: (PCI-only) the DMA address associated with the sk buffer.
- * @entry: The entry to which this sk buffer belongs.
+ * @sta: The station where sk buffer was sent.
*/
struct skb_frame_desc {
u8 flags;
@@ -116,6 +116,7 @@ struct skb_frame_desc {
__le32 iv[2];
dma_addr_t skb_dma;
+ struct ieee80211_sta *sta;
};
/**
--
1.8.3.1
^ permalink raw reply related
* [PATCH 01/10] rt2x00: rt2800lib: move rt2800_drv_data declaration into rt2800lib.h
From: Stanislaw Gruszka @ 2017-02-14 12:45 UTC (permalink / raw)
To: linux-wireless; +Cc: Helmut Schaa, Felix Fietkau, Gabor Juhos, Daniel Golle
In-Reply-To: <1487076368-7020-1-git-send-email-sgruszka@redhat.com>
From: Gabor Juhos <juhosg@openwrt.org>
The rt2800_drv_data structure contains driver specific
information. Move the declaration into the rt2800lib.h
header which is a more logical place for it. Also fix
the comment style to avoid checkpatch warning.
The patch contains no functional changes, it is in
preparation for the next patch.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/ralink/rt2x00/rt2800.h | 25 -------------------------
drivers/net/wireless/ralink/rt2x00/rt2800lib.h | 23 +++++++++++++++++++++++
2 files changed, 23 insertions(+), 25 deletions(-)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h
index 256496b..0e7051d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
@@ -2987,29 +2987,4 @@ enum rt2800_eeprom_word {
*/
#define BCN_TBTT_OFFSET 64
-/*
- * Hardware has 255 WCID table entries. First 32 entries are reserved for
- * shared keys. Since parts of the pairwise key table might be shared with
- * the beacon frame buffers 6 & 7 we could only use the first 222 entries.
- */
-#define WCID_START 33
-#define WCID_END 222
-#define STA_IDS_SIZE (WCID_END - WCID_START + 2)
-
-/*
- * RT2800 driver data structure
- */
-struct rt2800_drv_data {
- u8 calibration_bw20;
- u8 calibration_bw40;
- u8 bbp25;
- u8 bbp26;
- u8 txmixer_gain_24g;
- u8 txmixer_gain_5g;
- u8 max_psdu;
- unsigned int tbtt_tick;
- unsigned int ampdu_factor_cnt[4];
- DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
-};
-
#endif /* RT2800_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index 0a8b4df..8e1ae13 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -20,6 +20,29 @@
#ifndef RT2800LIB_H
#define RT2800LIB_H
+/*
+ * Hardware has 255 WCID table entries. First 32 entries are reserved for
+ * shared keys. Since parts of the pairwise key table might be shared with
+ * the beacon frame buffers 6 & 7 we could only use the first 222 entries.
+ */
+#define WCID_START 33
+#define WCID_END 222
+#define STA_IDS_SIZE (WCID_END - WCID_START + 2)
+
+/* RT2800 driver data structure */
+struct rt2800_drv_data {
+ u8 calibration_bw20;
+ u8 calibration_bw40;
+ u8 bbp25;
+ u8 bbp26;
+ u8 txmixer_gain_24g;
+ u8 txmixer_gain_5g;
+ u8 max_psdu;
+ unsigned int tbtt_tick;
+ unsigned int ampdu_factor_cnt[4];
+ DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+};
+
struct rt2800_ops {
void (*register_read)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset, u32 *value);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 00/10] rt2x00 patches 14.02.2017
From: Stanislaw Gruszka @ 2017-02-14 12:45 UTC (permalink / raw)
To: linux-wireless; +Cc: Helmut Schaa, Felix Fietkau
Patches for rt2x00. Most important is txdone functions rework to use
ieee80211_tx_status_noskb() if can not match sent skb with status
from TX_STAT_FIFO. Currently used only for rt2800usb.
Gabor Juhos (1):
rt2x00: rt2800lib: move rt2800_drv_data declaration into rt2800lib.h
Stanislaw Gruszka (9):
rt2800: identify station based on status WCID
rt2x00: separte filling tx status from rt2x00lib_txdone
rt2x00: separte clearing entry from rt2x00lib_txdone
rt2x00: add txdone nomatch function
rt2x00: fixup fill_tx_status for nomatch case
rt2x00: use txdone_nomatch on rt2800usb
rt2800: status based rate flags for nomatch case
rt2800: use TXOP_BACKOFF for probe frames
rt2x00: fix rt2x00debug_dump_frame comment
drivers/net/wireless/ralink/rt2x00/rt2800.h | 27 +--
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 67 ++++++-
drivers/net/wireless/ralink/rt2x00/rt2800lib.h | 27 ++-
drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 2 +-
drivers/net/wireless/ralink/rt2x00/rt2800usb.c | 18 +-
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 4 +-
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 232 +++++++++++++++--------
drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 7 +-
drivers/net/wireless/ralink/rt2x00/rt2x00queue.h | 4 +-
9 files changed, 260 insertions(+), 128 deletions(-)
--
1.8.3.1
^ permalink raw reply
* Re: [RFC V2 1/5] nl80211: allow multiple active scheduled scan requests
From: Arend Van Spriel @ 2017-02-14 12:35 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1485250815.7244.8.camel@sipsolutions.net>
On 24-1-2017 10:40, Johannes Berg wrote:
>
>> + * @max_sched_scan_reqs: maximum number of scheduled scan requests
>> that
>> + * the device can run concurrently.
>
> Perhaps we should get rid of WIPHY_FLAG_SUPPORTS_SCHED_SCAN and just
> set this to 1 for such devices? Otherwise we have two different
> requirements, and we need to track that 0 is an invalid value here if
> WIPHY_FLAG_SUPPORTS_SCHED_SCAN is set, or something like that?
Ok. Doesn't that cause issues in user-space. Or do you only want to get
rid of it in cfg80211 api and report the flag to user-space when
max_sched_scan_reqs equals 1?
>> + * @NL80211_ATTR_SCHED_SCAN_MAX_REQS: indicates maximum number of
>> scheduled
>> + * scan request that may be active for the device (u8).
>
> I'd make that a u32 - not that I believe we'll ever want to change this
> in the future, but there's simply no value in making it a u8 since it
> uses the same amount of space in a netlink message.
Ok.
>> + list_for_each_entry_safe(pos, tmp, &rdev-
>>> sched_scan_req_list, list) {
>> + cfg80211_stop_sched_scan_req(rdev, pos, false);
>> + }
>
> nit: don't really need braces here.
True.
>> + if ((wiphy->flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) &&
>> + !wiphy->max_sched_scan_reqs)
>> + wiphy->max_sched_scan_reqs = 1;
>
> Yeah, this. Why bother?
>
> (should even be simple to come up with an spatch to change all the
> drivers, but there are only five anyway)
Done.
>> + nla_put_u8(msg,
>> NL80211_ATTR_SCHED_SCAN_MAX_REQS,
>> + rdev->wiphy.max_sched_scan_reqs) ||
>> nla_put_u8(msg,
>> NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
>> rdev->wiphy.max_sched_scan_ssids) ||
>
> This might break older userspace - you'll have to put it in a later
> portion of the code.
>
> I'm also a bit surprised the attributes aren't actually optional for
> when sched scan isn't supported, I'd make the new one optional and I
> guess we can fix the others later too, if desired.
Why would it break user-space. Is the order in which attributes are
added into the stream something user-space relies on.
>> + bool want_multi;
>
> That's bool
>
>> + want_multi = !!info->attrs[NL80211_ATTR_SCHED_SCAN_MULTI];
>
> so you don't really need the !! as it's implied by the rules for bool
> :)
I see.
>> + /* leave request id zero for legacy request
>> + * or if driver does not support multi-scheduled scan
>> + */
>> + if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1) {
>
> Why do the >1 check here? It probably doesn't really make a difference
> since only one can be running at a time, but it might be nicer - at
> least for debug in userspace - to have a real value for all multi
> scans?
>
>> + while (!sched_scan_req->reqid)
>
> Pretty sure we won't run over the u64 ... but I guess it doesn't matter
> much :)
>
>
> I don't see you sending the reqid/cookie back to userspace here though,
> that's missing?
Indeed that is in the second patch. Maybe I should put that commit first
in the series.
>> static int nl80211_stop_sched_scan(struct sk_buff *skb,
>> struct genl_info *info)
>> {
>> + struct cfg80211_sched_scan_request *req;
>> struct cfg80211_registered_device *rdev = info->user_ptr[0];
>> + u64 cookie;
>>
>> if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
>> !rdev->ops->sched_scan_stop)
>> return -EOPNOTSUPP;
>>
>> - return __cfg80211_stop_sched_scan(rdev, false);
>> + if (info->attrs[NL80211_ATTR_COOKIE]) {
>> + cookie = nla_get_u64(info-
>>> attrs[NL80211_ATTR_COOKIE]);
>> + return __cfg80211_stop_sched_scan(rdev, cookie,
>> false);
>> + } else {
>> + req = list_first_or_null_rcu(&rdev-
>>> sched_scan_req_list,
>> + struct
>> cfg80211_sched_scan_request,
>> + list);
>> + if (!req || req->reqid ||
>> + (req->owner_nlportid &&
>> + req->owner_nlportid != info->snd_portid))
>> + return -ENOENT;
>
> Shouldn't this also check that it's non-multi?
non-multi == (req->reqid == 0). non-multi/legacy and multi can not be
active at the same time so we can use list_first_or_null_rcu here. If
req->reqid of first entry is non-zero there is no non-multi to stop here.
>> +void cfg80211_add_sched_scan_req(struct cfg80211_registered_device
>> *rdev,
>> + struct cfg80211_sched_scan_request
>> *req)
>> +{
>> + list_add_rcu(&req->list, &rdev->sched_scan_req_list);
>> +}
>> +
>> +static void cfg80211_del_sched_scan_req(struct
>> cfg80211_registered_device *rdev,
>> + struct
>> cfg80211_sched_scan_request *req)
>> +{
>> + list_del_rcu(&req->list);
>> + kfree_rcu(req, rcu_head);
>> +}
>
> Some locking assertions in these would be good, I think.
Will do.
>> +static struct cfg80211_sched_scan_request *
>> +cfg80211_find_sched_scan_req(struct cfg80211_registered_device
>> *rdev, u64 reqid)
>> +{
>> + struct cfg80211_sched_scan_request *pos;
>> +
>> + list_for_each_entry(pos, &rdev->sched_scan_req_list, list) {
>> + if (pos->reqid == reqid)
>> + return pos;
>> + }
>> + return ERR_PTR(-ENOENT);
>> +}
>
> Here too, I guess, since you don't actually use RCU.
So should I use RCU here? Not sure what is the better choice here.
Regards,
Arend
^ permalink raw reply
* [RFC 4/4] mac80211: add ability to parse CCFS2
From: Johannes Berg @ 2017-02-14 11:28 UTC (permalink / raw)
To: linux-wireless; +Cc: j, greearb, Johannes Berg
In-Reply-To: <20170214112827.28216-1-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
With newer VHT implementations, it's necessary to look at the
HT operation's CCFS2 field to identify the actual bandwidth
used.
NOTE: this cannot be applied until we make rate scaling aware
of the NSS restrictions in the previous patches, and we
may need to make this parsing conditional on that?
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/ibss.c | 1 +
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/mesh.c | 3 ++-
net/mac80211/mlme.c | 2 +-
net/mac80211/spectmgmt.c | 4 +++-
net/mac80211/util.c | 43 ++++++++++++++++++++++++++++---------------
6 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 98999d3d5262..20abe88a82bb 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1066,6 +1066,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta_vht_cap cap = sta->sta.vht_cap;
ieee80211_chandef_vht_oper(elems->vht_operation,
+ elems->ht_operation,
&chandef);
memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 159a1a733725..3ee63fb38a8d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2072,6 +2072,7 @@ u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo);
bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
struct cfg80211_chan_def *chandef);
bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper,
+ const struct ieee80211_ht_operation *htop,
struct cfg80211_chan_def *chandef);
u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index c28b0af9c1f2..585b59104ab6 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -92,7 +92,8 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
cfg80211_chandef_create(&sta_chan_def, sdata->vif.bss_conf.chandef.chan,
NL80211_CHAN_NO_HT);
ieee80211_chandef_ht_oper(ie->ht_operation, &sta_chan_def);
- ieee80211_chandef_vht_oper(ie->vht_operation, &sta_chan_def);
+ ieee80211_chandef_vht_oper(ie->vht_operation, ie->ht_operation,
+ &sta_chan_def);
if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
&sta_chan_def))
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6e90301154d5..fedd4f798d55 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -213,7 +213,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
}
vht_chandef = *chandef;
- if (!ieee80211_chandef_vht_oper(vht_oper, &vht_chandef)) {
+ if (!ieee80211_chandef_vht_oper(vht_oper, ht_oper, &vht_chandef)) {
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
sdata_info(sdata,
"AP VHT information is invalid, disable VHT\n");
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index 0782e486fe89..b0cc99d5f4e9 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -138,6 +138,7 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
wide_bw_chansw_ie->new_center_freq_seg1,
/* .basic_mcs_set doesn't matter */
};
+ struct ieee80211_ht_operation ht_oper = {};
/* default, for the case of IEEE80211_VHT_CHANWIDTH_USE_HT,
* to the previously parsed chandef
@@ -145,7 +146,8 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
new_vht_chandef = csa_ie->chandef;
/* ignore if parsing fails */
- if (!ieee80211_chandef_vht_oper(&vht_oper, &new_vht_chandef))
+ if (!ieee80211_chandef_vht_oper(&vht_oper, &ht_oper,
+ &new_vht_chandef))
new_vht_chandef.chan = NULL;
if (sta_flags & IEEE80211_STA_DISABLE_80P80MHZ &&
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7a37ce78bb38..10bdca76f469 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2483,48 +2483,61 @@ bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
}
bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper,
+ const struct ieee80211_ht_operation *htop,
struct cfg80211_chan_def *chandef)
{
struct cfg80211_chan_def new = *chandef;
- int cf1, cf2;
+ int cf0, cf1;
+ int ccfs0, ccfs1, ccfs2;
+ int ccf0, ccf1;
- if (!oper)
+ if (!oper || !htop)
return false;
- cf1 = ieee80211_channel_to_frequency(oper->center_freq_seg0_idx,
- chandef->chan->band);
- cf2 = ieee80211_channel_to_frequency(oper->center_freq_seg1_idx,
- chandef->chan->band);
+ ccfs0 = oper->center_freq_seg0_idx;
+ ccfs1 = oper->center_freq_seg1_idx;
+ ccfs2 = (le16_to_cpu(htop->operation_mode) &
+ IEEE80211_HT_OP_MODE_CCFS2_MASK)
+ >> IEEE80211_HT_OP_MODE_CCFS2_SHIFT;
+
+ /* when parsing (and we know how to) CCFS1 and CCFS2 are equivalent */
+ ccf0 = ccfs0;
+ ccf1 = ccfs1 ?: ccfs2;
+
+ cf0 = ieee80211_channel_to_frequency(ccf0, chandef->chan->band);
+ cf1 = ieee80211_channel_to_frequency(ccf1, chandef->chan->band);
switch (oper->chan_width) {
case IEEE80211_VHT_CHANWIDTH_USE_HT:
+ /* just use HT information directly */
break;
case IEEE80211_VHT_CHANWIDTH_80MHZ:
new.width = NL80211_CHAN_WIDTH_80;
- new.center_freq1 = cf1;
+ new.center_freq1 = cf0;
/* If needed, adjust based on the newer interop workaround. */
- if (oper->center_freq_seg1_idx) {
+ if (ccf1) {
unsigned int diff;
- diff = abs(oper->center_freq_seg1_idx -
- oper->center_freq_seg0_idx);
+ diff = abs(ccf1 - ccf0);
if (diff == 8) {
new.width = NL80211_CHAN_WIDTH_160;
- new.center_freq1 = cf2;
+ new.center_freq1 = cf1;
} else if (diff > 8) {
new.width = NL80211_CHAN_WIDTH_80P80;
- new.center_freq2 = cf2;
+ new.center_freq2 = cf1;
}
}
break;
case IEEE80211_VHT_CHANWIDTH_160MHZ:
+ /* deprecated encoding */
new.width = NL80211_CHAN_WIDTH_160;
- new.center_freq1 = cf1;
+ new.center_freq1 = cf0;
break;
case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
+ /* deprecated encoding */
new.width = NL80211_CHAN_WIDTH_80P80;
- new.center_freq1 = cf1;
- new.center_freq2 = cf2;
+ new.center_freq1 = cf0;
+ new.center_freq2 = cf1;
break;
default:
return false;
--
2.9.3
^ permalink raw reply related
* [RFC 1/4] ieee80211: rename CCFS1/CCFS2 to CCFS0/CCFS1
From: Johannes Berg @ 2017-02-14 11:28 UTC (permalink / raw)
To: linux-wireless; +Cc: j, greearb, Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
This matches the spec, and otherwise things are really
confusing with the next patch adding CCFS2.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
drivers/net/wireless/marvell/mwifiex/tdls.c | 2 +-
include/linux/ieee80211.h | 4 ++--
net/mac80211/spectmgmt.c | 4 ++--
net/mac80211/util.c | 22 +++++++++++-----------
4 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c
index df9704de0715..5fc8319ed302 100644
--- a/drivers/net/wireless/marvell/mwifiex/tdls.c
+++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
@@ -349,7 +349,7 @@ static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT;
break;
}
- vht_oper->center_freq_seg1_idx =
+ vht_oper->center_freq_seg0_idx =
mwifiex_get_center_freq_index(priv, BAND_AAC,
bss_desc->channel,
chan_bw);
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 0dd9498c694f..4a15e77d9d66 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1525,14 +1525,14 @@ enum ieee80211_vht_chanwidth {
* This structure is the "VHT operation element" as
* described in 802.11ac D3.0 8.4.2.161
* @chan_width: Operating channel width
+ * @center_freq_seg0_idx: center freq segment 0 index
* @center_freq_seg1_idx: center freq segment 1 index
- * @center_freq_seg2_idx: center freq segment 2 index
* @basic_mcs_set: VHT Basic MCS rate set
*/
struct ieee80211_vht_operation {
u8 chan_width;
+ u8 center_freq_seg0_idx;
u8 center_freq_seg1_idx;
- u8 center_freq_seg2_idx;
__le16 basic_mcs_set;
} __packed;
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index 97f4c9d6b54c..0782e486fe89 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -132,9 +132,9 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
struct ieee80211_vht_operation vht_oper = {
.chan_width =
wide_bw_chansw_ie->new_channel_width,
- .center_freq_seg1_idx =
+ .center_freq_seg0_idx =
wide_bw_chansw_ie->new_center_freq_seg0,
- .center_freq_seg2_idx =
+ .center_freq_seg1_idx =
wide_bw_chansw_ie->new_center_freq_seg1,
/* .basic_mcs_set doesn't matter */
};
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index ac59fbd280df..7a37ce78bb38 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2413,13 +2413,13 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
*pos++ = WLAN_EID_VHT_OPERATION;
*pos++ = sizeof(struct ieee80211_vht_operation);
vht_oper = (struct ieee80211_vht_operation *)pos;
- vht_oper->center_freq_seg1_idx = ieee80211_frequency_to_channel(
+ vht_oper->center_freq_seg0_idx = ieee80211_frequency_to_channel(
chandef->center_freq1);
if (chandef->center_freq2)
- vht_oper->center_freq_seg2_idx =
+ vht_oper->center_freq_seg1_idx =
ieee80211_frequency_to_channel(chandef->center_freq2);
else
- vht_oper->center_freq_seg2_idx = 0x00;
+ vht_oper->center_freq_seg1_idx = 0x00;
switch (chandef->width) {
case NL80211_CHAN_WIDTH_160:
@@ -2428,11 +2428,11 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
* workaround.
*/
vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
- vht_oper->center_freq_seg2_idx = vht_oper->center_freq_seg1_idx;
+ vht_oper->center_freq_seg1_idx = vht_oper->center_freq_seg0_idx;
if (chandef->chan->center_freq < chandef->center_freq1)
- vht_oper->center_freq_seg1_idx -= 8;
+ vht_oper->center_freq_seg0_idx -= 8;
else
- vht_oper->center_freq_seg1_idx += 8;
+ vht_oper->center_freq_seg0_idx += 8;
break;
case NL80211_CHAN_WIDTH_80P80:
/*
@@ -2491,9 +2491,9 @@ bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper,
if (!oper)
return false;
- cf1 = ieee80211_channel_to_frequency(oper->center_freq_seg1_idx,
+ cf1 = ieee80211_channel_to_frequency(oper->center_freq_seg0_idx,
chandef->chan->band);
- cf2 = ieee80211_channel_to_frequency(oper->center_freq_seg2_idx,
+ cf2 = ieee80211_channel_to_frequency(oper->center_freq_seg1_idx,
chandef->chan->band);
switch (oper->chan_width) {
@@ -2503,11 +2503,11 @@ bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper,
new.width = NL80211_CHAN_WIDTH_80;
new.center_freq1 = cf1;
/* If needed, adjust based on the newer interop workaround. */
- if (oper->center_freq_seg2_idx) {
+ if (oper->center_freq_seg1_idx) {
unsigned int diff;
- diff = abs(oper->center_freq_seg2_idx -
- oper->center_freq_seg1_idx);
+ diff = abs(oper->center_freq_seg1_idx -
+ oper->center_freq_seg0_idx);
if (diff == 8) {
new.width = NL80211_CHAN_WIDTH_160;
new.center_freq1 = cf2;
--
2.9.3
^ permalink raw reply related
* [RFC 3/4] ieee80211: add new VHT capability fields/parsing
From: Johannes Berg @ 2017-02-14 11:28 UTC (permalink / raw)
To: linux-wireless; +Cc: j, greearb, Johannes Berg
In-Reply-To: <20170214112827.28216-1-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
IEEE 802.11-2016 extended the VHT capability fields to allow
indicating the number of spatial streams depending on the
actually used bandwidth, add support for decoding this.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/linux/ieee80211.h | 81 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 79 insertions(+), 2 deletions(-)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 4a7200c6c9ea..eecae214c47a 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1457,13 +1457,16 @@ struct ieee80211_ht_operation {
* STA can receive. Rate expressed in units of 1 Mbps.
* If this field is 0 this value should not be used to
* consider the highest RX data rate supported.
- * The top 3 bits of this field are reserved.
+ * The top 3 bits of this field indicate the Maximum NSTS,total
+ * (a beamformee capability.)
* @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams
* @tx_highest: Indicates highest long GI VHT PPDU data rate
* STA can transmit. Rate expressed in units of 1 Mbps.
* If this field is 0 this value should not be used to
* consider the highest TX data rate supported.
- * The top 3 bits of this field are reserved.
+ * The top 2 bits of this field are reserved, the
+ * 3rd bit from the top indiciates VHT Extended NSS BW
+ * Capability.
*/
struct ieee80211_vht_mcs_info {
__le16 rx_mcs_map;
@@ -1472,6 +1475,11 @@ struct ieee80211_vht_mcs_info {
__le16 tx_highest;
} __packed;
+#define IEEE80211_VHT_MAX_NSTS_TOTAL_SHIFT 13
+#define IEEE80211_VHT_MAX_NSTS_TOTAL_MASK (7 << IEEE80211_VHT_MAX_NSTS_TOTAL_SHIFT)
+
+#define IEEE80211_VHT_EXT_NSS_BW_CAPABLE (1 << 13)
+
/**
* enum ieee80211_vht_mcs_support - VHT MCS support definitions
* @IEEE80211_VHT_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the
@@ -1547,6 +1555,7 @@ struct ieee80211_vht_operation {
#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004
#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008
#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK 0x0000000C
+#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_SHIFT 2
#define IEEE80211_VHT_CAP_RXLDPC 0x00000010
#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020
#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040
@@ -1575,6 +1584,74 @@ struct ieee80211_vht_operation {
#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000
#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000
#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000
+#define IEEE80211_VHT_CAP_EXT_NSS_BW_SHIFT 30
+#define IEEE80211_VHT_CAP_EXT_NSS_BW_MASK 0xc0000000
+
+static inline int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
+ enum ieee80211_vht_chanwidth bw)
+{
+ unsigned long w;
+ int max_vht_nss;
+ int ext_nss_bw;
+ int supp_width;
+
+ if (cap->supp_mcs.rx_mcs_map == 0xffff)
+ return 0;
+
+ w = cap->supp_mcs.rx_mcs_map ^ 0xffff;
+ max_vht_nss = DIV_ROUND_UP(fls(w) + 1, 2);
+
+ if (!(cap->supp_mcs.tx_mcs_map & IEEE80211_VHT_EXT_NSS_BW_CAPABLE))
+ return max_vht_nss;
+
+ ext_nss_bw = (le32_to_cpu(cap->vht_cap_info) &
+ IEEE80211_VHT_CAP_EXT_NSS_BW_MASK)
+ >> IEEE80211_VHT_CAP_EXT_NSS_BW_SHIFT;
+ supp_width = (le32_to_cpu(cap->vht_cap_info) &
+ IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK)
+ >> IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_SHIFT;
+
+ /*
+ * Cover all the special cases according to IEEE 802.11-2016 Table 9-250.
+ * All other cases are either factor of 1 or not valid/supported.
+ */
+ switch (bw) {
+ case IEEE80211_VHT_CHANWIDTH_USE_HT:
+ case IEEE80211_VHT_CHANWIDTH_80MHZ:
+ if ((supp_width == 1 || supp_width == 2) &&
+ ext_nss_bw == 3)
+ return 2 * max_vht_nss;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_160MHZ:
+ if (supp_width == 0 &&
+ (ext_nss_bw == 1 || ext_nss_bw == 2))
+ return DIV_ROUND_UP(max_vht_nss, 2);
+ if (supp_width == 0 &&
+ ext_nss_bw == 3)
+ return DIV_ROUND_UP(3 * max_vht_nss, 4);
+ if (supp_width == 1 &&
+ ext_nss_bw == 3)
+ return 2 * max_vht_nss;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
+ if (supp_width == 0 &&
+ ext_nss_bw == 2)
+ return DIV_ROUND_UP(max_vht_nss, 2);
+ if (supp_width == 0 &&
+ ext_nss_bw == 3)
+ return DIV_ROUND_UP(3 * max_vht_nss, 4);
+ if (supp_width == 1 &&
+ ext_nss_bw == 1)
+ return DIV_ROUND_UP(max_vht_nss, 2);
+ if (supp_width == 1 &&
+ ext_nss_bw == 2)
+ return DIV_ROUND_UP(3 * max_vht_nss, 4);
+ break;
+ }
+
+ /* not covered or invalid combination received */
+ return max_vht_nss;
+}
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
--
2.9.3
^ permalink raw reply related
* [RFC 2/4] ieee80211: define HT operation CCFS2 field
From: Johannes Berg @ 2017-02-14 11:28 UTC (permalink / raw)
To: linux-wireless; +Cc: j, greearb, Johannes Berg
In-Reply-To: <20170214112827.28216-1-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
The Channel Center Frequency Segment 2 field is used in
802.11-2016 for encoding the actual channel position of
the 80+80/160 MHz channel, if the max NSS is restricted.
This is used for backwards compatibility.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/linux/ieee80211.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 4a15e77d9d66..4a7200c6c9ea 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1411,6 +1411,8 @@ struct ieee80211_ht_operation {
#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3
#define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004
#define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010
+#define IEEE80211_HT_OP_MODE_CCFS2_SHIFT 5
+#define IEEE80211_HT_OP_MODE_CCFS2_MASK 0x1fe0
/* for stbc_param */
#define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040
--
2.9.3
^ permalink raw reply related
* Re: VHT 160Mhz and nss related config.
From: Sebastian Gottschall @ 2017-02-14 10:19 UTC (permalink / raw)
To: Ben Greear, Adrian Chadd; +Cc: linux-wireless@vger.kernel.org, ath10k
In-Reply-To: <58A23D68.5070507@candelatech.com>
now the test result. yes. it assocs with VHT160 SGI in my case. but
performance is as expected identical to VHT80
Am 14.02.2017 um 00:12 schrieb Ben Greear:
> On 02/13/2017 02:48 PM, Sebastian Gottschall wrote:
>> Am 13.02.2017 um 20:56 schrieb Ben Greear:
>>> On 02/11/2017 10:21 AM, Sebastian Gottschall wrote:
>>>> Am 11.02.2017 um 18:58 schrieb Ben Greear:
>>>>> On 02/10/2017 08:37 PM, Adrian Chadd wrote:
>>>>>> On 10 February 2017 at 20:22, Sebastian Gottschall
>>>>>> <s.gottschall@dd-wrt.com> wrote:
>>>>>>> i really can't believe this. if this is true the 160 mhz mode
>>>>>>> would not
>>>>>>> make any sense.
>>>>>>> the maximum tx / rx rate for 4x4 vht80 and 2x2 vht160 is
>>>>>>> identical. so
>>>>>>> vht160 would not increase performance in any way
>>>>>>
>>>>>> Well, if it can also do 2x2 MU-MIMO at 160MHz then it can be a
>>>>>> perfectly fine STA to a 4x4 160MHz MU-MIMO chip that can actually
>>>>>> transmit 2x2 rates to different MU-MIMO peers.
>>>>>>
>>>>>> That's the outstanding question I have - is it like, 2x2 MU only, or
>>>>>> is it say, 2 concurrently different spatial stream 2x2 MU? Ie,
>>>>>> can you
>>>>>> have 2 peers, different VHT spatial groups (or 4 peers, 1 spatial
>>>>>> group each) all going at the same time?
>>>>>>
>>>>>> I'm .. not even sure how you're supposed to cleanly negotiate
>>>>>> that you
>>>>>> can do 4NSS in VHT80 but 2NSS in VHT160 to a peer... that only makes
>>>>>> sense if you're doing lots of 1NSS and 2NSS MU-MIMO peers..
>>>>>
>>>>> I think using the max-rx-rate logic might could imply this, but I
>>>>> am not sure
>>>>> many drivers fill this out properly.
>>>>>
>>>>> Looks like a mess waiting to happen to me.
>>>>>
>>>>> Even if you can do 1x1 160Mhz MU-MIMO to two stations, and I am
>>>>> not certain you
>>>>> can since in 80Mhz you can only do a 1x1 and a 2x2 (not two 2x2).
>>>>>
>>>>> So, from what I know currently, 80+80 is not that useful on the
>>>>> 9984 NIC...
>>>> never tried 80+80 since i need to enhance the channel logic alot in
>>>> my firmware code to handle it. would be great enough if vht160
>>>> would work as expected and
>>>> i'm not sure right now if it really works, even if the interface
>>>> initialized correctly it assocs only with vht80
>>>
>>> Looks like it is working with the hack I posted:
>>>
>>> Station 04:f0:21:2e:49:65 (on wlan2)
>>> inactive time: 0 ms
>>> rx bytes: 64902998
>>> rx packets: 37918
>>> tx bytes: 64760298
>>> tx packets: 42239
>>> tx retries: 0
>>> tx failed: 0
>>> signal: -43 dBm
>>> signal avg: -42 dBm
>>> tx bitrate: 1053.0 MBit/s VHT-MCS 6 160MHz VHT-NSS 2
>>> rx bitrate: 1560.0 MBit/s VHT-MCS 8 160MHz short GI VHT-NSS 2
>>> authorized: yes
>>> authenticated: yes
>>> preamble: long
>>> WMM/WME: yes
>>> MFP: no
>>> TDLS peer: no
>>> connected time: 156 seconds
>>>
>>> Thanks,
>>> Ben
>>>
>>>
>> the hack you posted crashes the driver for me. i also see that this
>> patch is based on the CT ath10k source. it doesnt apply clean to
>> ath10k. needed to merge it
>> manually
>
> Ok, I'm in the middle of a bunch of changes to support VHT overrides
> to allow
> disabling VHT160/80+80 in station mode, and I'll push all my changes
> to my
> tree when I get that implemented and testing.
>
> I've about given up on getting ath10k patches upstream, but I'll get
> these changes into
> ath10k-ct in LEDE sometime...
>
> If you want to post the splat, just possibly I'll have a quick idea of
> why it
> is crashing.
>
> Thanks,
> Ben
>
>
--
Mit freundlichen Grüssen / Regards
Sebastian Gottschall / CTO
NewMedia-NET GmbH - DD-WRT
Firmensitz: Berliner Ring 101, 64625 Bensheim
Registergericht: Amtsgericht Darmstadt, HRB 25473
Geschäftsführer: Peter Steinhäuser, Christian Scheele
http://www.dd-wrt.com
email: s.gottschall@dd-wrt.com
Tel.: +496251-582650 / Fax: +496251-5826565
^ permalink raw reply
* Re: [PATCH v2] iw: Fix bitrate output when no rate info found
From: Johannes Berg @ 2017-02-14 9:45 UTC (permalink / raw)
To: Masashi Honma; +Cc: linux-wireless
In-Reply-To: <1487065138-4892-1-git-send-email-masashi.honma@gmail.com>
On Tue, 2017-02-14 at 18:38 +0900, Masashi Honma wrote:
> Previously, bitrate showed uninitialized buffer when no rate info
> found.
> This patch fixes the issue.
>
Applied, thanks.
johannes
^ permalink raw reply
* [PATCH v2] iw: Fix bitrate output when no rate info found
From: Masashi Honma @ 2017-02-14 9:38 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Masashi Honma
In-Reply-To: <1487049663-2942-1-git-send-email-masashi.honma@gmail.com>
Previously, bitrate showed uninitialized buffer when no rate info found.
This patch fixes the issue.
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
---
station.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/station.c b/station.c
index f3e3da8..4885dc0 100644
--- a/station.c
+++ b/station.c
@@ -151,6 +151,8 @@ void parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen)
if (rate > 0)
pos += snprintf(pos, buflen - (pos - buf),
"%d.%d MBit/s", rate / 10, rate % 10);
+ else
+ pos += snprintf(pos, buflen - (pos - buf), "(unknown)");
if (rinfo[NL80211_RATE_INFO_MCS])
pos += snprintf(pos, buflen - (pos - buf),
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] iw: Fix bitrate output when no rate info found
From: Masashi Honma @ 2017-02-14 9:35 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1487063659.4705.5.camel@sipsolutions.net>
On 2017-02-14 18:14, Johannes Berg wrote:
> Yes, this is bad! But if you saw that, why did you ever get to the
> below code that checked for the BITRATE(32) attributes?
>
>> So I used explaining message. We could see the message like this.
>>
>> tx bitrate: No rate info found!
>> rx bitrate: 48.0 MBit/s
>
> Yeah I was just thinking we could also see
>
> tx bitrate: (unknown)
>
> and then if there was MCS anyway you'd see
>
> tx bitrate: (unknown) MCS 7
>
> or something like that?
Yes, showing information as far as possible looks good.
I will modify this patch.
Masashi Honma.
^ permalink raw reply
* Re: [PATCH] iw: Fix bitrate output when no rate info found
From: Johannes Berg @ 2017-02-14 9:14 UTC (permalink / raw)
To: Masashi Honma; +Cc: linux-wireless
In-Reply-To: <a2ffeab5-dd9c-1c9d-3fd1-c098a6d1e748@gmail.com>
On Tue, 2017-02-14 at 17:55 +0900, Masashi Honma wrote:
> On 2017-02-14 17:35, Johannes Berg wrote:
> > On Tue, 2017-02-14 at 14:21 +0900, Masashi Honma wrote:
> > > Previously, bitrate showed uninitialized buffer when no rate info
> > > found.
> >
> > When would this happen?
>
> I could see in mesh STA connection with 11n and legacy mixed.
> STA A has disable_ht=1.
> STA B has disable_ht=0.
Interesting, ok.
> > I'm not really sure this is right - perhaps we don't have
> > RATE_INFO_BITRATE(32), but still have the MCS data?
>
> I recognized there was a issue on such a case. I will send a patch
> to wpa_supplicant. Anyway, showing string message is better than
> showing raw binary data.
>
> > How about we just add "(unknown)" or so and not return here?
>
> Yes. First time, I supposed to use "unknown".
Ok.
> But in the function
> parse_bitrate(), nla_parse_nested() returns message "failed to parse
> nested rate attributes!". This explains why the bitrate is unknown.
Yes, this is bad! But if you saw that, why did you ever get to the
below code that checked for the BITRATE(32) attributes?
> So I used explaining message. We could see the message like this.
>
> tx bitrate: No rate info found!
> rx bitrate: 48.0 MBit/s
Yeah I was just thinking we could also see
tx bitrate: (unknown)
and then if there was MCS anyway you'd see
tx bitrate: (unknown) MCS 7
or something like that?
johannes
^ permalink raw reply
* Re: [PATCH] iw: Fix bitrate output when no rate info found
From: Masashi Honma @ 2017-02-14 8:55 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1487061321.4705.1.camel@sipsolutions.net>
On 2017-02-14 17:35, Johannes Berg wrote:
> On Tue, 2017-02-14 at 14:21 +0900, Masashi Honma wrote:
>> Previously, bitrate showed uninitialized buffer when no rate info
>> found.
>
> When would this happen?
I could see in mesh STA connection with 11n and legacy mixed.
STA A has disable_ht=1.
STA B has disable_ht=0.
> I'm not really sure this is right - perhaps we don't have
> RATE_INFO_BITRATE(32), but still have the MCS data?
I recognized there was a issue on such a case. I will send a patch to
wpa_supplicant. Anyway, showing string message is better than showing
raw binary data.
> How about we just add "(unknown)" or so and not return here?
Yes. First time, I supposed to use "unknown". But in the function
parse_bitrate(), nla_parse_nested() returns message "failed to parse
nested rate attributes!". This explains why the bitrate is unknown. So I
used explaining message. We could see the message like this.
tx bitrate: No rate info found!
rx bitrate: 48.0 MBit/s
Masashi Honma.
^ permalink raw reply
* Re: [PATCH] iw: Fix bitrate output when no rate info found
From: Johannes Berg @ 2017-02-14 8:35 UTC (permalink / raw)
To: Masashi Honma; +Cc: linux-wireless
In-Reply-To: <1487049663-2942-1-git-send-email-masashi.honma@gmail.com>
On Tue, 2017-02-14 at 14:21 +0900, Masashi Honma wrote:
> Previously, bitrate showed uninitialized buffer when no rate info
> found.
When would this happen?
I'm not really sure this is right - perhaps we don't have
RATE_INFO_BITRATE(32), but still have the MCS data?
How about we just add "(unknown)" or so and not return here?
johannes
^ permalink raw reply
* Re: [PATCH] iw: Fix bitrate output when no rate info found
From: Masashi Honma @ 2017-02-14 5:26 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless
In-Reply-To: <1487049663-2942-1-git-send-email-masashi.honma@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 189 bytes --]
On 2017/02/14 14:21, Masashi Honma wrote:
> Previously, bitrate showed uninitialized buffer when no rate info found.
> This patch fixes the issue.
This is the screen shot.
Masashi Honma.
[-- Attachment #2: tx_bitrate.jpeg --]
[-- Type: image/jpeg, Size: 62242 bytes --]
^ permalink raw reply
* [PATCH] iw: Fix bitrate output when no rate info found
From: Masashi Honma @ 2017-02-14 5:21 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Masashi Honma
Previously, bitrate showed uninitialized buffer when no rate info found.
This patch fixes the issue.
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
---
station.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/station.c b/station.c
index f3e3da8..9d3eb4d 100644
--- a/station.c
+++ b/station.c
@@ -151,6 +151,10 @@ void parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen)
if (rate > 0)
pos += snprintf(pos, buflen - (pos - buf),
"%d.%d MBit/s", rate / 10, rate % 10);
+ else {
+ snprintf(buf, buflen, "No rate info found!");
+ return;
+ }
if (rinfo[NL80211_RATE_INFO_MCS])
pos += snprintf(pos, buflen - (pos - buf),
--
2.7.4
^ permalink raw reply related
* Re: VHT 160Mhz and nss related config.
From: Ben Greear @ 2017-02-13 23:12 UTC (permalink / raw)
To: Sebastian Gottschall, Adrian Chadd; +Cc: linux-wireless@vger.kernel.org, ath10k
In-Reply-To: <f6d4b239-03af-976b-0c97-e7a5858f00da@dd-wrt.com>
On 02/13/2017 02:48 PM, Sebastian Gottschall wrote:
> Am 13.02.2017 um 20:56 schrieb Ben Greear:
>> On 02/11/2017 10:21 AM, Sebastian Gottschall wrote:
>>> Am 11.02.2017 um 18:58 schrieb Ben Greear:
>>>> On 02/10/2017 08:37 PM, Adrian Chadd wrote:
>>>>> On 10 February 2017 at 20:22, Sebastian Gottschall
>>>>> <s.gottschall@dd-wrt.com> wrote:
>>>>>> i really can't believe this. if this is true the 160 mhz mode would not
>>>>>> make any sense.
>>>>>> the maximum tx / rx rate for 4x4 vht80 and 2x2 vht160 is identical. so
>>>>>> vht160 would not increase performance in any way
>>>>>
>>>>> Well, if it can also do 2x2 MU-MIMO at 160MHz then it can be a
>>>>> perfectly fine STA to a 4x4 160MHz MU-MIMO chip that can actually
>>>>> transmit 2x2 rates to different MU-MIMO peers.
>>>>>
>>>>> That's the outstanding question I have - is it like, 2x2 MU only, or
>>>>> is it say, 2 concurrently different spatial stream 2x2 MU? Ie, can you
>>>>> have 2 peers, different VHT spatial groups (or 4 peers, 1 spatial
>>>>> group each) all going at the same time?
>>>>>
>>>>> I'm .. not even sure how you're supposed to cleanly negotiate that you
>>>>> can do 4NSS in VHT80 but 2NSS in VHT160 to a peer... that only makes
>>>>> sense if you're doing lots of 1NSS and 2NSS MU-MIMO peers..
>>>>
>>>> I think using the max-rx-rate logic might could imply this, but I am not sure
>>>> many drivers fill this out properly.
>>>>
>>>> Looks like a mess waiting to happen to me.
>>>>
>>>> Even if you can do 1x1 160Mhz MU-MIMO to two stations, and I am not certain you
>>>> can since in 80Mhz you can only do a 1x1 and a 2x2 (not two 2x2).
>>>>
>>>> So, from what I know currently, 80+80 is not that useful on the 9984 NIC...
>>> never tried 80+80 since i need to enhance the channel logic alot in my firmware code to handle it. would be great enough if vht160 would work as expected and
>>> i'm not sure right now if it really works, even if the interface initialized correctly it assocs only with vht80
>>
>> Looks like it is working with the hack I posted:
>>
>> Station 04:f0:21:2e:49:65 (on wlan2)
>> inactive time: 0 ms
>> rx bytes: 64902998
>> rx packets: 37918
>> tx bytes: 64760298
>> tx packets: 42239
>> tx retries: 0
>> tx failed: 0
>> signal: -43 dBm
>> signal avg: -42 dBm
>> tx bitrate: 1053.0 MBit/s VHT-MCS 6 160MHz VHT-NSS 2
>> rx bitrate: 1560.0 MBit/s VHT-MCS 8 160MHz short GI VHT-NSS 2
>> authorized: yes
>> authenticated: yes
>> preamble: long
>> WMM/WME: yes
>> MFP: no
>> TDLS peer: no
>> connected time: 156 seconds
>>
>> Thanks,
>> Ben
>>
>>
> the hack you posted crashes the driver for me. i also see that this patch is based on the CT ath10k source. it doesnt apply clean to ath10k. needed to merge it
> manually
Ok, I'm in the middle of a bunch of changes to support VHT overrides to allow
disabling VHT160/80+80 in station mode, and I'll push all my changes to my
tree when I get that implemented and testing.
I've about given up on getting ath10k patches upstream, but I'll get these changes into
ath10k-ct in LEDE sometime...
If you want to post the splat, just possibly I'll have a quick idea of why it
is crashing.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: VHT 160Mhz and nss related config.
From: Sebastian Gottschall @ 2017-02-13 22:48 UTC (permalink / raw)
To: Ben Greear, Adrian Chadd; +Cc: linux-wireless@vger.kernel.org, ath10k
In-Reply-To: <36c7dfa2-b39c-ad7a-5e39-3daf8983ed2f@candelatech.com>
Am 13.02.2017 um 20:56 schrieb Ben Greear:
> On 02/11/2017 10:21 AM, Sebastian Gottschall wrote:
>> Am 11.02.2017 um 18:58 schrieb Ben Greear:
>>> On 02/10/2017 08:37 PM, Adrian Chadd wrote:
>>>> On 10 February 2017 at 20:22, Sebastian Gottschall
>>>> <s.gottschall@dd-wrt.com> wrote:
>>>>> i really can't believe this. if this is true the 160 mhz mode
>>>>> would not
>>>>> make any sense.
>>>>> the maximum tx / rx rate for 4x4 vht80 and 2x2 vht160 is
>>>>> identical. so
>>>>> vht160 would not increase performance in any way
>>>>
>>>> Well, if it can also do 2x2 MU-MIMO at 160MHz then it can be a
>>>> perfectly fine STA to a 4x4 160MHz MU-MIMO chip that can actually
>>>> transmit 2x2 rates to different MU-MIMO peers.
>>>>
>>>> That's the outstanding question I have - is it like, 2x2 MU only, or
>>>> is it say, 2 concurrently different spatial stream 2x2 MU? Ie, can you
>>>> have 2 peers, different VHT spatial groups (or 4 peers, 1 spatial
>>>> group each) all going at the same time?
>>>>
>>>> I'm .. not even sure how you're supposed to cleanly negotiate that you
>>>> can do 4NSS in VHT80 but 2NSS in VHT160 to a peer... that only makes
>>>> sense if you're doing lots of 1NSS and 2NSS MU-MIMO peers..
>>>
>>> I think using the max-rx-rate logic might could imply this, but I am
>>> not sure
>>> many drivers fill this out properly.
>>>
>>> Looks like a mess waiting to happen to me.
>>>
>>> Even if you can do 1x1 160Mhz MU-MIMO to two stations, and I am not
>>> certain you
>>> can since in 80Mhz you can only do a 1x1 and a 2x2 (not two 2x2).
>>>
>>> So, from what I know currently, 80+80 is not that useful on the 9984
>>> NIC...
>> never tried 80+80 since i need to enhance the channel logic alot in
>> my firmware code to handle it. would be great enough if vht160 would
>> work as expected and
>> i'm not sure right now if it really works, even if the interface
>> initialized correctly it assocs only with vht80
>
> Looks like it is working with the hack I posted:
>
> Station 04:f0:21:2e:49:65 (on wlan2)
> inactive time: 0 ms
> rx bytes: 64902998
> rx packets: 37918
> tx bytes: 64760298
> tx packets: 42239
> tx retries: 0
> tx failed: 0
> signal: -43 dBm
> signal avg: -42 dBm
> tx bitrate: 1053.0 MBit/s VHT-MCS 6 160MHz VHT-NSS 2
> rx bitrate: 1560.0 MBit/s VHT-MCS 8 160MHz short GI VHT-NSS 2
> authorized: yes
> authenticated: yes
> preamble: long
> WMM/WME: yes
> MFP: no
> TDLS peer: no
> connected time: 156 seconds
>
> Thanks,
> Ben
>
>
the hack you posted crashes the driver for me. i also see that this
patch is based on the CT ath10k source. it doesnt apply clean to ath10k.
needed to merge it manually
--
Mit freundlichen Grüssen / Regards
Sebastian Gottschall / CTO
NewMedia-NET GmbH - DD-WRT
Firmensitz: Berliner Ring 101, 64625 Bensheim
Registergericht: Amtsgericht Darmstadt, HRB 25473
Geschäftsführer: Peter Steinhäuser, Christian Scheele
http://www.dd-wrt.com
email: s.gottschall@dd-wrt.com
Tel.: +496251-582650 / Fax: +496251-5826565
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox