* Re: [PATCH v3] ath10k: implement NAPI support
From: Dave Taht @ 2016-08-26 11:49 UTC (permalink / raw)
To: Johannes Berg
Cc: Rajkumar Manoharan, ath10k, linux-wireless, Rajkumar Manoharan
In-Reply-To: <1472209920.390.34.camel@sipsolutions.net>
On Fri, Aug 26, 2016 at 4:12 AM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> On Fri, 2016-08-26 at 03:48 -0700, Dave Taht wrote:
>> I'm always rather big on people testing latency under load, and napi
>> tends to add some.
>
> That's a completely useless comment.
>
> Obviously, everybody uses NAPI; it's necessary for system load and thus
> performance, and lets drivers take advantage of TCP merging to reduce
> ACKs, which is tremendously helpful (over wifi in particular.)
>
> Please stop making such drive-by comments that focus only on the single
> thing you find important above all; not all people can care only about
> that single thing, and unconstructively reiterating it over and over
> doesn't help.
Well, I apologize for being testy. It is I spent a lot of time
testing michal's patchset for the ath10k back in may, and I *will* go
and retest ath10k, when these patches land. My principal concern with
using napi is at lower rates than the maxes typically reported in a
patchset.
But it would be nice if people always did test for latency under load
when making improvements, before getting to me, and despite having
helped make a very comprehensive test suite available (flent) that
tests all sorts of things for wifi, getting people to actually use it
to see real problems, (in addition to latency under load!) while their
fingers are still hot in the codebase, and track/plot their results,
remains an ongoing issue across the entire industry.
http://blog.cerowrt.org/post/fq_codel_on_ath10k/
There are many other problems in wifi, of course, that could use
engineering mental internalization, like airtime fairness, and the
mis-behavior of the hardware queues,
http://blog.cerowrt.org/post/cs5_lockout/
wifi channel scans
http://blog.cerowrt.org/post/disabling_channel_scans/
and so on.
I have a ton more datasets and blog entries left to write up from the
ath9k work thus far which point to some other issues (minstrel,
aggregation, retries)
> Thanks,
> johannes
--=20
Dave T=C3=A4ht
Let's go make home routers and wifi faster! With better software!
http://blog.cerowrt.org
^ permalink raw reply
* Re: [PATCH v3] ath10k: implement NAPI support
From: Johannes Berg @ 2016-08-26 11:12 UTC (permalink / raw)
To: Dave Taht, Rajkumar Manoharan; +Cc: ath10k, linux-wireless, Rajkumar Manoharan
In-Reply-To: <CAA93jw7vHWROH9Ymq1UoOKA5kw+fDbCM=vJehs8J=QP2PVs_RA@mail.gmail.com>
On Fri, 2016-08-26 at 03:48 -0700, Dave Taht wrote:
> I'm always rather big on people testing latency under load, and napi
> tends to add some.
That's a completely useless comment.
Obviously, everybody uses NAPI; it's necessary for system load and thus
performance, and lets drivers take advantage of TCP merging to reduce
ACKs, which is tremendously helpful (over wifi in particular.)
Please stop making such drive-by comments that focus only on the single
thing you find important above all; not all people can care only about
that single thing, and unconstructively reiterating it over and over
doesn't help.
Thanks,
johannes
^ permalink raw reply
* Re: [PATCH v3] ath10k: implement NAPI support
From: Dave Taht @ 2016-08-26 10:48 UTC (permalink / raw)
To: Rajkumar Manoharan; +Cc: ath10k, linux-wireless, Rajkumar Manoharan
In-Reply-To: <20160826102250.24174-1-rmanohar@qti.qualcomm.com>
I'm always rather big on people testing latency under load, and napi
tends to add some.
^ permalink raw reply
* [PATCH v3] ath10k: implement NAPI support
From: Rajkumar Manoharan @ 2016-08-26 10:22 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, rmanohar, Rajkumar Manoharan
Add NAPI support for rx and tx completion. NAPI poll is scheduled
from interrupt handler. The design is as below
- on interrupt
- schedule napi and mask interrupts
- on poll
- process all pipes (no actual Tx/Rx)
- process Rx within budget
- if quota exceeds budget reschedule napi poll by returning budget
- process Tx completions and update budget if necessary
- process Tx fetch indications (pull-push)
- push any other pending Tx (if possible)
- before resched or napi completion replenish htt rx ring buffer
- if work done < budget, complete napi poll and unmask interrupts
This change also get rid of two tasklets (intr_tq and txrx_compl_task).
Measured peak throughput with NAPI on IPQ4019 platform in controlled
environment. No noticeable reduction in throughput is seen and also
observed improvements in CPU usage. Approx. 15% CPU usage got reduced
in UDP uplink case.
DL: AP DUT Tx
UL: AP DUT Rx
IPQ4019 (avg. cpu usage %)
========
TOT +NAPI
=========== =============
TCP DL 644 Mbps (42%) 645 Mbps (36%)
TCP UL 673 Mbps (30%) 675 Mbps (26%)
UDP DL 682 Mbps (49%) 680 Mbps (49%)
UDP UL 720 Mbps (28%) 717 Mbps (11%)
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
---
v2: rebased change
v3: napi_synchronize and napi_disable should be called on deinit. Otherwise
it is causing invalid memory access. Thanks to Kalle for reporting this issue.
drivers/net/wireless/ath/ath10k/ahb.c | 10 +-
drivers/net/wireless/ath/ath10k/core.c | 2 +
drivers/net/wireless/ath/ath10k/core.h | 8 ++
drivers/net/wireless/ath/ath10k/htt.h | 2 +-
drivers/net/wireless/ath/ath10k/htt_rx.c | 154 +++++++++++++++++++------------
drivers/net/wireless/ath/ath10k/htt_tx.c | 2 -
drivers/net/wireless/ath/ath10k/pci.c | 71 ++++++++------
drivers/net/wireless/ath/ath10k/pci.h | 6 +-
8 files changed, 159 insertions(+), 96 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
index acec16b9cf49..83ecfb6d1a36 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -462,13 +462,13 @@ static void ath10k_ahb_halt_chip(struct ath10k *ar)
static irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg)
{
struct ath10k *ar = arg;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
if (!ath10k_pci_irq_pending(ar))
return IRQ_NONE;
ath10k_pci_disable_and_clear_legacy_irq(ar);
- tasklet_schedule(&ar_pci->intr_tq);
+ ath10k_pci_irq_msi_fw_mask(ar);
+ napi_schedule(&ar->napi);
return IRQ_HANDLED;
}
@@ -717,6 +717,9 @@ static void ath10k_ahb_hif_stop(struct ath10k *ar)
synchronize_irq(ar_ahb->irq);
ath10k_pci_flush(ar);
+
+ napi_synchronize(&ar->napi);
+ napi_disable(&ar->napi);
}
static int ath10k_ahb_hif_power_up(struct ath10k *ar)
@@ -748,6 +751,7 @@ static int ath10k_ahb_hif_power_up(struct ath10k *ar)
ath10k_err(ar, "could not wake up target CPU: %d\n", ret);
goto err_ce_deinit;
}
+ napi_enable(&ar->napi);
return 0;
@@ -831,7 +835,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev)
goto err_resource_deinit;
}
- ath10k_pci_init_irq_tasklets(ar);
+ ath10k_pci_init_napi(ar);
ret = ath10k_ahb_request_irq_legacy(ar);
if (ret)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index e88982921aa3..0ca58cf0ffea 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2249,6 +2249,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
INIT_WORK(&ar->register_work, ath10k_core_register_work);
INIT_WORK(&ar->restart_work, ath10k_core_restart);
+ init_dummy_netdev(&ar->napi_dev);
+
ret = ath10k_debug_create(ar);
if (ret)
goto err_free_aux_wq;
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 30ae5bf81611..f36c2b274ee5 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -65,6 +65,10 @@
#define ATH10K_KEEPALIVE_MAX_IDLE 3895
#define ATH10K_KEEPALIVE_MAX_UNRESPONSIVE 3900
+/* NAPI poll budget */
+#define ATH10K_NAPI_BUDGET 64
+#define ATH10K_NAPI_QUOTA_LIMIT 60
+
struct ath10k;
enum ath10k_bus {
@@ -936,6 +940,10 @@ struct ath10k {
struct ath10k_thermal thermal;
struct ath10k_wow wow;
+ /* NAPI */
+ struct net_device napi_dev;
+ struct napi_struct napi;
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 430a83e142aa..98c14247021b 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1665,7 +1665,6 @@ struct ath10k_htt {
/* This is used to group tx/rx completions separately and process them
* in batches to reduce cache stalls */
- struct tasklet_struct txrx_compl_task;
struct sk_buff_head rx_compl_q;
struct sk_buff_head rx_in_ord_compl_q;
struct sk_buff_head tx_fetch_ind_q;
@@ -1798,5 +1797,6 @@ int ath10k_htt_tx(struct ath10k_htt *htt,
struct sk_buff *msdu);
void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
struct sk_buff *skb);
+int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget);
#endif
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 78db5d679f19..d3f8baf532d4 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -34,7 +34,6 @@
#define HTT_RX_RING_REFILL_RESCHED_MS 5
static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb);
-static void ath10k_htt_txrx_compl_task(unsigned long ptr);
static struct sk_buff *
ath10k_htt_rx_find_skb_paddr(struct ath10k *ar, u32 paddr)
@@ -226,7 +225,6 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar)
void ath10k_htt_rx_free(struct ath10k_htt *htt)
{
del_timer_sync(&htt->rx_ring.refill_retry_timer);
- tasklet_kill(&htt->txrx_compl_task);
skb_queue_purge(&htt->rx_compl_q);
skb_queue_purge(&htt->rx_in_ord_compl_q);
@@ -520,9 +518,6 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
skb_queue_head_init(&htt->tx_fetch_ind_q);
atomic_set(&htt->num_mpdus_ready, 0);
- tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task,
- (unsigned long)htt);
-
ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt rx ring size %d fill_level %d\n",
htt->rx_ring.size, htt->rx_ring.fill_level);
return 0;
@@ -958,7 +953,7 @@ static void ath10k_process_rx(struct ath10k *ar,
trace_ath10k_rx_hdr(ar, skb->data, skb->len);
trace_ath10k_rx_payload(ar, skb->data, skb->len);
- ieee80211_rx(ar->hw, skb);
+ ieee80211_rx_napi(ar->hw, NULL, skb, &ar->napi);
}
static int ath10k_htt_rx_nwifi_hdrlen(struct ath10k *ar,
@@ -1527,7 +1522,7 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
struct ath10k *ar = htt->ar;
static struct ieee80211_rx_status rx_status;
struct sk_buff_head amsdu;
- int ret;
+ int ret, num_msdus;
__skb_queue_head_init(&amsdu);
@@ -1549,13 +1544,14 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
return ret;
}
+ num_msdus = skb_queue_len(&amsdu);
ath10k_htt_rx_h_ppdu(ar, &amsdu, &rx_status, 0xffff);
ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
ath10k_htt_rx_h_filter(ar, &amsdu, &rx_status);
ath10k_htt_rx_h_mpdu(ar, &amsdu, &rx_status);
ath10k_htt_rx_h_deliver(ar, &amsdu, &rx_status);
- return 0;
+ return num_msdus;
}
static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
@@ -1579,15 +1575,6 @@ static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
mpdu_count += mpdu_ranges[i].mpdu_count;
atomic_add(mpdu_count, &htt->num_mpdus_ready);
-
- tasklet_schedule(&htt->txrx_compl_task);
-}
-
-static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt)
-{
- atomic_inc(&htt->num_mpdus_ready);
-
- tasklet_schedule(&htt->txrx_compl_task);
}
static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
@@ -1772,14 +1759,15 @@ static void ath10k_htt_rx_h_rx_offload_prot(struct ieee80211_rx_status *status,
RX_FLAG_MMIC_STRIPPED;
}
-static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
- struct sk_buff_head *list)
+static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
+ struct sk_buff_head *list)
{
struct ath10k_htt *htt = &ar->htt;
struct ieee80211_rx_status *status = &htt->rx_status;
struct htt_rx_offload_msdu *rx;
struct sk_buff *msdu;
size_t offset;
+ int num_msdu = 0;
while ((msdu = __skb_dequeue(list))) {
/* Offloaded frames don't have Rx descriptor. Instead they have
@@ -1819,10 +1807,12 @@ static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
ath10k_htt_rx_h_rx_offload_prot(status, msdu);
ath10k_htt_rx_h_channel(ar, status, NULL, rx->vdev_id);
ath10k_process_rx(ar, status, msdu);
+ num_msdu++;
}
+ return num_msdu;
}
-static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
+static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
{
struct ath10k_htt *htt = &ar->htt;
struct htt_resp *resp = (void *)skb->data;
@@ -1835,12 +1825,12 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
u8 tid;
bool offload;
bool frag;
- int ret;
+ int ret, num_msdus = 0;
lockdep_assert_held(&htt->rx_ring.lock);
if (htt->rx_confused)
- return;
+ return -EIO;
skb_pull(skb, sizeof(resp->hdr));
skb_pull(skb, sizeof(resp->rx_in_ord_ind));
@@ -1859,7 +1849,7 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
if (skb->len < msdu_count * sizeof(*resp->rx_in_ord_ind.msdu_descs)) {
ath10k_warn(ar, "dropping invalid in order rx indication\n");
- return;
+ return -EINVAL;
}
/* The event can deliver more than 1 A-MSDU. Each A-MSDU is later
@@ -1870,14 +1860,14 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
if (ret < 0) {
ath10k_warn(ar, "failed to pop paddr list: %d\n", ret);
htt->rx_confused = true;
- return;
+ return -EIO;
}
/* Offloaded frames are very different and need to be handled
* separately.
*/
if (offload)
- ath10k_htt_rx_h_rx_offload(ar, &list);
+ num_msdus = ath10k_htt_rx_h_rx_offload(ar, &list);
while (!skb_queue_empty(&list)) {
__skb_queue_head_init(&amsdu);
@@ -1890,6 +1880,7 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
* better to report something than nothing though. This
* should still give an idea about rx rate to the user.
*/
+ num_msdus += skb_queue_len(&amsdu);
ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
ath10k_htt_rx_h_filter(ar, &amsdu, status);
ath10k_htt_rx_h_mpdu(ar, &amsdu, status);
@@ -1902,9 +1893,10 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
ath10k_warn(ar, "failed to extract amsdu: %d\n", ret);
htt->rx_confused = true;
__skb_queue_purge(&list);
- return;
+ return -EIO;
}
}
+ return num_msdus;
}
static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar,
@@ -2267,7 +2259,6 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
}
case HTT_T2H_MSG_TYPE_TX_COMPL_IND:
ath10k_htt_rx_tx_compl_ind(htt->ar, skb);
- tasklet_schedule(&htt->txrx_compl_task);
break;
case HTT_T2H_MSG_TYPE_SEC_IND: {
struct ath10k *ar = htt->ar;
@@ -2284,7 +2275,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
case HTT_T2H_MSG_TYPE_RX_FRAG_IND: {
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
skb->data, skb->len);
- ath10k_htt_rx_frag_handler(htt);
+ atomic_inc(&htt->num_mpdus_ready);
break;
}
case HTT_T2H_MSG_TYPE_TEST:
@@ -2320,8 +2311,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
break;
}
case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: {
- skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
- tasklet_schedule(&htt->txrx_compl_task);
+ __skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
return false;
}
case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND:
@@ -2347,7 +2337,6 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
break;
}
skb_queue_tail(&htt->tx_fetch_ind_q, tx_fetch_ind);
- tasklet_schedule(&htt->txrx_compl_task);
break;
}
case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM:
@@ -2376,27 +2365,77 @@ void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
}
EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler);
-static void ath10k_htt_txrx_compl_task(unsigned long ptr)
+int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget)
{
- struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
- struct ath10k *ar = htt->ar;
+ struct ath10k_htt *htt = &ar->htt;
struct htt_tx_done tx_done = {};
- struct sk_buff_head rx_ind_q;
struct sk_buff_head tx_ind_q;
struct sk_buff *skb;
unsigned long flags;
- int num_mpdus;
+ int quota = 0, done, num_rx_msdus;
+ bool resched_napi = false;
- __skb_queue_head_init(&rx_ind_q);
__skb_queue_head_init(&tx_ind_q);
- spin_lock_irqsave(&htt->rx_in_ord_compl_q.lock, flags);
- skb_queue_splice_init(&htt->rx_in_ord_compl_q, &rx_ind_q);
- spin_unlock_irqrestore(&htt->rx_in_ord_compl_q.lock, flags);
+ /* Since in-ord-ind can deliver more than 1 A-MSDU in single event,
+ * process it first to utilize full available quota.
+ */
+ while (quota < budget) {
+ if (skb_queue_empty(&htt->rx_in_ord_compl_q))
+ break;
- spin_lock_irqsave(&htt->tx_fetch_ind_q.lock, flags);
- skb_queue_splice_init(&htt->tx_fetch_ind_q, &tx_ind_q);
- spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags);
+ skb = __skb_dequeue(&htt->rx_in_ord_compl_q);
+ if (!skb) {
+ resched_napi = true;
+ goto exit;
+ }
+
+ spin_lock_bh(&htt->rx_ring.lock);
+ num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb);
+ spin_unlock_bh(&htt->rx_ring.lock);
+ if (num_rx_msdus < 0) {
+ resched_napi = true;
+ goto exit;
+ }
+
+ dev_kfree_skb_any(skb);
+ if (num_rx_msdus > 0)
+ quota += num_rx_msdus;
+
+ if ((quota > ATH10K_NAPI_QUOTA_LIMIT) &&
+ !skb_queue_empty(&htt->rx_in_ord_compl_q)) {
+ resched_napi = true;
+ goto exit;
+ }
+ }
+
+ while (quota < budget) {
+ /* no more data to receive */
+ if (!atomic_read(&htt->num_mpdus_ready))
+ break;
+
+ num_rx_msdus = ath10k_htt_rx_handle_amsdu(htt);
+ if (num_rx_msdus < 0) {
+ resched_napi = true;
+ goto exit;
+ }
+
+ quota += num_rx_msdus;
+ atomic_dec(&htt->num_mpdus_ready);
+ if ((quota > ATH10K_NAPI_QUOTA_LIMIT) &&
+ atomic_read(&htt->num_mpdus_ready)) {
+ resched_napi = true;
+ goto exit;
+ }
+ }
+
+ /* From NAPI documentation:
+ * The napi poll() function may also process TX completions, in which
+ * case if it processes the entire TX ring then it should count that
+ * work as the rest of the budget.
+ */
+ if ((quota < budget) && !kfifo_is_empty(&htt->txdone_fifo))
+ quota = budget;
/* kfifo_get: called only within txrx_tasklet so it's neatly serialized.
* From kfifo_get() documentation:
@@ -2406,27 +2445,22 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
while (kfifo_get(&htt->txdone_fifo, &tx_done))
ath10k_txrx_tx_unref(htt, &tx_done);
+ spin_lock_irqsave(&htt->tx_fetch_ind_q.lock, flags);
+ skb_queue_splice_init(&htt->tx_fetch_ind_q, &tx_ind_q);
+ spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags);
+
while ((skb = __skb_dequeue(&tx_ind_q))) {
ath10k_htt_rx_tx_fetch_ind(ar, skb);
dev_kfree_skb_any(skb);
}
- num_mpdus = atomic_read(&htt->num_mpdus_ready);
-
- while (num_mpdus) {
- if (ath10k_htt_rx_handle_amsdu(htt))
- break;
-
- num_mpdus--;
- atomic_dec(&htt->num_mpdus_ready);
- }
-
- while ((skb = __skb_dequeue(&rx_ind_q))) {
- spin_lock_bh(&htt->rx_ring.lock);
- ath10k_htt_rx_in_ord_ind(ar, skb);
- spin_unlock_bh(&htt->rx_ring.lock);
- dev_kfree_skb_any(skb);
- }
-
+exit:
ath10k_htt_rx_msdu_buff_replenish(htt);
+ /* In case of rx failure or more data to read, report budget
+ * to reschedule NAPI poll
+ */
+ done = resched_napi ? budget : quota;
+
+ return done;
}
+EXPORT_SYMBOL(ath10k_htt_txrx_compl_task);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 7c072b605bc7..ae5b33fe5ba8 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -390,8 +390,6 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
{
int size;
- tasklet_kill(&htt->txrx_compl_task);
-
idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
idr_destroy(&htt->pending_tx);
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 9a22c478dd1b..4bc663979856 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -1506,12 +1506,10 @@ void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe,
ath10k_ce_per_engine_service(ar, pipe);
}
-void ath10k_pci_kill_tasklet(struct ath10k *ar)
+static void ath10k_pci_rx_retry_sync(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- tasklet_kill(&ar_pci->intr_tq);
-
del_timer_sync(&ar_pci->rx_post_retry);
}
@@ -1570,7 +1568,7 @@ void ath10k_pci_hif_get_default_pipe(struct ath10k *ar,
ul_pipe, dl_pipe);
}
-static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
+void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
{
u32 val;
@@ -1753,7 +1751,7 @@ void ath10k_pci_ce_deinit(struct ath10k *ar)
void ath10k_pci_flush(struct ath10k *ar)
{
- ath10k_pci_kill_tasklet(ar);
+ ath10k_pci_rx_retry_sync(ar);
ath10k_pci_buffer_cleanup(ar);
}
@@ -1780,6 +1778,8 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
ath10k_pci_irq_disable(ar);
ath10k_pci_irq_sync(ar);
ath10k_pci_flush(ar);
+ napi_synchronize(&ar->napi);
+ napi_disable(&ar->napi);
spin_lock_irqsave(&ar_pci->ps_lock, flags);
WARN_ON(ar_pci->ps_wake_refcount > 0);
@@ -2533,6 +2533,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
ath10k_err(ar, "could not wake up target CPU: %d\n", ret);
goto err_ce;
}
+ napi_enable(&ar->napi);
return 0;
@@ -2772,35 +2773,53 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
return IRQ_NONE;
}
- if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) {
- if (!ath10k_pci_irq_pending(ar))
- return IRQ_NONE;
-
- ath10k_pci_disable_and_clear_legacy_irq(ar);
- }
+ if ((ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) &&
+ !ath10k_pci_irq_pending(ar))
+ return IRQ_NONE;
- tasklet_schedule(&ar_pci->intr_tq);
+ ath10k_pci_disable_and_clear_legacy_irq(ar);
+ ath10k_pci_irq_msi_fw_mask(ar);
+ napi_schedule(&ar->napi);
return IRQ_HANDLED;
}
-static void ath10k_pci_tasklet(unsigned long data)
+static int ath10k_pci_napi_poll(struct napi_struct *ctx, int budget)
{
- struct ath10k *ar = (struct ath10k *)data;
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ struct ath10k *ar = container_of(ctx, struct ath10k, napi);
+ int done = 0;
if (ath10k_pci_has_fw_crashed(ar)) {
- ath10k_pci_irq_disable(ar);
ath10k_pci_fw_crashed_clear(ar);
ath10k_pci_fw_crashed_dump(ar);
- return;
+ napi_complete(ctx);
+ return done;
}
ath10k_ce_per_engine_service_any(ar);
- /* Re-enable legacy irq that was disabled in the irq handler */
- if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY)
+ done = ath10k_htt_txrx_compl_task(ar, budget);
+
+ if (done < budget) {
+ napi_complete(ctx);
+ /* In case of MSI, it is possible that interrupts are received
+ * while NAPI poll is inprogress. So pending interrupts that are
+ * received after processing all copy engine pipes by NAPI poll
+ * will not be handled again. This is causing failure to
+ * complete boot sequence in x86 platform. So before enabling
+ * interrupts safer to check for pending interrupts for
+ * immediate servicing.
+ */
+ if (CE_INTERRUPT_SUMMARY(ar)) {
+ napi_reschedule(ctx);
+ goto out;
+ }
ath10k_pci_enable_legacy_irq(ar);
+ ath10k_pci_irq_msi_fw_unmask(ar);
+ }
+
+out:
+ return done;
}
static int ath10k_pci_request_irq_msi(struct ath10k *ar)
@@ -2858,11 +2877,10 @@ static void ath10k_pci_free_irq(struct ath10k *ar)
free_irq(ar_pci->pdev->irq, ar);
}
-void ath10k_pci_init_irq_tasklets(struct ath10k *ar)
+void ath10k_pci_init_napi(struct ath10k *ar)
{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-
- tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar);
+ netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_pci_napi_poll,
+ ATH10K_NAPI_BUDGET);
}
static int ath10k_pci_init_irq(struct ath10k *ar)
@@ -2870,7 +2888,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar)
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret;
- ath10k_pci_init_irq_tasklets(ar);
+ ath10k_pci_init_napi(ar);
if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_AUTO)
ath10k_info(ar, "limiting irq mode to: %d\n",
@@ -3131,7 +3149,8 @@ int ath10k_pci_setup_resource(struct ath10k *ar)
void ath10k_pci_release_resource(struct ath10k *ar)
{
- ath10k_pci_kill_tasklet(ar);
+ ath10k_pci_rx_retry_sync(ar);
+ netif_napi_del(&ar->napi);
ath10k_pci_ce_deinit(ar);
ath10k_pci_free_pipes(ar);
}
@@ -3298,7 +3317,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
err_free_irq:
ath10k_pci_free_irq(ar);
- ath10k_pci_kill_tasklet(ar);
+ ath10k_pci_rx_retry_sync(ar);
err_deinit_irq:
ath10k_pci_deinit_irq(ar);
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index 6eca1df2ce60..9854ad56b2de 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -177,8 +177,6 @@ struct ath10k_pci {
/* Operating interrupt mode */
enum ath10k_pci_irq_mode oper_irq_mode;
- struct tasklet_struct intr_tq;
-
struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX];
/* Copy Engine used for Diagnostic Accesses */
@@ -294,8 +292,7 @@ void ath10k_pci_free_pipes(struct ath10k *ar);
void ath10k_pci_free_pipes(struct ath10k *ar);
void ath10k_pci_rx_replenish_retry(unsigned long ptr);
void ath10k_pci_ce_deinit(struct ath10k *ar);
-void ath10k_pci_init_irq_tasklets(struct ath10k *ar);
-void ath10k_pci_kill_tasklet(struct ath10k *ar);
+void ath10k_pci_init_napi(struct ath10k *ar);
int ath10k_pci_init_pipes(struct ath10k *ar);
int ath10k_pci_init_config(struct ath10k *ar);
void ath10k_pci_rx_post(struct ath10k *ar);
@@ -303,6 +300,7 @@ void ath10k_pci_flush(struct ath10k *ar);
void ath10k_pci_enable_legacy_irq(struct ath10k *ar);
bool ath10k_pci_irq_pending(struct ath10k *ar);
void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar);
+void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar);
int ath10k_pci_wait_for_target_init(struct ath10k *ar);
int ath10k_pci_setup_resource(struct ath10k *ar);
void ath10k_pci_release_resource(struct ath10k *ar);
--
2.9.2
^ permalink raw reply related
* Re: [Make-wifi-fast] [PATCH v2] mac80211: Move crypto IV generation to after TXQ dequeue.
From: Toke Høiland-Jørgensen @ 2016-08-26 8:54 UTC (permalink / raw)
To: Johannes Berg; +Cc: Dave Taht, make-wifi-fast, linux-wireless, Felix Fietkau
In-Reply-To: <1472200706.390.29.camel@sipsolutions.net>
Johannes Berg <johannes@sipsolutions.net> writes:
> On Mon, 2016-08-22 at 16:47 +0200, Toke H=C3=B8iland-J=C3=B8rgensen wrote:
>>=C2=A0
>> I suppose that could be a way to do it (i.e. have
>> ieee80211_tx_dequeue call all the TX hooks etc), but am not sure
>> whether there would be problems doing all this work in the loop
>> that's building aggregates (which is what would happen for ath9k at
>> least).
>
> I don't know, but it seems that it's worth trying.
>
>> An alternative could be to split the process up in two: An "early"
>> and "late" stage, where the early stage does everything that is not
>> sensitive to reordering and the occasional drop, and the late stage
>> is everything that is. Then the queueing step could happen in-between=20
>> the two stages, and the non-queueing path could just call both stages
>> at once. In effect, this would just make the current work-arounds be
>> more explicit in the structure, rather than being marked as
>> exceptions.
>
> I'm not sure that works the way you think it does.
>
> What you did works for fast-xmit, but *only* because that doesn't do
> software crypto. If, for some reason, the TXQ stuff combines with
> software crypto, which doesn't seem impossible (ath9k even has a module
> parameter, iirc), then you have no way for this to work.
Yeah, I realised that when I started reviewing the slow path (sorry for
not realising that straight away). The v3 takes the "split handlers"
approach for this reason. That saved having to deal with fragmentation
on TXQ dequeue, and it means that some of the processing can be done
before queueing (such as GSO splitting; having packets be as small as
possible before applying FQ to them is a good thing if we want to
realise the full potential).
It seems there are still some bugs to work out with that patch, but I'd
be grateful if you could glance at it and comment on whether you think
this is a viable way forward (provided we can work out all the bugs, of
course).
>> > Now, it's unlikely to be that simple - fragmentation, for example,
>> > might mess this up.
>> >=20
>> > Overall though, I'm definitely wondering if it should be this way,
>> > since all the special cases just add complexity.
>>=20
>> I agree that the work-arounds are iffy, but I do also think it's
>> important to keep in mind that we are improving latency by orders of
>> magnitude here. A few special cases is worth it to achieve that, IMO.
>> And then iterating towards a design that don't need them, of course
>> :)
>
> I don't really agree, I'm not going to treat this unlike any other
> feature, which gets merged when it's ready for that.
>
> Right now, your code here obviously isn't, since it doesn't even
> address the cases that ath9k could run into, so either ath9k shouldn't
> use this mac80211 feature, or the mac80211 feature needs to be fixed
> before ath9k can use it.
Yeah, I agree now that I've looked at it some more :)
> I have no problems with documenting that the TXQ stuff can only be
> used with full hardware crypto, but then we should add some checks and
> warnings in mac80211 to ensure that, i.e. not allow software keys when
> TXQ stuff is used, nor allow keys with mac80211 PN assignment, etc.
I'd much rather fix things so it works in all cases. My patch to ath9k
to use this stuff completely removes the old TX path, and things like
the airtime fairness scheduler needs the intermediate queues to work.
-Toke
^ permalink raw reply
* Re: [Make-wifi-fast] [PATCH v2] mac80211: Move crypto IV generation to after TXQ dequeue.
From: Johannes Berg @ 2016-08-26 8:38 UTC (permalink / raw)
To: Toke Høiland-Jørgensen
Cc: Dave Taht, make-wifi-fast, linux-wireless, Felix Fietkau
In-Reply-To: <87oa4k508r.fsf@toke.dk>
On Mon, 2016-08-22 at 16:47 +0200, Toke Høiland-Jørgensen wrote:
>
> I suppose that could be a way to do it (i.e. have
> ieee80211_tx_dequeue call all the TX hooks etc), but am not sure
> whether there would be problems doing all this work in the loop
> that's building aggregates (which is what would happen for ath9k at
> least).
I don't know, but it seems that it's worth trying.
> An alternative could be to split the process up in two: An "early"
> and "late" stage, where the early stage does everything that is not
> sensitive to reordering and the occasional drop, and the late stage
> is everything that is. Then the queueing step could happen in-between
> the two stages, and the non-queueing path could just call both stages
> at once. In effect, this would just make the current work-arounds be
> more explicit in the structure, rather than being marked as
> exceptions.
I'm not sure that works the way you think it does.
What you did works for fast-xmit, but *only* because that doesn't do
software crypto. If, for some reason, the TXQ stuff combines with
software crypto, which doesn't seem impossible (ath9k even has a module
parameter, iirc), then you have no way for this to work.
> > Now, it's unlikely to be that simple - fragmentation, for example,
> > might mess this up.
> >
> > Overall though, I'm definitely wondering if it should be this way,
> > since all the special cases just add complexity.
>
> I agree that the work-arounds are iffy, but I do also think it's
> important to keep in mind that we are improving latency by orders of
> magnitude here. A few special cases is worth it to achieve that, IMO.
> And then iterating towards a design that don't need them, of course
> :)
I don't really agree, I'm not going to treat this unlike any other
feature, which gets merged when it's ready for that.
Right now, your code here obviously isn't, since it doesn't even
address the cases that ath9k could run into, so either ath9k shouldn't
use this mac80211 feature, or the mac80211 feature needs to be fixed
before ath9k can use it.
I have no problems with documenting that the TXQ stuff can only be used
with full hardware crypto, but then we should add some checks and
warnings in mac80211 to ensure that, i.e. not allow software keys when
TXQ stuff is used, nor allow keys with mac80211 PN assignment, etc.
Even QoS-seqno assignment will be broken btw, so you do need a bunch
more offloads to make this work.
johannes
^ permalink raw reply
* Re: [PATCH v2] rt2x00: add support for mac addr from device tree
From: Stanislaw Gruszka @ 2016-08-26 8:22 UTC (permalink / raw)
To: Mathias Kresin; +Cc: linux-wireless
In-Reply-To: <1472195813-30471-1-git-send-email-dev@kresin.me>
On Fri, Aug 26, 2016 at 09:16:53AM +0200, Mathias Kresin wrote:
> On some devices the EEPROMs of Ralink Wi-Fi chips have a default Ralink
> MAC address set (RT3062F: 00:0C:43:30:62:00, RT3060F:
> 00:0C:43:30:60:00). Using multiple of these devices in the same network
> can cause nasty issues.
>
> Allow to override the MAC in the EEPROM with (a known good) one set in
> the device tree to bypass the issue.
>
> Signed-off-by: Mathias Kresin <dev@kresin.me>
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
^ permalink raw reply
* Re: [PATCH] cfg80211: Add support for user configurable beacon data rate
From: Johannes Berg @ 2016-08-26 8:14 UTC (permalink / raw)
To: Undekari, Sunil Dutt, Kushwaha, Purushottam
Cc: linux-wireless@vger.kernel.org, Malinen, Jouni,
Kondabattini, Ganesh, Kalikot Veetil, Mahesh Kumar,
Hullur Subramanyam, Amarnath, Kumar, Deepak (QCA)
In-Reply-To: <17fc8f16b6184c2ba09146faefd2bc8c@aphydexm01f.ap.qualcomm.com>
On Wed, 2016-08-24 at 12:30 +0000, Undekari, Sunil Dutt wrote:
> > It also doesn't check that you specified exactly one rate, but it's
> > not clear how else this would work?
> I can think of the following options here .
> 1. Consider these rates as only the preference ( in order ) to the
> host driver , but the User space would have no way of knowing what
> the driver has selected.
> 2. Limit this beacon rate to only one . cfg80211 to verify that there
> is exactly one rate to be specified.
>
> Is option 2 a viable option ?
>
Yeah, I think option 1 doesn't make much sense.
johannes
^ permalink raw reply
* Re: [PATCH] nl80211: Fix unfiltered GET_INTERFACE dumps
From: Johannes Berg @ 2016-08-26 8:13 UTC (permalink / raw)
To: Denis Kenzior, linux-wireless
In-Reply-To: <1472157884-3174-1-git-send-email-denkenz@gmail.com>
On Thu, 2016-08-25 at 15:44 -0500, Denis Kenzior wrote:
> dump_wiphy_parse only assigns filter_wiphy if one of the supported
> NL80211 attributes is present. So for unfiltered dumps, filter_wiphy
> was always initialized to 0, and only interface 0 was dumped.
>
> This was introduced in commit
> 2d75da13fbb957e955d212555b91101cef36f0ce.
>
> Reported-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
> Signed-off-by: Denis Kenzior <denkenz@gmail.com>
>
Thanks guys, I've squashed this (and moved it into the initializer we
already had.)
johannes
^ permalink raw reply
* [PATCH v5] ath10k: Fix broken NULL func data frame status for 10.4
From: Mohammed Shafi Shajakhan @ 2016-08-26 8:12 UTC (permalink / raw)
To: ath10k; +Cc: mohammed, linux-wireless, Mohammed Shafi Shajakhan,
Tamizh chelvam
From: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
Older firmware with HTT delivers incorrect tx status for null func
frames to driver, but this fixed in 10.2 and 10.4 firmware versions.
Also this workaround results in reporting of incorrect null func status
for 10.4. Fix this is by introducing a firmware feature flag for 10.4
so that this workaround is skipped and proper tx status for null func
frames are reported
Signed-off-by: Tamizh chelvam <c_traja@qti.qualcomm.com>
Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
---
[v5 based on the review comments from Michal]
drivers/net/wireless/ath/ath10k/core.c | 1 +
drivers/net/wireless/ath/ath10k/core.h | 7 +++++++
drivers/net/wireless/ath/ath10k/mac.c | 2 ++
3 files changed, 10 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index e889829..798b3f8 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -304,6 +304,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp",
[ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl",
[ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param",
+ [ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war",
};
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 30ae5bf..54e40f3 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -551,6 +551,13 @@ enum ath10k_fw_features {
*/
ATH10K_FW_FEATURE_BTCOEX_PARAM = 14,
+ /* Older firmware with HTT delivers incorrect tx status for null func
+ * frames to driver, but this fixed in 10.2 and 10.4 firmware versions.
+ * Also this workaround results in reporting of incorrect null func
+ * status for 10.4. This flag is used to skip the workaround.
+ */
+ ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR = 15,
+
/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index fb8e38d..7508ef8 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3255,6 +3255,8 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
if (ar->htt.target_version_major < 3 &&
(ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) &&
!test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
+ ar->running_fw->fw_file.fw_features) &&
+ !test_bit(ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR,
ar->running_fw->fw_file.fw_features))
return ATH10K_HW_TXRX_MGMT;
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] cfg80211: Add HT and VHT information in start_ap
From: Johannes Berg @ 2016-08-26 8:09 UTC (permalink / raw)
To: Malinen, Jouni; +Cc: linux-wireless@vger.kernel.org, Xu, Peng
In-Reply-To: <20160816123441.GA3678@jouni.qca.qualcomm.com>
On Tue, 2016-08-16 at 12:34 +0000, Malinen, Jouni wrote:
>
> > So if you get HT_VHT_NOT_INDICATED in the driver, don't you *still*
> > have to parse the IEs?
>
> Well.. Yes, I guess one would need to do that for some time until
> relevant user space is expected to have been updated to support the
> new attribute.
So I guess the question is what drivers would use this, and how, and
would we have to introduce this code into the kernel anyway?
If yes, I'd argue it might as well be in cfg80211 instead of the
driver(s).
> I guess that could be considered reasonable approach for the existing
> HT and VHT cases and new attributes would obviously be significantly
> easier to introduce with new extensions (need to remember to do this
> for HE from the beginning..).
Indeed. I'll try to also remember :)
> The parsing for these HT/VHT enabled/required is a bit strange
> combination having to go over three IEs. I'm not sure a parsing
> function to do so would be that nice.. The parsing code could indeed
> be moved to cfg80211 so that it would not need to be duplicated into
> each driver needing this, though.
Right.
johannes
^ permalink raw reply
* Re: [PATCH v6] cfg80211: Provision to allow the support for different beacon intervals
From: Johannes Berg @ 2016-08-26 8:07 UTC (permalink / raw)
To: Undekari, Sunil Dutt, Kushwaha, Purushottam
Cc: linux-wireless@vger.kernel.org, Malinen, Jouni,
Hullur Subramanyam, Amarnath, Kumar, Deepak (QCA)
In-Reply-To: <b13661a358d94e81950f6c4387681bd4@aphydexm01f.ap.qualcomm.com>
Hi,
Sorry - missed that mail somehow.
> cfg80211_validate_beacon_int -> cfg80211_iter_combinations shall be
> invoked for the interface combinations , currently.
> diff_beacon_int_gcd_min is applicable for the interface combinations
> and am not sure how can we validate this for a single interface .
> This specific interface can be part of two different groups (
> interface combinations) with different values for
> "diff_beacon_int_gcd_min".
> I don't think we can get the match for the right set of combination
> here , isn't ?
Well if you have just a single interface, any combination that contains
it is valid, so you'd just continue?
I *think* the code works by checking if any combination applies to the
currently desired state, and rejects if no combination is possible,
that would still be perfectly reasonable here, no?
> To make things simple , can we ignore the following rule
> " When >0, any beacon interval must also be bigger than this value."
> and rather have only the following one ?
> " When >0, different beacon intervals must have a GCD that's at least
> as big as this value." (To be more precise , any second interface
> which does not meet this rule , will fail to start ) .
Yeah, I suppose we could, but does that really make sense? If you can
have a smaller BI, then you could as well have a smaller GCD, no?
johannes
^ permalink raw reply
* [PATCH v2] rt2x00: add support for mac addr from device tree
From: Mathias Kresin @ 2016-08-26 7:16 UTC (permalink / raw)
To: linux-wireless
On some devices the EEPROMs of Ralink Wi-Fi chips have a default Ralink
MAC address set (RT3062F: 00:0C:43:30:62:00, RT3060F:
00:0C:43:30:60:00). Using multiple of these devices in the same network
can cause nasty issues.
Allow to override the MAC in the EEPROM with (a known good) one set in
the device tree to bypass the issue.
Signed-off-by: Mathias Kresin <dev@kresin.me>
---
As discussed before, forcing a random MAC for known default MACs would
be a wonky approach. I wouldn't be surprise to see ODMs setting an ODM
specific default MAC in the EEPROM. This would require a permanent
update of the list of known default MACs.
Changes in v2:
- new commit message, the former one was incomprehensible
drivers/net/wireless/ralink/rt2x00/rt2400pci.c | 5 +----
drivers/net/wireless/ralink/rt2x00/rt2500pci.c | 5 +----
drivers/net/wireless/ralink/rt2x00/rt2500usb.c | 5 +----
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 5 +----
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 +
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 17 +++++++++++++++++
drivers/net/wireless/ralink/rt2x00/rt61pci.c | 5 +----
drivers/net/wireless/ralink/rt2x00/rt73usb.c | 5 +----
8 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
index 155f343..085c5b4 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
@@ -1459,10 +1459,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
index 2553cdd..9832fd5 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
@@ -1585,10 +1585,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
index 2d64611..cd3ab5a 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
@@ -1349,10 +1349,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index bf3f0a3..59c49af 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -6919,10 +6919,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);
if (word == 0xffff) {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index f68d492..aa3d4cee 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -1403,6 +1403,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
*/
u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
struct ieee80211_vif *vif);
+void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr);
/*
* Interrupt context handlers.
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index 4e0c565..d659250 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -26,6 +26,8 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/log2.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
@@ -931,6 +933,21 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry,
entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
}
+void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr)
+{
+ const char *mac_addr;
+
+ mac_addr = of_get_mac_address(rt2x00dev->dev->of_node);
+ if (mac_addr)
+ ether_addr_copy(eeprom_mac_addr, mac_addr);
+
+ if (!is_valid_ether_addr(eeprom_mac_addr)) {
+ eth_random_addr(eeprom_mac_addr);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", eeprom_mac_addr);
+ }
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_set_mac_address);
+
static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
struct hw_mode_spec *spec)
{
diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
index 03013eb..5306a3b 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
@@ -2413,10 +2413,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.c b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
index c1397a6..1a29c4d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
@@ -1766,10 +1766,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Start validation of the data that has been read.
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
- if (!is_valid_ether_addr(mac)) {
- eth_random_addr(mac);
- rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
- }
+ rt2x00lib_set_mac_address(rt2x00dev, mac);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] nl80211: Fix unfiltered GET_INTERFACE dumps
From: Arend van Spriel @ 2016-08-25 21:35 UTC (permalink / raw)
To: Denis Kenzior, linux-wireless
In-Reply-To: <1472157884-3174-1-git-send-email-denkenz@gmail.com>
On 25-08-16 22:44, Denis Kenzior wrote:
> dump_wiphy_parse only assigns filter_wiphy if one of the supported
> NL80211 attributes is present. So for unfiltered dumps, filter_wiphy
> was always initialized to 0, and only interface 0 was dumped.
>
> This was introduced in commit 2d75da13fbb957e955d212555b91101cef36f0ce.
>
> Reported-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
Actually sent a patch for this issue a little earlier. I should have
Cc'ed you explicitly, I guess.
Regards,
Arend
> Signed-off-by: Denis Kenzior <denkenz@gmail.com>
> ---
> net/wireless/nl80211.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 95d55d2..ddc994a 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -2534,6 +2534,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
> struct nl80211_dump_wiphy_state state = {};
> int ret;
>
> + state.filter_wiphy = -1;
> ret = nl80211_dump_wiphy_parse(skb, cb, &state);
> if (ret)
> return ret;
>
^ permalink raw reply
* Re: [PATCH] nl80211: Fix unfiltered GET_INTERFACE dumps
From: Arend van Spriel @ 2016-08-25 22:07 UTC (permalink / raw)
To: Denis Kenzior, linux-wireless
In-Reply-To: <57BF689A.5050406@gmail.com>
On 25-08-16 23:52, Denis Kenzior wrote:
> Hi Arend,
>
> On 08/25/2016 04:35 PM, Arend van Spriel wrote:
>> On 25-08-16 22:44, Denis Kenzior wrote:
>>> dump_wiphy_parse only assigns filter_wiphy if one of the supported
>>> NL80211 attributes is present. So for unfiltered dumps, filter_wiphy
>>> was always initialized to 0, and only interface 0 was dumped.
>>>
>>> This was introduced in commit 2d75da13fbb957e955d212555b91101cef36f0ce.
>>>
>>> Reported-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
>>
>> Actually sent a patch for this issue a little earlier. I should have
>> Cc'ed you explicitly, I guess.
>>
>
> Whoops. I saw your regression report and didn't look to see if you
> fixed it :)
I wanted to avoid having to revert so I decided to take a closer look.
> Looking at your patch, I'm worried that
>
> - int filter_wiphy = -1;
> + int filter_wiphy;
>
> might still break things, since Johannes used:
>
> if (!cb->args[2]) {
> ...
Maybe my look was not close enough. In this branch cb->args[2] is set to
-1. So indeed that would make filter_wiphy uninitialized in subsequent
call(s). Thanks for catching that.
Regards,
Arend
> } else if (cb->args[2] > 0) {
> filter_wiphy = cb->args[2] - 1;
> }
>
> So for unfiltered dumps, filter_wiphy would not be initialized properly
> for the second & onward call of nl80211_dump_interface. Right?
>
> Regards,
> -Denis
^ permalink raw reply
* Re: [PATCH] nl80211: Fix unfiltered GET_INTERFACE dumps
From: Denis Kenzior @ 2016-08-25 21:52 UTC (permalink / raw)
To: Arend van Spriel, linux-wireless
In-Reply-To: <210adf6d-287c-f836-8e2c-78f42de94dee@broadcom.com>
Hi Arend,
On 08/25/2016 04:35 PM, Arend van Spriel wrote:
> On 25-08-16 22:44, Denis Kenzior wrote:
>> dump_wiphy_parse only assigns filter_wiphy if one of the supported
>> NL80211 attributes is present. So for unfiltered dumps, filter_wiphy
>> was always initialized to 0, and only interface 0 was dumped.
>>
>> This was introduced in commit 2d75da13fbb957e955d212555b91101cef36f0ce.
>>
>> Reported-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
>
> Actually sent a patch for this issue a little earlier. I should have
> Cc'ed you explicitly, I guess.
>
Whoops. I saw your regression report and didn't look to see if you
fixed it :)
Looking at your patch, I'm worried that
- int filter_wiphy = -1;
+ int filter_wiphy;
might still break things, since Johannes used:
if (!cb->args[2]) {
...
} else if (cb->args[2] > 0) {
filter_wiphy = cb->args[2] - 1;
}
So for unfiltered dumps, filter_wiphy would not be initialized properly
for the second & onward call of nl80211_dump_interface. Right?
Regards,
-Denis
^ permalink raw reply
* [PATCH] nl80211: Fix unfiltered GET_INTERFACE dumps
From: Denis Kenzior @ 2016-08-25 20:44 UTC (permalink / raw)
To: linux-wireless; +Cc: Denis Kenzior
dump_wiphy_parse only assigns filter_wiphy if one of the supported
NL80211 attributes is present. So for unfiltered dumps, filter_wiphy
was always initialized to 0, and only interface 0 was dumped.
This was introduced in commit 2d75da13fbb957e955d212555b91101cef36f0ce.
Reported-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Denis Kenzior <denkenz@gmail.com>
---
net/wireless/nl80211.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 95d55d2..ddc994a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2534,6 +2534,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
struct nl80211_dump_wiphy_state state = {};
int ret;
+ state.filter_wiphy = -1;
ret = nl80211_dump_wiphy_parse(skb, cb, &state);
if (ret)
return ret;
--
2.7.3
^ permalink raw reply related
* Re: [PATCH 4/4] ath10k: fix spurious tx/rx during boot
From: Ben Greear @ 2016-08-25 19:19 UTC (permalink / raw)
To: Michal Kazior
Cc: Kalle Valo, linux-wireless, ath10k@lists.infradead.org,
Marek Puzyniak
In-Reply-To: <CA+BoTQk5GPFnC7tT5qoG6aiN0hSNbiDAVNv7O7j2SXgCvUUjBA@mail.gmail.com>
On 08/24/2016 11:18 PM, Michal Kazior wrote:
>> I was looking at firmware to make sure that I fixed what I could there....
>>
>> From what I can tell, 10.4 should not have this bug. Did you see this only
>> on 10.1/10.2 firmware? It is of course possible that I am mis-understanding
>> 10.4....
>
> I did see it on 10.1 and 10.2. Don't recall seeing it on 10.4 though.
> If you didn't see warnings on 10.4 even after adding msleep() as per
> commit log then I guess it doesn't suffer from the bug.
I can still occasionally see that message with a 15000 ms sleep.
Based on debugging, it seems my firmware is now setting the mac-mask properly.
But, as you mention, the rxfilter is enabled very early. So, probably
it is still possible to see packets early if they are multicast, bcast, etc.
I don't think it is worth re-working the entire rx-filter calc in
the concurrency logic properly for 10.1 firmware, so I'm going to figure
my fix is good enough as is as long as it sets the mac-mask properly.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* [PATCH] nl80211: initialize state.filter_wiphy in nl80211_dump_interface()
From: Arend van Spriel @ 2016-08-25 19:20 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, Arend van Spriel
In nl80211_dump_interface() the filter_wiphy variable was set to -1.
However, that does not help as message may not contain wiphy or wdev
attribute. Instead initialize state.filter_wiphy as is done in
nl80211_dump_wiphy().
Fixes: 2d75da13fbb9 ("nl80211: Allow GET_INTERFACE dumps to be filtered")
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
---
net/wireless/nl80211.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 95d55d2..681c689 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2525,7 +2525,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
int if_idx = 0;
int wp_start = cb->args[0];
int if_start = cb->args[1];
- int filter_wiphy = -1;
+ int filter_wiphy;
struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
@@ -2534,6 +2534,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
struct nl80211_dump_wiphy_state state = {};
int ret;
+ state.filter_wiphy = -1;
ret = nl80211_dump_wiphy_parse(skb, cb, &state);
if (ret)
return ret;
--
1.9.1
^ permalink raw reply related
* Re: [PATCH] wlcore: mesh: add zone time sync support
From: Pedersen, Thomas @ 2016-08-25 18:50 UTC (permalink / raw)
To: Mishol, Guy; +Cc: Kalle Valo, linux-wireless@vger.kernel.org
In-Reply-To: <97207D90F0289D498537011312FCAD1138F55E66@DFRE01.ent.ti.com>
T24gU3VuLCAyMDE2LTA4LTIxIGF0IDEwOjEzICswMDAwLCBNaXNob2wsIEd1eSB3cm90ZToNCj4g
S2FsbGUvVGhvbWFzLA0KPiBUaGFua3MgZm9yIHlvdXIgZmVlZGJhY2suDQo+IA0KPiBUaGlzIHRp
bWUgc3luYyBzdXBwb3J0IGlzIGRpZmZlcmVudCBmcm9tIHRoZSBvbmUgdGhhdCBtYWM4MDIxMSBt
YWludGFpbnMgd2l0aCBtZXNoIHBlZXJzLg0KPiBUaGlzIHRpbWUgc3luYyBpcyBtb3N0bHkgdXNl
ZCBieSB1cHBlciBsYXllcnMgZm9yIHNldmVyYWwgYXBwbGljYXRpb25zIChsaWtlIGF1ZGlvKS4N
Cj4gSW4gdGhpcyBjYXNlIHdlIGFsbG93IHRoZSB1c2VyIHRvIGNvbmZpZ3VyZSBmb3IgZWFjaCB6
b25lIHdobyB3aWxsIGJlIHRoZSBzeW5jaHJvbml6ZXIuDQo+IFlvdSBjYW4gcmVmZXIgdG8gdGhl
IGZvbGxvd2luZyBBcHBsaWNhdGlvbiBSZXBvcnQgKGNoYXB0ZXIgNikgZm9yIG1vcmUgaW5mb3Jt
YXRpb246IGh0dHA6Ly93d3cudGkuY29tL2xpdC9hbi9zd2FhMTY2L3N3YWExNjYucGRmDQoNClNv
IGl0IGJyZWFrcyByZWd1bGFyIG1lc2ggc3luY2hyb25pemF0aW9uPyBQb3dlciBTYXZlLCBhbmQg
aW4gdGhlIGZ1dHVyZQ0KcG9zc2libHkgREZTIGFuZCBNQ0NBIHJlbHkgb24gdGhpcyB0byB3b3Jr
Lg0KDQpJdCBzb3VuZHMgbGlrZSB5b3Ugd2FudCBzb21lIGFic29sdXRlIFRTRiB0aW1lIHN5bmNo
cm9uaXplZCB3aXRoaW4gMjB1cy4NCk1lc2ggVFNGIHN5bmNocm9uaXphdGlvbiBjYW4gcHJvdmlk
ZSB0aGlzLCBpdCdzIGp1c3QgYSBsaXR0bGUgbW9yZQ0KY29tcGxpY2F0ZWQgYXMgeW91J2xsIG5l
ZWQgdG8gY29tcHV0ZSBhdCB0aGUgYXBwbGljYXRpb24gbGV2ZWwgdXNpbmcgdGhlDQpwZXItc3Rh
IG9mZnNldHMuIE1lc2ggc3luY2hyb25pemF0aW9uIGFjY3VyYWN5IHdhcyBwcmV0dHkgZ29vZCBJ
SVJDLA0KdW5mb3J0dW5hdGVseSBJIGRvbid0IGhhdmUgYW55IHRlc3QgZGF0YSB0byBzaGFyZSA6
KA0KDQp0aG9tYXMNCg==
^ permalink raw reply
* [PATCH 2/3] mwifiex: print status of FW ready event
From: Stanislaw Gruszka @ 2016-08-25 15:05 UTC (permalink / raw)
To: linux-wireless; +Cc: Amitkumar Karwar, Nishant Sarmukadam, Stanislaw Gruszka
In-Reply-To: <1472137518-10431-1-git-send-email-sgruszka@redhat.com>
For debugging purpose print content of reg->fw_status register and other
variables values when waiting for firmware ready event.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/marvell/mwifiex/pcie.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 8abbbfe..2f555b0 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -2043,6 +2043,10 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
ret = -1;
else
ret = 0;
+
+ mwifiex_dbg(adapter, INFO, "Try %d if FW is ready <%d,%#x>",
+ tries, ret, firmware_stat);
+
if (ret)
continue;
if (firmware_stat == FIRMWARE_READY_PCIE) {
--
1.8.3.1
^ permalink raw reply related
* [PATCH 1/3] mwifiex: make "PCI-E is not the winner" print more informative
From: Stanislaw Gruszka @ 2016-08-25 15:05 UTC (permalink / raw)
To: linux-wireless; +Cc: Amitkumar Karwar, Nishant Sarmukadam, Stanislaw Gruszka
In-Reply-To: <1472137518-10431-1-git-send-email-sgruszka@redhat.com>
Printing ret and adapter->winner do not provide any useful information
as those are always 0 at point where the massage is printed. Print value
read from reg->fw_status register instead.
Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/marvell/mwifiex/pcie.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 453ab6a..8abbbfe 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -2074,8 +2074,7 @@ mwifiex_check_winner_status(struct mwifiex_adapter *adapter)
adapter->winner = 1;
} else {
mwifiex_dbg(adapter, ERROR,
- "PCI-E is not the winner <%#x,%d>, exit dnld\n",
- ret, adapter->winner);
+ "PCI-E is not the winner <%#x>", winner);
}
return ret;
--
1.8.3.1
^ permalink raw reply related
* [PATCH 0/3] mwifiex: FW downloading debug printing improvements
From: Stanislaw Gruszka @ 2016-08-25 15:05 UTC (permalink / raw)
To: linux-wireless; +Cc: Amitkumar Karwar, Nishant Sarmukadam, Stanislaw Gruszka
3 small patches that make FW downloading prints more informative
Stanislaw Gruszka (3):
mwifiex: make "PCI-E is not the winner" print more informative
mwifiex: print status of FW ready event
mwifiex: do not print dot when downloading FW
drivers/net/wireless/marvell/mwifiex/pcie.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
--
1.8.3.1
^ permalink raw reply
* Re: [PATCH] rt2x00: add support for mac addr from device tree
From: Stanislaw Gruszka @ 2016-08-25 15:18 UTC (permalink / raw)
To: Mathias Kresin; +Cc: linux-wireless
In-Reply-To: <CABwW5n=Jomr+EO4dp3mzhV0HFxdfrAJuc=cZv8fdmRe31OS+3Q@mail.gmail.com>
On Thu, Aug 25, 2016 at 05:03:06PM +0200, Mathias Kresin wrote:
> 2016-08-25 15:19 GMT+02:00 Stanislaw Gruszka <sgruszka@redhat.com>:
> > On Thu, Aug 25, 2016 at 01:12:22PM +0200, Mathias Kresin wrote:
> >> 2016-08-25 11:33 GMT+02:00 Stanislaw Gruszka <sgruszka@redhat.com>:
> >> > On Thu, Aug 25, 2016 at 10:19:22AM +0200, Mathias Kresin wrote:
>
> >> CPE = Customer Premises Equipment or the small plastic box from your
> >> ISP at home. The whole point of the patch is that the MAC stored in
> >> the wifi EEPROM might not be unique and need to be overridden. I'm
> >> aware of three different "home router", where each model has the same
> >> generic ralink MAC address stored in the wifi EEPROM. This can cause
> >> nasty issues.
> >
> > I think we still want MAC from EEPROM instead of random one on systems
> > without OF. Otherwise we could just use random MAC every time, but this
> > does not seems lika a good idea.
>
> Either I got you wrong, the code does something different than I
> intended/tested or you misread the code.
I misread the patch. It's ok (except the changelog).
Thanks
Stanislaw
^ permalink raw reply
* Re: rtl8192ce
From: Jes Sorensen @ 2016-08-25 15:13 UTC (permalink / raw)
To: Larry Finger; +Cc: Lobachevskii Vitalii, linux-wireless
In-Reply-To: <6f06ce56-6289-6931-973f-1c52886e2b45@lwfinger.net>
Larry Finger <Larry.Finger@lwfinger.net> writes:
> On 08/25/2016 08:17 AM, Jes Sorensen wrote:
>> Lobachevskii Vitalii <silverunicorn2011@yandex.ru> writes:
>> The realtek devices all require firmwere to operate correctly,
>> including the 8192c series. There are a bunch of commands flying back
>> and forth between the driver and the firmware.
>>
>> If your device happens to work without loading the firmware then you
>> have an old firmware blob loaded.
>>
>> At least this is the case for the USB version of the device, and I find
>> it highly unlikely the PCIe version is any different.
>>
>> Trying to remove the firmware loading error is just plain silly.
>
> I have not bothered my Realtek contacts with such a question, but I
> have a plausible explanation. If an RTL8192CE functions without
> loading external firmware, it is because the device has minimal
> function built in the default firmware. Mostly this rudimentary
> firmware is used to boot the device and to download the firmware for
> complex wireless communication. Rudimentary wifi functions would be
> needed for wake-on-lan operations. The fact that Realtek has never
> implemented WOL for the 8192C chips is highly suggestive that they do
> not function very well in that capacity.
>
> If the RTL8192CE actually runs without loading external firmware, then
> I am quite sure that it will be restricted to 802.11g at the most, and
> more likely 802.11b. If it handles any 802.11n capabilities, then that
> firmware will certainly not have any of the bug fixes applied to the
> firmware since the earliest release.
>
> You are certainly allowed to configure your system any way you want,
> but please do not send any such "fixes" to the kernel sources. They
> will NEVER be accepted!
>
> Configuring a kernel without firmware loading capacity is indeed silly.
Makes perfect sense, but as you also correctly point out, it means the
device actually is running some firmware, but we have no idea what state
or version it is. Trying to run a device with this level of firmware is
both risky and makes it hard to rely on correct operation.
Of course it also makes this whole ostrich process even more pointless,
since the device is in fact running firmware - pretending it isn't is
just silly.
One more thing, yes you can apply this patch to your own degraded
kernel, but if you ship it, kindle remove ALL email addresses of any
driver authors in it. None of us wants to waste our time on bug reports
because of this.
If you truly want to run your system without firmware, I hear there are
great bargains for NE2000 and 3c501 cards on ebay :)
Jes
^ 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