* Re: Ath10k probe response error related to mac80211 commit.
From: Ben Greear @ 2016-09-01 18:23 UTC (permalink / raw)
To: Johannes Berg, linux-wireless@vger.kernel.org
In-Reply-To: <1472752911.9608.11.camel@sipsolutions.net>
On 09/01/2016 11:01 AM, Johannes Berg wrote:
>
>> If someone has any idea of why this patch might trigger it, please
>> let me know.
>> I'll keep digging in the meantime...
>>
>> Revert "mac80211: don't advertise NL80211_FEATURE_FULL_AP_CLIENT_STATE"
>>
>
> With a sufficiently recent hostapd/wpa_supplicant, the patch will cause
> a station entry to be added to the firmware before sending the
> authentication frame.
>
> Why, of all frames, probe response frames should be corrupted I don't
> know - I could imagine auth/assoc replies being treated differently
> since they are now with a station entry rather than without.
Could easily be that others are corrupted too, but since probe resp is bad,
the association will not proceed.
>
>> This only breaks AP mode (station mode works fine).
>
> It also has no impact on anything but AP mode, as even indicated by the
> name of the flag :)
Heh, I spent 4 days tracking this down, so I wanted to be precise in
my bug report :)
> Anyway, I was pretty sure this was safe and it does help other drivers
> to have the full state, but I guess you can make the driver opt out of
> the flag again (just unset it before register_hw).
The result I see is that there is an extra 10 bytes at the end of the frame on
air. But, it looks like the exact same pkt is sent to the firmware both with
and without this patch. Maybe the firmware is using the wrong tid or something
like that due to how the station is created differently with this patch.
Since this only happens (as far as I know) with my modified firmware, then
I will try to fix it there. Or, possibly I can change ath10k driver to flip this
mac80211 flag when loading my firmware variant if firmware cannot be easily fixed.
Thanks for the info,
--Ben
>
> johannes
>
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* RE: [PATCH] mwifiex: handle edmac vendor command
From: Amitkumar Karwar @ 2016-09-01 16:34 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <87poon1xka.fsf@kamboji.qca.qualcomm.com>
Hi Kalle,
> From: Kalle Valo [mailto:kvalo@codeaurora.org]
> Sent: Thursday, September 01, 2016 8:23 PM
> To: Amitkumar Karwar
> Cc: linux-wireless@vger.kernel.org
> Subject: Re: [PATCH] mwifiex: handle edmac vendor command
>
> Amitkumar Karwar <akarwar@marvell.com> writes:
>
> >> From: Kalle Valo [mailto:kvalo@codeaurora.org]
> >> Sent: Tuesday, May 24, 2016 1:53 AM
> >> To: Amitkumar Karwar
> >> Cc: linux-wireless@vger.kernel.org
> >> Subject: Re: [PATCH] mwifiex: handle edmac vendor command
> >>
> >> Amitkumar Karwar <akarwar@marvell.com> writes:
> >>
> >> > Hi Kalle,
> >> >
> >> >> From: Amitkumar Karwar [mailto:akarwar@marvell.com]
> >> >> Sent: Friday, April 29, 2016 9:28 PM
> >> >> To: linux-wireless@vger.kernel.org
> >> >> Cc: Jeff CF Chen; Amitkumar Karwar
> >> >> Subject: [PATCH] mwifiex: handle edmac vendor command
> >> >>
> >> >> From: chunfan chen <jeffc@marvell.com>
> >> >>
> >> >> Userspace can configure edmac values through a custom vendor
> command.
> >> >> They will be used by hardware for adaptivity.
> >> >>
> >> >> Signed-off-by: chunfan chen <jeffc@marvell.com>
> >> >> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> >>
> >> [deleted over 200 lines of unnecessary quotes]
> >>
> >> > This patch seems to have deferred. We basically want a way to
> >> > download a vendor specific configuration to our firmware. Do you
> >> > have any suggestions on how can achieve this in better way?
> >> >
> >> > I can see below iw command suits our requirement.
> >> >
> >> > iw dev <devname> vendor send <oui> <subcmd> <filename|-|hex data>
> >> >
> >> > Please guide.
> >>
> >> It was deferred because use of the nl80211 vendor interface (which I
> >> don't think belong to upstream drivers). I'll take a look at this
> >> patch in detail after the merge window.
> >>
> >
> > Did you get a chance to check this patch?
> > Please let me know if you have any suggestions.
>
> Sorry for the delay. I have been thinking about vendor commands quite a
> lot and I don't think they belong to upstream drivers. For regular use
> cases (used by normal users) we have nl80211, for developer and testing
> purposes we have debugfs and for manufacturing type of tests we have
> nl80211 testmode interface. The focus of development should be adding
> new functionality to nl80211 (and other generic interfaces), not to
> driver specific vendor commands.
>
> I know brcm80211 and ti's wlcore have few vendor commands but I'm hoping
> to remove them sometime soon.
>
> Thoughts?
>
Thanks for your reply.
There is something called energy detect mode. Chip can detect non-WiFi radio signal also and monitor it for specified time before transmitting frames.
As per ETSI specification, enabling this mode is mandatory for some countries for certain frequencies.
The purpose of this patch is to configure the chip for working in this mode.
I can see cfg80211 has a framework to handle vendor specific commands and events. I think having vendor commands would be helpful to support vendor specific functionalities which can't be generalized.
I suppose debugfs interface is only for collecting stats and info which can be used for debugging purpose.
Regards,
Amitkumar
^ permalink raw reply
* Ath10k probe response error related to mac80211 commit.
From: Ben Greear @ 2016-09-01 16:29 UTC (permalink / raw)
To: linux-wireless@vger.kernel.org
I have a variant of the ath10k 10.1 firmware that puts all frames, including management,
over the normal htt packet transport. This has worked fine for many kernels, but
for reasons that currently escape me, the patch below breaks this firmware.
On air, I see corrupted probe responses, seems the end of the frames are corrupted.
This only breaks AP mode (station mode works fine).
There may be some other similar breakage somewhere, since git bisect could not find this
error and I had to bisect it by hand.
If someone has any idea of why this patch might trigger it, please let me know.
I'll keep digging in the meantime...
Author: Johannes Berg <johannes.berg@intel.com> 2015-11-26 07:26:14
Committer: Johannes Berg <johannes.berg@intel.com> 2015-12-04 05:43:32
Tags: ben-bad-athia-6
Parent: bda95eb1d1581cfd79e9717ebda4b7ccd2265351 (cfg80211: handle add_station auth/assoc flag quirks)
Child: 86c7ec9eb154020797c39e1cc7dafa92da02f603 (mac80211: properly free skb when r-o-c for TX fails)
Branches: master, remotes/origin/master
Follows: ben-good-athia-7
Precedes: ben-bad-5-athai
Revert "mac80211: don't advertise NL80211_FEATURE_FULL_AP_CLIENT_STATE"
This reverts commit 45bb780a2147b9995f3d288c44ecb87ca8a330e2,
the previous two patches fixed the functionality.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----------------------------- net/mac80211/main.c -----------------------------
index 175ffcf..858f6b1 100644
@@ -541,7 +541,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
NL80211_FEATURE_HT_IBSS |
NL80211_FEATURE_VIF_TXPOWER |
NL80211_FEATURE_MAC_ON_CREATE |
- NL80211_FEATURE_USERSPACE_MPM;
+ NL80211_FEATURE_USERSPACE_MPM |
+ NL80211_FEATURE_FULL_AP_CLIENT_STATE;
if (!ops->hw_scan)
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: linux-4.8-rcX: ath9k traceback
From: Kalle Valo @ 2016-09-01 16:15 UTC (permalink / raw)
To: Mimi Zohar
Cc: QCA ath9k Development, ath9k-devel, linux-wireless,
Luis R. Rodriguez
In-Reply-To: <1472682267.2607.8.camel@linux.vnet.ibm.com>
Mimi Zohar <zohar@linux.vnet.ibm.com> writes:
> There weren't any problems on linux-4.7 kernels. I'm getting the
> following traceback on linux-4.8-rc1/-rc4 kernels. Let me know if you
> need any additional information.
>
> [ 64.006529] WARNING: CPU: 3 PID: 94 at drivers/net/wireless/ath/ath9k/beacon.c:642 ath9k_beacon_config+0x12c/0x140 [ath9k]
This should fix it:
ath9k: fix client mode beacon configuration
https://git.kernel.org/cgit/linux/kernel/git/kvalo/wireless-drivers.git/commit/?id=05860bed491b114a9f2d7a4f6e09fb02c0b69056
--
Kalle Valo
^ permalink raw reply
* [PATCH] ath10k: Remove unnecessary error code assignment
From: Mohammed Shafi Shajakhan @ 2016-09-01 16:13 UTC (permalink / raw)
To: ath10k; +Cc: mohammed, linux-wireless, Mohammed Shafi Shajakhan
From: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
The error assigned does not seems to be used anywhere,
fixes nothing just a small cleanup
Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/wmi.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index eb2831c..3117a71 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -3544,7 +3544,6 @@ void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
ath10k_warn(ar, "failed to map beacon: %d\n",
ret);
dev_kfree_skb_any(bcn);
- ret = -EIO;
goto skip;
}
--
1.9.1
^ permalink raw reply related
* [PATCH v5] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Toke Høiland-Jørgensen @ 2016-09-01 16:03 UTC (permalink / raw)
To: make-wifi-fast, linux-wireless; +Cc: Toke Høiland-Jørgensen
In-Reply-To: <20160830131548.6014-1-toke@toke.dk>
The TXQ intermediate queues can cause packet reordering when more than
one flow is active to a single station. Since some of the wifi-specific
packet handling (notably sequence number and encryption handling) is
sensitive to re-ordering, things break if they are applied before the
TXQ.
This splits up the TX handlers and fast_xmit logic into two parts: An
early part and a late part. The former is applied before TXQ enqueue,
and the latter after dequeue. The non-TXQ path just applies both parts
at once.
To avoid having to deal with fragmentation on dequeue, the split is set
to be after the fragmentation handler. This means that some reordering
of TX handlers is necessary, and some handlers had to be made aware of
fragmentation due to this reordering.
This approach avoids having to scatter special cases for when TXQ is
enabled, at the cost of making the fast_xmit and TX handler code
slightly more complex.
Signed-off-by: Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk>
---
Changes since v4:
- Keep fragnum assignment in fragmentation handler and fix endianness
issues in seqno handler.
- Assume xmit_fast_finish can't fail in dequeue handler (and warn if
fast_tx handle disappears).
- Move TKIP MIC and key selection handlers back before fragmentation
handler. Turns out the MIC doesn't actually depend on a global
sequence number, so it can be before the intermediate queueing step.
The only cost of this is running the key selection handler twice in
some cases.
- Improve readability of the composite invoke_tx_handlers() function.
include/net/mac80211.h | 2 +
net/mac80211/tx.c | 266 +++++++++++++++++++++++++++++++++++++++----=
------
2 files changed, 214 insertions(+), 54 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index cca510a..9a6a3e9 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -715,6 +715,7 @@ enum mac80211_tx_info_flags {
* frame (PS-Poll or uAPSD).
* @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate info=
rmation
* @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
+ * @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xm=
it path
*
* These flags are used in tx_info->control.flags.
*/
@@ -723,6 +724,7 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_CTRL_PS_RESPONSE =3D BIT(1),
IEEE80211_TX_CTRL_RATE_INJECT =3D BIT(2),
IEEE80211_TX_CTRL_AMSDU =3D BIT(3),
+ IEEE80211_TX_CTRL_FAST_XMIT =3D BIT(4),
};
=20
/*
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 1d0746d..f7373c2 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -38,6 +38,12 @@
#include "wme.h"
#include "rate.h"
=20
+static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx);
+static bool ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sda=
ta,
+ struct sta_info *sta,
+ struct ieee80211_fast_tx *fast_tx,
+ struct sk_buff *skb, bool xmit);
+
/* misc utils */
=20
static inline void ieee80211_tx_stats(struct net_device *dev, u32 len)
@@ -585,20 +591,27 @@ static ieee80211_tx_result debug_noinline
ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
{
struct ieee80211_key *key;
- struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(tx->skb);
- struct ieee80211_hdr *hdr =3D (struct ieee80211_hdr *)tx->skb->data;
+ struct ieee80211_tx_info *info;
+ struct ieee80211_hdr *hdr;
+ struct sk_buff *skb =3D tx->skb;
+
+ if (!skb)
+ skb =3D skb_peek(&tx->skbs);
+
+ info =3D IEEE80211_SKB_CB(skb);
+ hdr =3D (struct ieee80211_hdr *)skb->data;
=20
if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
tx->key =3D NULL;
else if (tx->sta &&
(key =3D rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
tx->key =3D key;
- else if (ieee80211_is_group_privacy_action(tx->skb) &&
+ else if (ieee80211_is_group_privacy_action(skb) &&
(key =3D rcu_dereference(tx->sdata->default_multicast_key)))
tx->key =3D key;
else if (ieee80211_is_mgmt(hdr->frame_control) &&
is_multicast_ether_addr(hdr->addr1) &&
- ieee80211_is_robust_mgmt_frame(tx->skb) &&
+ ieee80211_is_robust_mgmt_frame(skb) &&
(key =3D rcu_dereference(tx->sdata->default_mgmt_key)))
tx->key =3D key;
else if (is_multicast_ether_addr(hdr->addr1) &&
@@ -628,8 +641,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *t=
x)
case WLAN_CIPHER_SUITE_GCMP_256:
if (!ieee80211_is_data_present(hdr->frame_control) &&
!ieee80211_use_mfp(hdr->frame_control, tx->sta,
- tx->skb) &&
- !ieee80211_is_group_privacy_action(tx->skb))
+ skb) &&
+ !ieee80211_is_group_privacy_action(skb))
tx->key =3D NULL;
else
skip_hw =3D (tx->key->conf.flags &
@@ -799,10 +812,12 @@ static __le16 ieee80211_tx_next_seq(struct sta_info=
*sta, int tid)
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
{
- struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(tx->skb);
- struct ieee80211_hdr *hdr =3D (struct ieee80211_hdr *)tx->skb->data;
+ struct sk_buff *skb =3D skb_peek(&tx->skbs);
+ struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr =3D (struct ieee80211_hdr *)skb->data;
u8 *qc;
int tid;
+ __le16 seq;
=20
/*
* Packet injection may want to control the sequence
@@ -829,10 +844,15 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *t=
x)
*/
if (!ieee80211_is_data_qos(hdr->frame_control) ||
is_multicast_ether_addr(hdr->addr1)) {
- /* driver should assign sequence number */
- info->flags |=3D IEEE80211_TX_CTL_ASSIGN_SEQ;
- /* for pure STA mode without beacons, we can do it */
- hdr->seq_ctrl =3D cpu_to_le16(tx->sdata->sequence_number);
+ seq =3D cpu_to_le16(tx->sdata->sequence_number);
+ skb_queue_walk(&tx->skbs, skb) {
+ info =3D IEEE80211_SKB_CB(skb);
+ hdr =3D (struct ieee80211_hdr *)skb->data;
+ /* driver should assign sequence number */
+ info->flags |=3D IEEE80211_TX_CTL_ASSIGN_SEQ;
+ /* for pure STA mode without beacons, we can do it */
+ hdr->seq_ctrl |=3D seq;
+ }
tx->sdata->sequence_number +=3D 0x10;
if (tx->sta)
tx->sta->tx_stats.msdu[IEEE80211_NUM_TIDS]++;
@@ -853,8 +873,13 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx=
)
tid =3D *qc & IEEE80211_QOS_CTL_TID_MASK;
tx->sta->tx_stats.msdu[tid]++;
=20
- if (!tx->sta->sta.txq[0])
- hdr->seq_ctrl =3D ieee80211_tx_next_seq(tx->sta, tid);
+ if (!tx->sta->sta.txq[0]) {
+ seq =3D ieee80211_tx_next_seq(tx->sta, tid);
+ skb_queue_walk(&tx->skbs, skb) {
+ hdr =3D (struct ieee80211_hdr *)skb->data;
+ hdr->seq_ctrl |=3D seq;
+ }
+ }
=20
return TX_CONTINUE;
}
@@ -1481,33 +1506,57 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee8=
0211_hw *hw,
{
struct ieee80211_local *local =3D hw_to_local(hw);
struct txq_info *txqi =3D container_of(txq, struct txq_info, txq);
- struct ieee80211_hdr *hdr;
struct sk_buff *skb =3D NULL;
struct fq *fq =3D &local->fq;
struct fq_tin *tin =3D &txqi->tin;
+ struct ieee80211_tx_info *info;
=20
spin_lock_bh(&fq->lock);
=20
if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags))
goto out;
=20
+begin:
skb =3D fq_tin_dequeue(fq, tin, fq_tin_dequeue_func);
if (!skb)
goto out;
=20
ieee80211_set_skb_vif(skb, txqi);
=20
- hdr =3D (struct ieee80211_hdr *)skb->data;
- if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) {
+ info =3D IEEE80211_SKB_CB(skb);
+ if (txq->sta && info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
struct sta_info *sta =3D container_of(txq->sta, struct sta_info,
sta);
- struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
+ struct ieee80211_fast_tx *fast_tx;
=20
- hdr->seq_ctrl =3D ieee80211_tx_next_seq(sta, txq->tid);
- if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
- info->flags |=3D IEEE80211_TX_CTL_AMPDU;
- else
- info->flags &=3D ~IEEE80211_TX_CTL_AMPDU;
+ fast_tx =3D rcu_dereference(sta->fast_tx);
+ if (WARN_ON(!fast_tx)) {
+ /* lost the fast_tx pointer while the packet was queued */
+ ieee80211_free_txskb(hw, skb);
+ goto begin;
+ }
+ ieee80211_xmit_fast_finish(sta->sdata, sta, fast_tx, skb, false);
+ } else {
+ struct ieee80211_tx_data tx =3D { };
+
+ __skb_queue_head_init(&tx.skbs);
+ tx.local =3D local;
+ if (txq->sta) {
+ struct sta_info *sta =3D container_of(txq->sta,
+ struct sta_info,
+ sta);
+ tx.sta =3D container_of(txq->sta, struct sta_info, sta);
+ tx.sdata =3D sta->sdata;
+ } else {
+ tx.sdata =3D vif_to_sdata(info->control.vif);
+ }
+
+ __skb_queue_tail(&tx.skbs, skb);
+
+ if (invoke_tx_handlers_late(&tx))
+ goto begin;
+
+ __skb_unlink(skb, &tx.skbs);
}
=20
out:
@@ -1521,6 +1570,71 @@ out:
}
EXPORT_SYMBOL(ieee80211_tx_dequeue);
=20
+static bool ieee80211_queue_skb(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
+ struct fq *fq =3D &local->fq;
+ struct ieee80211_vif *vif;
+ struct txq_info *txqi;
+
+ if (!local->ops->wake_tx_queue)
+ return false;
+
+ if (sdata->vif.type =3D=3D NL80211_IFTYPE_AP_VLAN)
+ sdata =3D container_of(sdata->bss,
+ struct ieee80211_sub_if_data, u.ap);
+
+ vif =3D &sdata->vif;
+ txqi =3D ieee80211_get_txq(local, vif, sta, skb);
+
+ if (!txqi)
+ return false;
+
+ info->control.vif =3D vif;
+
+ spin_lock_bh(&fq->lock);
+ ieee80211_txq_enqueue(local, txqi, skb);
+ spin_unlock_bh(&fq->lock);
+
+ drv_wake_tx_queue(local, txqi);
+
+ return true;
+}
+
+static bool ieee80211_queue_frags(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta,
+ struct sk_buff_head *skbs)
+{
+ struct sk_buff *skb;
+ struct ieee80211_sta *pubsta;
+
+ if (WARN_ON(skb_queue_empty(skbs)))
+ return true;
+
+ if (!local->ops->wake_tx_queue ||
+ sdata->vif.type =3D=3D NL80211_IFTYPE_MONITOR)
+ return false;
+
+ if (sta && sta->uploaded)
+ pubsta =3D &sta->sta;
+ else
+ pubsta =3D NULL;
+
+ while (!skb_queue_empty(skbs)) {
+ skb =3D __skb_dequeue(skbs);
+ if (unlikely(!ieee80211_queue_skb(local, sdata, pubsta, skb))) {
+ __skb_queue_head(skbs, skb);
+ return false;
+ }
+ }
+
+ return true;
+}
+
static bool ieee80211_tx_frags(struct ieee80211_local *local,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -1528,9 +1642,7 @@ static bool ieee80211_tx_frags(struct ieee80211_loc=
al *local,
bool txpending)
{
struct ieee80211_tx_control control =3D {};
- struct fq *fq =3D &local->fq;
struct sk_buff *skb, *tmp;
- struct txq_info *txqi;
unsigned long flags;
=20
skb_queue_walk_safe(skbs, skb, tmp) {
@@ -1545,21 +1657,6 @@ static bool ieee80211_tx_frags(struct ieee80211_lo=
cal *local,
}
#endif
=20
- txqi =3D ieee80211_get_txq(local, vif, sta, skb);
- if (txqi) {
- info->control.vif =3D vif;
-
- __skb_unlink(skb, skbs);
-
- spin_lock_bh(&fq->lock);
- ieee80211_txq_enqueue(local, txqi, skb);
- spin_unlock_bh(&fq->lock);
-
- drv_wake_tx_queue(local, txqi);
-
- continue;
- }
-
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
if (local->queue_stop_reasons[q] ||
(!txpending && !skb_queue_empty(&local->pending[q]))) {
@@ -1680,8 +1777,12 @@ static bool __ieee80211_tx(struct ieee80211_local =
*local,
/*
* Invoke TX handlers, return 0 on success and non-zero if the
* frame was dropped or queued.
+ *
+ * The handlers are split into an early and late part. The latter is eve=
rything
+ * that can be sensitive to reordering, and will be deferred to after pa=
ckets
+ * are dequeued from the intermediate queues (when they are enabled).
*/
-static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
+static int invoke_tx_handlers_early(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(tx->skb);
ieee80211_tx_result res =3D TX_DROP;
@@ -1708,9 +1807,32 @@ static int invoke_tx_handlers(struct ieee80211_tx_=
data *tx)
}
CALL_TXH(ieee80211_tx_h_michael_mic_add);
- CALL_TXH(ieee80211_tx_h_sequence);
CALL_TXH(ieee80211_tx_h_fragment);
- /* handlers after fragment must be aware of tx info fragmentation! */
+
+ txh_done:
+ if (unlikely(res =3D=3D TX_DROP)) {
+ I802_DEBUG_INC(tx->local->tx_handlers_drop);
+ if (tx->skb)
+ ieee80211_free_txskb(&tx->local->hw, tx->skb);
+ else
+ ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
+ return -1;
+ } else if (unlikely(res =3D=3D TX_QUEUED)) {
+ I802_DEBUG_INC(tx->local->tx_handlers_queued);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* late tx handlers must be aware of tx info fragmentation! */
+static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx)
+{
+ ieee80211_tx_result res =3D TX_DROP;
+
+ if (!tx->key) /* Not set unless early and late handlers where chained. =
*/
+ CALL_TXH(ieee80211_tx_h_select_key);
+ CALL_TXH(ieee80211_tx_h_sequence);
CALL_TXH(ieee80211_tx_h_stats);
CALL_TXH(ieee80211_tx_h_encrypt);
if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
@@ -1733,6 +1856,15 @@ static int invoke_tx_handlers(struct ieee80211_tx_=
data *tx)
return 0;
}
=20
+static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
+{
+ int r =3D invoke_tx_handlers_early(tx);
+ if (r)
+ return r;
+
+ return invoke_tx_handlers_late(tx);
+}
+
bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct sk_buff *skb,
int band, struct ieee80211_sta **sta)
@@ -1807,7 +1939,13 @@ static bool ieee80211_tx(struct ieee80211_sub_if_d=
ata *sdata,
info->hw_queue =3D
sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
=20
- if (!invoke_tx_handlers(&tx))
+ if (invoke_tx_handlers_early(&tx))
+ return false;
+
+ if (ieee80211_queue_frags(local, sdata, tx.sta, &tx.skbs))
+ return true;
+
+ if (!invoke_tx_handlers_late(&tx))
result =3D __ieee80211_tx(local, &tx.skbs, led_len,
tx.sta, txpending);
=20
@@ -3170,8 +3308,6 @@ static bool ieee80211_xmit_fast(struct ieee80211_su=
b_if_data *sdata,
struct ethhdr eth;
struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr =3D (void *)fast_tx->hdr;
- struct ieee80211_tx_data tx;
- ieee80211_tx_result r;
struct tid_ampdu_tx *tid_tx =3D NULL;
u8 tid =3D IEEE80211_NUM_TIDS;
=20
@@ -3240,11 +3376,30 @@ static bool ieee80211_xmit_fast(struct ieee80211_=
sub_if_data *sdata,
info->flags =3D IEEE80211_TX_CTL_FIRST_FRAGMENT |
IEEE80211_TX_CTL_DONTFRAG |
(tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
+ info->control.flags =3D IEEE80211_TX_CTRL_FAST_XMIT;
+
+ if (ieee80211_queue_skb(local, sdata, &sta->sta, skb))
+ return true;
+
+ return ieee80211_xmit_fast_finish(sdata, sta, fast_tx, skb, true);
+}
+
+static bool ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sda=
ta,
+ struct sta_info *sta,
+ struct ieee80211_fast_tx *fast_tx,
+ struct sk_buff *skb, bool xmit)
+{
+ struct ieee80211_local *local =3D sdata->local;
+ struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr =3D (void *)skb->data;
+ struct ieee80211_tx_data tx;
+ ieee80211_tx_result r;
+ u8 tid =3D IEEE80211_NUM_TIDS;
=20
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
+ tid =3D skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
*ieee80211_get_qos_ctl(hdr) =3D tid;
- if (!sta->sta.txq[0])
- hdr->seq_ctrl =3D ieee80211_tx_next_seq(sta, tid);
+ hdr->seq_ctrl =3D ieee80211_tx_next_seq(sta, tid);
} else {
info->flags |=3D IEEE80211_TX_CTL_ASSIGN_SEQ;
hdr->seq_ctrl =3D cpu_to_le16(sdata->sequence_number);
@@ -3309,12 +3464,15 @@ static bool ieee80211_xmit_fast(struct ieee80211_=
sub_if_data *sdata,
}
}
=20
- if (sdata->vif.type =3D=3D NL80211_IFTYPE_AP_VLAN)
- sdata =3D container_of(sdata->bss,
- struct ieee80211_sub_if_data, u.ap);
+ if (xmit) {
+ if (sdata->vif.type =3D=3D NL80211_IFTYPE_AP_VLAN)
+ sdata =3D container_of(sdata->bss,
+ struct ieee80211_sub_if_data, u.ap);
+
+ __skb_queue_tail(&tx.skbs, skb);
+ ieee80211_tx_frags(local, &sdata->vif, &sta->sta, &tx.skbs, false);
+ }
=20
- __skb_queue_tail(&tx.skbs, skb);
- ieee80211_tx_frags(local, &sdata->vif, &sta->sta, &tx.skbs, false);
return true;
}
=20
--=20
2.9.3
^ permalink raw reply related
* Re: [PATCH] drivers: staging: rtl823au: hal: Remove pointless test
From: Greg KH @ 2016-09-01 15:54 UTC (permalink / raw)
To: Matthias Beyer
Cc: devel, linux-kernel, linux-wireless, shivanib134,
ksenija.stanojevic, Jes.Sorensen, meleodr, bhaktipriya96,
bhumirks, Larry.Finger
In-Reply-To: <20160823194417.30531-1-mail@beyermatthias.de>
On Tue, Aug 23, 2016 at 09:44:16PM +0200, Matthias Beyer wrote:
> As reported by David Binderman, this test is useless as of
>
> if (a < 3) {
> /* ... */
> } else if (a >= 3) {
> /* ... */
> }
>
> so this patch removes the second check.
>
> Matthias Beyer (1):
> drivers: staging: rtl8723au: hal: Remove pointless test
>
> drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
There is no patch here :(
^ permalink raw reply
* Re: [PATCH] drivers: staging: rtl823au: hal: Remove pointless test
From: Greg KH @ 2016-09-01 15:54 UTC (permalink / raw)
To: Matthias Beyer
Cc: devel, linux-kernel, linux-wireless, shivanib134,
ksenija.stanojevic, Jes.Sorensen, meleodr, bhaktipriya96,
bhumirks, Larry.Finger
In-Reply-To: <20160831193256.GA20648@lucy>
On Wed, Aug 31, 2016 at 09:32:56PM +0200, Matthias Beyer wrote:
> Pinging here as nobody responded yet.
>
> Maybe this was overlooked.
Nope, it was only a week, staging patches are at the bottom of my queue,
please give me time to get to them, I process them usually ever few
weeks...
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH 1/6] rtl8723au: remove declaration of unimplemented functions
From: Greg Kroah-Hartman @ 2016-09-01 15:42 UTC (permalink / raw)
To: Luca Ceresoli
Cc: devel, Jes Sorensen, linux-wireless, linux-kernel, Larry Finger
In-Reply-To: <1472301649-18694-1-git-send-email-luca@lucaceresoli.net>
On Sat, Aug 27, 2016 at 02:40:44PM +0200, Luca Ceresoli wrote:
> Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net>
> Cc: Larry Finger <Larry.Finger@lwfinger.net>
> Cc: Jes Sorensen <Jes.Sorensen@redhat.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: linux-wireless@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
> drivers/staging/rtl8723au/include/recv_osdep.h | 3 ---
> 1 file changed, 3 deletions(-)
I can't take patches without any changelog text, sorry. Please fix that
up for all 6 of these patches and resend.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH] mwifiex: handle edmac vendor command
From: Kalle Valo @ 2016-09-01 14:53 UTC (permalink / raw)
To: Amitkumar Karwar; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <e2b7d7d9aef1488a97eb7ec44b4c46af@SC-EXCH04.marvell.com>
Amitkumar Karwar <akarwar@marvell.com> writes:
>> From: Kalle Valo [mailto:kvalo@codeaurora.org]
>> Sent: Tuesday, May 24, 2016 1:53 AM
>> To: Amitkumar Karwar
>> Cc: linux-wireless@vger.kernel.org
>> Subject: Re: [PATCH] mwifiex: handle edmac vendor command
>>
>> Amitkumar Karwar <akarwar@marvell.com> writes:
>>
>> > Hi Kalle,
>> >
>> >> From: Amitkumar Karwar [mailto:akarwar@marvell.com]
>> >> Sent: Friday, April 29, 2016 9:28 PM
>> >> To: linux-wireless@vger.kernel.org
>> >> Cc: Jeff CF Chen; Amitkumar Karwar
>> >> Subject: [PATCH] mwifiex: handle edmac vendor command
>> >>
>> >> From: chunfan chen <jeffc@marvell.com>
>> >>
>> >> Userspace can configure edmac values through a custom vendor command.
>> >> They will be used by hardware for adaptivity.
>> >>
>> >> Signed-off-by: chunfan chen <jeffc@marvell.com>
>> >> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
>>
>> [deleted over 200 lines of unnecessary quotes]
>>
>> > This patch seems to have deferred. We basically want a way to download
>> > a vendor specific configuration to our firmware. Do you have any
>> > suggestions on how can achieve this in better way?
>> >
>> > I can see below iw command suits our requirement.
>> >
>> > iw dev <devname> vendor send <oui> <subcmd> <filename|-|hex data>
>> >
>> > Please guide.
>>
>> It was deferred because use of the nl80211 vendor interface (which I
>> don't think belong to upstream drivers). I'll take a look at this patch
>> in detail after the merge window.
>>
>
> Did you get a chance to check this patch?
> Please let me know if you have any suggestions.
Sorry for the delay. I have been thinking about vendor commands quite a
lot and I don't think they belong to upstream drivers. For regular use
cases (used by normal users) we have nl80211, for developer and testing
purposes we have debugfs and for manufacturing type of tests we have
nl80211 testmode interface. The focus of development should be adding
new functionality to nl80211 (and other generic interfaces), not to
driver specific vendor commands.
I know brcm80211 and ti's wlcore have few vendor commands but I'm hoping
to remove them sometime soon.
Thoughts?
--
Kalle Valo
^ permalink raw reply
* [PATCH v3 1/2] wcn36xx: Transition driver to SMD client
From: Bjorn Andersson @ 2016-09-01 14:51 UTC (permalink / raw)
To: Eugene Krasnikov, Kalle Valo
Cc: wcn36xx, linux-wireless, netdev, linux-kernel, linux-arm-msm
The wcn36xx wifi driver follows the life cycle of the WLAN_CTRL SMD
channel, as such it should be a SMD client. This patch makes this
transition, now that we have the necessary frameworks available.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
Changes since v2:
- Correct the call to the new ieee80211_scan_completed()
drivers/net/wireless/ath/wcn36xx/Kconfig | 2 +-
drivers/net/wireless/ath/wcn36xx/dxe.c | 16 +++---
drivers/net/wireless/ath/wcn36xx/main.c | 79 ++++++++++++++++++++----------
drivers/net/wireless/ath/wcn36xx/smd.c | 29 +++++------
drivers/net/wireless/ath/wcn36xx/smd.h | 5 ++
drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 21 +++-----
6 files changed, 86 insertions(+), 66 deletions(-)
diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig b/drivers/net/wireless/ath/wcn36xx/Kconfig
index 591ebaea8265..394fe5b77c90 100644
--- a/drivers/net/wireless/ath/wcn36xx/Kconfig
+++ b/drivers/net/wireless/ath/wcn36xx/Kconfig
@@ -1,6 +1,6 @@
config WCN36XX
tristate "Qualcomm Atheros WCN3660/3680 support"
- depends on MAC80211 && HAS_DMA
+ depends on MAC80211 && HAS_DMA && QCOM_SMD
---help---
This module adds support for wireless adapters based on
Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets.
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 231fd022f0f5..87dfdaf9044c 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -23,6 +23,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/interrupt.h>
+#include <linux/soc/qcom/smem_state.h>
#include "wcn36xx.h"
#include "txrx.h"
@@ -151,9 +152,12 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
goto out_err;
/* Initialize SMSM state Clear TX Enable RING EMPTY STATE */
- ret = wcn->ctrl_ops->smsm_change_state(
- WCN36XX_SMSM_WLAN_TX_ENABLE,
- WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+ ret = qcom_smem_state_update_bits(wcn->tx_enable_state,
+ WCN36XX_SMSM_WLAN_TX_ENABLE |
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY,
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+ if (ret)
+ goto out_err;
return 0;
@@ -678,9 +682,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
* notify chip about new frame through SMSM bus.
*/
if (is_low && vif_priv->pw_state == WCN36XX_BMPS) {
- wcn->ctrl_ops->smsm_change_state(
- 0,
- WCN36XX_SMSM_WLAN_TX_ENABLE);
+ qcom_smem_state_update_bits(wcn->tx_rings_empty_state,
+ WCN36XX_SMSM_WLAN_TX_ENABLE,
+ WCN36XX_SMSM_WLAN_TX_ENABLE);
} else {
/* indicate End Of Packet and generate interrupt on descriptor
* done.
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index e1d59da2ad20..3c2522b07c90 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -21,6 +21,10 @@
#include <linux/platform_device.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/soc/qcom/smd.h>
+#include <linux/soc/qcom/smem_state.h>
+#include <linux/soc/qcom/wcnss_ctrl.h>
#include "wcn36xx.h"
unsigned int wcn36xx_dbg_mask;
@@ -1058,8 +1062,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
int ret;
/* Set TX IRQ */
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
- "wcnss_wlantx_irq");
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
if (!res) {
wcn36xx_err("failed to get tx_irq\n");
return -ENOENT;
@@ -1067,14 +1070,29 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
wcn->tx_irq = res->start;
/* Set RX IRQ */
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
- "wcnss_wlanrx_irq");
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
if (!res) {
wcn36xx_err("failed to get rx_irq\n");
return -ENOENT;
}
wcn->rx_irq = res->start;
+ /* Acquire SMSM tx enable handle */
+ wcn->tx_enable_state = qcom_smem_state_get(&pdev->dev,
+ "tx-enable", &wcn->tx_enable_state_bit);
+ if (IS_ERR(wcn->tx_enable_state)) {
+ wcn36xx_err("failed to get tx-enable state\n");
+ return PTR_ERR(wcn->tx_enable_state);
+ }
+
+ /* Acquire SMSM tx rings empty handle */
+ wcn->tx_rings_empty_state = qcom_smem_state_get(&pdev->dev,
+ "tx-rings-empty", &wcn->tx_rings_empty_state_bit);
+ if (IS_ERR(wcn->tx_rings_empty_state)) {
+ wcn36xx_err("failed to get tx-rings-empty state\n");
+ return PTR_ERR(wcn->tx_rings_empty_state);
+ }
+
mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0);
if (!mmio_node) {
wcn36xx_err("failed to acquire qcom,mmio reference\n");
@@ -1115,11 +1133,14 @@ static int wcn36xx_probe(struct platform_device *pdev)
{
struct ieee80211_hw *hw;
struct wcn36xx *wcn;
+ void *wcnss;
int ret;
- u8 addr[ETH_ALEN];
+ const u8 *addr;
wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
+ wcnss = dev_get_drvdata(pdev->dev.parent);
+
hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
if (!hw) {
wcn36xx_err("failed to alloc hw\n");
@@ -1130,11 +1151,23 @@ static int wcn36xx_probe(struct platform_device *pdev)
wcn = hw->priv;
wcn->hw = hw;
wcn->dev = &pdev->dev;
- wcn->ctrl_ops = pdev->dev.platform_data;
-
mutex_init(&wcn->hal_mutex);
- if (!wcn->ctrl_ops->get_hw_mac(addr)) {
+ wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process);
+ if (IS_ERR(wcn->smd_channel)) {
+ wcn36xx_err("failed to open WLAN_CTRL channel\n");
+ ret = PTR_ERR(wcn->smd_channel);
+ goto out_wq;
+ }
+
+ qcom_smd_set_drvdata(wcn->smd_channel, hw);
+
+ addr = of_get_property(pdev->dev.of_node, "local-mac-address", &ret);
+ if (addr && ret != ETH_ALEN) {
+ wcn36xx_err("invalid local-mac-address\n");
+ ret = -EINVAL;
+ goto out_wq;
+ } else if (addr) {
wcn36xx_info("mac address: %pM\n", addr);
SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
}
@@ -1158,6 +1191,7 @@ out_wq:
out_err:
return ret;
}
+
static int wcn36xx_remove(struct platform_device *pdev)
{
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
@@ -1168,42 +1202,33 @@ static int wcn36xx_remove(struct platform_device *pdev)
mutex_destroy(&wcn->hal_mutex);
ieee80211_unregister_hw(hw);
+
+ qcom_smem_state_put(wcn->tx_enable_state);
+ qcom_smem_state_put(wcn->tx_rings_empty_state);
+
iounmap(wcn->dxe_base);
iounmap(wcn->ccu_base);
ieee80211_free_hw(hw);
return 0;
}
-static const struct platform_device_id wcn36xx_platform_id_table[] = {
- {
- .name = "wcn36xx",
- .driver_data = 0
- },
+
+static const struct of_device_id wcn36xx_of_match[] = {
+ { .compatible = "qcom,wcnss-wlan" },
{}
};
-MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table);
+MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
static struct platform_driver wcn36xx_driver = {
.probe = wcn36xx_probe,
.remove = wcn36xx_remove,
.driver = {
.name = "wcn36xx",
+ .of_match_table = wcn36xx_of_match,
},
- .id_table = wcn36xx_platform_id_table,
};
-static int __init wcn36xx_init(void)
-{
- platform_driver_register(&wcn36xx_driver);
- return 0;
-}
-module_init(wcn36xx_init);
-
-static void __exit wcn36xx_exit(void)
-{
- platform_driver_unregister(&wcn36xx_driver);
-}
-module_exit(wcn36xx_exit);
+module_platform_driver(wcn36xx_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index a443992320f2..d9ff2e2a8118 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -19,6 +19,7 @@
#include <linux/etherdevice.h>
#include <linux/firmware.h>
#include <linux/bitops.h>
+#include <linux/soc/qcom/smd.h>
#include "smd.h"
struct wcn36xx_cfg_val {
@@ -253,7 +254,7 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
init_completion(&wcn->hal_rsp_compl);
start = jiffies;
- ret = wcn->ctrl_ops->tx(wcn->hal_buf, len);
+ ret = qcom_smd_send(wcn->smd_channel, wcn->hal_buf, len);
if (ret) {
wcn36xx_err("HAL TX failed\n");
goto out;
@@ -2180,9 +2181,12 @@ out:
return ret;
}
-static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
+int wcn36xx_smd_rsp_process(struct qcom_smd_channel *channel,
+ const void *buf, size_t len)
{
struct wcn36xx_hal_msg_header *msg_header = buf;
+ struct ieee80211_hw *hw = qcom_smd_get_drvdata(channel);
+ struct wcn36xx *wcn = hw->priv;
struct wcn36xx_hal_ind_msg *msg_ind;
wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
@@ -2233,15 +2237,11 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
case WCN36XX_HAL_OTA_TX_COMPL_IND:
case WCN36XX_HAL_MISSED_BEACON_IND:
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
- msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_KERNEL);
+ msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC);
if (!msg_ind) {
- /*
- * FIXME: Do something smarter then just
- * printing an error.
- */
wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
msg_header->msg_type);
- break;
+ return -ENOMEM;
}
msg_ind->msg_len = len;
@@ -2257,6 +2257,8 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
wcn36xx_err("SMD_EVENT (%d) not supported\n",
msg_header->msg_type);
}
+
+ return 0;
}
static void wcn36xx_ind_smd_work(struct work_struct *work)
{
@@ -2315,22 +2317,13 @@ int wcn36xx_smd_open(struct wcn36xx *wcn)
INIT_LIST_HEAD(&wcn->hal_ind_queue);
spin_lock_init(&wcn->hal_ind_lock);
- ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
- if (ret) {
- wcn36xx_err("failed to open control channel\n");
- goto free_wq;
- }
-
- return ret;
+ return 0;
-free_wq:
- destroy_workqueue(wcn->hal_ind_wq);
out:
return ret;
}
void wcn36xx_smd_close(struct wcn36xx *wcn)
{
- wcn->ctrl_ops->close();
destroy_workqueue(wcn->hal_ind_wq);
}
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
index df80cbbd9d1b..40d829563c2b 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -51,6 +51,7 @@ struct wcn36xx_hal_ind_msg {
};
struct wcn36xx;
+struct qcom_smd_channel;
int wcn36xx_smd_open(struct wcn36xx *wcn);
void wcn36xx_smd_close(struct wcn36xx *wcn);
@@ -127,6 +128,10 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index);
int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index);
int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value);
+
+int wcn36xx_smd_rsp_process(struct qcom_smd_channel *channel,
+ const void *buf, size_t len);
+
int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
struct ieee80211_vif *vif,
struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp);
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 22242d18e1fe..68cc06cf9bc0 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -103,19 +103,6 @@ struct nv_data {
u8 table;
};
-/* Interface for platform control path
- *
- * @open: hook must be called when wcn36xx wants to open control channel.
- * @tx: sends a buffer.
- */
-struct wcn36xx_platform_ctrl_ops {
- int (*open)(void *drv_priv, void *rsp_cb);
- void (*close)(void);
- int (*tx)(char *buf, size_t len);
- int (*get_hw_mac)(u8 *addr);
- int (*smsm_change_state)(u32 clear_mask, u32 set_mask);
-};
-
/**
* struct wcn36xx_vif - holds VIF related fields
*
@@ -205,7 +192,13 @@ struct wcn36xx {
void __iomem *ccu_base;
void __iomem *dxe_base;
- struct wcn36xx_platform_ctrl_ops *ctrl_ops;
+ struct qcom_smd_channel *smd_channel;
+
+ struct qcom_smem_state *tx_enable_state;
+ unsigned tx_enable_state_bit;
+ struct qcom_smem_state *tx_rings_empty_state;
+ unsigned tx_rings_empty_state_bit;
+
/*
* smd_buf must be protected with smd_mutex to garantee
* that all messages are sent one after another
--
2.5.0
^ permalink raw reply related
* [PATCH v3 2/2] wcn36xx: Implement firmware assisted scan
From: Bjorn Andersson @ 2016-09-01 14:51 UTC (permalink / raw)
To: Eugene Krasnikov, Kalle Valo
Cc: wcn36xx, linux-wireless, netdev, linux-kernel, linux-arm-msm
In-Reply-To: <1472741468-24762-1-git-send-email-bjorn.andersson@linaro.org>
Using the software based channel scan mechanism from mac80211 keeps us
offline for 10-15 second, we should instead issue a start_scan/end_scan
on each channel reducing this time.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
Changes since v2:
- None
drivers/net/wireless/ath/wcn36xx/main.c | 64 +++++++++++++++++++++++++-----
drivers/net/wireless/ath/wcn36xx/smd.c | 8 ++--
drivers/net/wireless/ath/wcn36xx/smd.h | 4 +-
drivers/net/wireless/ath/wcn36xx/txrx.c | 19 ++++++---
drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 9 +++++
5 files changed, 81 insertions(+), 23 deletions(-)
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 3c2522b07c90..96a9584edcbb 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -568,23 +568,59 @@ out:
return ret;
}
-static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void wcn36xx_hw_scan_worker(struct work_struct *work)
{
- struct wcn36xx *wcn = hw->priv;
+ struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work);
+ struct cfg80211_scan_request *req = wcn->scan_req;
+ u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX];
+ struct cfg80211_scan_info scan_info = {};
+ int i;
+
+ wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", req->n_channels);
+
+ for (i = 0; i < req->n_channels; i++)
+ channels[i] = req->channels[i]->hw_value;
+
+ wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels);
wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
- wcn36xx_smd_start_scan(wcn);
+ for (i = 0; i < req->n_channels; i++) {
+ wcn->scan_freq = req->channels[i]->center_freq;
+ wcn->scan_band = req->channels[i]->band;
+
+ wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value);
+ msleep(30);
+ wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value);
+
+ wcn->scan_freq = 0;
+ }
+ wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+
+ scan_info.aborted = false;
+ ieee80211_scan_completed(wcn->hw, &scan_info);
+
+ mutex_lock(&wcn->scan_lock);
+ wcn->scan_req = NULL;
+ mutex_unlock(&wcn->scan_lock);
}
-static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *hw_req)
{
struct wcn36xx *wcn = hw->priv;
- wcn36xx_smd_end_scan(wcn);
- wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+ mutex_lock(&wcn->scan_lock);
+ if (wcn->scan_req) {
+ mutex_unlock(&wcn->scan_lock);
+ return -EBUSY;
+ }
+ wcn->scan_req = &hw_req->req;
+ mutex_unlock(&wcn->scan_lock);
+
+ schedule_work(&wcn->scan_work);
+
+ return 0;
}
static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
@@ -997,8 +1033,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
.configure_filter = wcn36xx_configure_filter,
.tx = wcn36xx_tx,
.set_key = wcn36xx_set_key,
- .sw_scan_start = wcn36xx_sw_scan_start,
- .sw_scan_complete = wcn36xx_sw_scan_complete,
+ .hw_scan = wcn36xx_hw_scan,
.bss_info_changed = wcn36xx_bss_info_changed,
.set_rts_threshold = wcn36xx_set_rts_threshold,
.sta_add = wcn36xx_sta_add,
@@ -1023,6 +1058,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
+ ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
@@ -1032,6 +1068,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz;
wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz;
+ wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
+ wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN;
+
wcn->hw->wiphy->cipher_suites = cipher_suites;
wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
@@ -1152,6 +1191,9 @@ static int wcn36xx_probe(struct platform_device *pdev)
wcn->hw = hw;
wcn->dev = &pdev->dev;
mutex_init(&wcn->hal_mutex);
+ mutex_init(&wcn->scan_lock);
+
+ INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker);
wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process);
if (IS_ERR(wcn->smd_channel)) {
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index d9ff2e2a8118..83d067876969 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -522,7 +522,7 @@ out:
return ret;
}
-int wcn36xx_smd_start_scan(struct wcn36xx *wcn)
+int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel)
{
struct wcn36xx_hal_start_scan_req_msg msg_body;
int ret = 0;
@@ -530,7 +530,7 @@ int wcn36xx_smd_start_scan(struct wcn36xx *wcn)
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
- msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
+ msg_body.scan_channel = scan_channel;
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
@@ -552,7 +552,7 @@ out:
return ret;
}
-int wcn36xx_smd_end_scan(struct wcn36xx *wcn)
+int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel)
{
struct wcn36xx_hal_end_scan_req_msg msg_body;
int ret = 0;
@@ -560,7 +560,7 @@ int wcn36xx_smd_end_scan(struct wcn36xx *wcn)
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
- msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
+ msg_body.scan_channel = scan_channel;
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
index 40d829563c2b..8892ccd67b14 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -60,8 +60,8 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn);
int wcn36xx_smd_start(struct wcn36xx *wcn);
int wcn36xx_smd_stop(struct wcn36xx *wcn);
int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode);
-int wcn36xx_smd_start_scan(struct wcn36xx *wcn);
-int wcn36xx_smd_end_scan(struct wcn36xx *wcn);
+int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel);
+int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel);
int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
enum wcn36xx_hal_sys_mode mode);
int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t channel_count);
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c
index 1f34c2e912d7..8c387a0a3c09 100644
--- a/drivers/net/wireless/ath/wcn36xx/txrx.c
+++ b/drivers/net/wireless/ath/wcn36xx/txrx.c
@@ -45,9 +45,20 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len);
skb_pull(skb, bd->pdu.mpdu_header_off);
+ hdr = (struct ieee80211_hdr *) skb->data;
+ fc = __le16_to_cpu(hdr->frame_control);
+ sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl));
+
+ /* When scanning associate beacons to this */
+ if (ieee80211_is_beacon(hdr->frame_control) && wcn->scan_freq) {
+ status.freq = wcn->scan_freq;
+ status.band = wcn->scan_band;
+ } else {
+ status.freq = WCN36XX_CENTER_FREQ(wcn);
+ status.band = WCN36XX_BAND(wcn);
+ }
+
status.mactime = 10;
- status.freq = WCN36XX_CENTER_FREQ(wcn);
- status.band = WCN36XX_BAND(wcn);
status.signal = -get_rssi0(bd);
status.antenna = 1;
status.rate_idx = 1;
@@ -61,10 +72,6 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
- hdr = (struct ieee80211_hdr *) skb->data;
- fc = __le16_to_cpu(hdr->frame_control);
- sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl));
-
if (ieee80211_is_beacon(hdr->frame_control)) {
wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n",
skb, skb->len, fc, sn);
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 68cc06cf9bc0..35a6590c3ee5 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -35,6 +35,9 @@
/* How many frames until we start a-mpdu TX session */
#define WCN36XX_AMPDU_START_THRESH 20
+#define WCN36XX_MAX_SCAN_SSIDS 9
+#define WCN36XX_MAX_SCAN_IE_LEN 500
+
extern unsigned int wcn36xx_dbg_mask;
enum wcn36xx_debug_mask {
@@ -212,6 +215,12 @@ struct wcn36xx {
spinlock_t hal_ind_lock;
struct list_head hal_ind_queue;
+ struct work_struct scan_work;
+ struct cfg80211_scan_request *scan_req;
+ int scan_freq;
+ int scan_band;
+ struct mutex scan_lock;
+
/* DXE channels */
struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */
struct wcn36xx_dxe_ch dxe_tx_h_ch; /* TX high */
--
2.5.0
^ permalink raw reply related
* Re: pull-request: iwlwifi-next 2016-08-30-2
From: Kalle Valo @ 2016-09-01 14:28 UTC (permalink / raw)
To: Luca Coelho; +Cc: linux-wireless, linuxwifi
In-Reply-To: <1472556999.27868.86.camel@coelho.fi>
Luca Coelho <luca@coelho.fi> writes:
> This is a v2 of my pull request with the potential below array bounds
> access, reported by kbuild bot, fixed.
>
>> Another pull request, this time intended for 4.9. I have a lot of
>> patches to send, but I'll send smaller batches this time. :)
>>
>> These patches contain mostly preparation for new HW, but also some
>> improvements in the dynamic queue allocation code and the
>> implementation to support GMAC.
>
> Let me know if everything's fine (or not). :)
>
> Luca.
>
>
> The following changes since commit 60747ef4d173c2747bf7f0377fb22846cb422195:
>
> Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net (2016-08-18 01:17:32 -0400)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git tags/iwlwifi-next-for-kalle-2016-08-30-2
Pulled, thanks.
--
Kalle Valo
^ permalink raw reply
* Re: pull-request: iwlwifi 2016-08-29
From: Kalle Valo @ 2016-09-01 14:13 UTC (permalink / raw)
To: Luca Coelho; +Cc: linux-wireless, linuxwifi
In-Reply-To: <1472499451.27868.31.camel@coelho.fi>
Luca Coelho <luca@coelho.fi> writes:
> Here are 4 patches intended for 4.8. They are all very small and low
> risk, but fix some actual issues. More details in the tag description.
>
> Let me know if everything's fine (or not). :)
>
> Luca.
>
>
> The following changes since commit bb87f02b7e4ccdb614a83cbf840524de81e9b321:
>
> Merge ath-current from ath.git (2016-08-29 21:39:04 +0300)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes.git tags/iwlwifi-for-kalle-2016-08-29
Pulled, thanks.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Toke Høiland-Jørgensen @ 2016-09-01 9:42 UTC (permalink / raw)
To: Johannes Berg; +Cc: make-wifi-fast, linux-wireless
In-Reply-To: <1472722020.9608.3.camel@sipsolutions.net>
Johannes Berg <johannes@sipsolutions.net> writes:
>> Yeah, was going to do that anyway. But since I'm touching the code
>> anyway, this might be an opportunity to avoid constructs like this:
>>=20
>> if (!invoke_tx_handlers(tx))
>> =C2=A0 /* continue sending the packet */
>>=20
>> Most other succeed/fail functions seem to be of type bool, so it
>> would help consistency as well. Unless there is some particular
>> reason why this function happens to be using 0 to indicate success?
>>=20
>
> It's just convention in the kernel, really.
>
> IMHO if a function has a bool return value it should be have a more
> expressive name that indicates better what's going on, like e.g.
>
> bool ieee80211_is_radar_required(...);
>
> but of course that's not always done.
Well, it's applied somewhat inconsistently across mac80211, it seems
(e.g. ieee80211_tx() and ieee80211_tx_prepare_skb() are bool, while
invoke_tx_handlers() and ieee80211_skb_resize() are int). But okay,
don't have that strong an opinion about the colour of this particular
bikeshed so I'll keep it the way it is ;)
-Toke
^ permalink raw reply
* Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Johannes Berg @ 2016-09-01 9:27 UTC (permalink / raw)
To: Toke Høiland-Jørgensen; +Cc: make-wifi-fast, linux-wireless
In-Reply-To: <8760qgugb0.fsf@toke.dk>
> Yeah, was going to do that anyway. But since I'm touching the code
> anyway, this might be an opportunity to avoid constructs like this:
>
> if (!invoke_tx_handlers(tx))
> /* continue sending the packet */
>
> Most other succeed/fail functions seem to be of type bool, so it
> would help consistency as well. Unless there is some particular
> reason why this function happens to be using 0 to indicate success?
>
It's just convention in the kernel, really.
IMHO if a function has a bool return value it should be have a more
expressive name that indicates better what's going on, like e.g.
bool ieee80211_is_radar_required(...);
but of course that's not always done.
johannes
^ permalink raw reply
* Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Toke Høiland-Jørgensen @ 2016-09-01 9:20 UTC (permalink / raw)
To: Johannes Berg; +Cc: make-wifi-fast, linux-wireless
In-Reply-To: <1472720848.9608.1.camel@sipsolutions.net>
Johannes Berg <johannes@sipsolutions.net> writes:
>> > They have three possible values ... :)
>>
>> Ah, no, not the handlers themselves. Meant the invoke_tx_handlers()
>> function (or all three of them after my patch; hence the plural). To
>> avoid the "0 means true" confusion you alluded to :)
>>
>
> Ah. Actually, even I got confused and thought the return value *was*
> the same as the handler.
>
> I think it doesn't matter to be tricky, gcc is probably going to (have
> to) generate exactly the same code like when you explicitly put an if
> statement in there, it seems?
Yeah, was going to do that anyway. But since I'm touching the code
anyway, this might be an opportunity to avoid constructs like this:
if (!invoke_tx_handlers(tx))
/* continue sending the packet */
Most other succeed/fail functions seem to be of type bool, so it would
help consistency as well. Unless there is some particular reason why
this function happens to be using 0 to indicate success?
-Toke
^ permalink raw reply
* Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Johannes Berg @ 2016-09-01 9:07 UTC (permalink / raw)
To: Toke Høiland-Jørgensen; +Cc: make-wifi-fast, linux-wireless
In-Reply-To: <8737lk816p.fsf@toke.dk>
> > They have three possible values ... :)
>
> Ah, no, not the handlers themselves. Meant the invoke_tx_handlers()
> function (or all three of them after my patch; hence the plural). To
> avoid the "0 means true" confusion you alluded to :)
>
Ah. Actually, even I got confused and thought the return value *was*
the same as the handler.
I think it doesn't matter to be tricky, gcc is probably going to (have
to) generate exactly the same code like when you explicitly put an if
statement in there, it seems?
johannes
^ permalink raw reply
* Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Toke Høiland-Jørgensen @ 2016-09-01 8:38 UTC (permalink / raw)
To: Johannes Berg; +Cc: make-wifi-fast, linux-wireless
In-Reply-To: <1472718860.4249.0.camel@sipsolutions.net>
Johannes Berg <johannes@sipsolutions.net> writes:
>> > > +static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
>> > > +{
>> > > + return invoke_tx_handlers_early(tx) ||
>> > > invoke_tx_handlers_late(tx);
>> > > +}
>> >
>> > Ugh, please, no, don't be tricky where it's not necessary. Now
>> > every
>> > person reading this has to first look up the return type, and then
>> > the
>> > return value, and make sure they understand that success is
>> > actually
>> > the value 0 ... that's way too much to ask.
>>
>> Noted. Any objections to turning these into bool return types?
>
> They have three possible values ... :)
Ah, no, not the handlers themselves. Meant the invoke_tx_handlers()
function (or all three of them after my patch; hence the plural). To
avoid the "0 means true" confusion you alluded to :)
-Toke
^ permalink raw reply
* Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Johannes Berg @ 2016-09-01 8:34 UTC (permalink / raw)
To: Toke Høiland-Jørgensen; +Cc: make-wifi-fast, linux-wireless
In-Reply-To: <87inug81vo.fsf@toke.dk>
> > > +static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
> > > +{
> > > + return invoke_tx_handlers_early(tx) ||
> > > invoke_tx_handlers_late(tx);
> > > +}
> >
> > Ugh, please, no, don't be tricky where it's not necessary. Now
> > every
> > person reading this has to first look up the return type, and then
> > the
> > return value, and make sure they understand that success is
> > actually
> > the value 0 ... that's way too much to ask.
>
> Noted. Any objections to turning these into bool return types?
They have three possible values ... :)
johannes
^ permalink raw reply
* Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Toke Høiland-Jørgensen @ 2016-09-01 8:23 UTC (permalink / raw)
To: Johannes Berg; +Cc: make-wifi-fast, linux-wireless
In-Reply-To: <1472677599.5470.13.camel@sipsolutions.net>
Johannes Berg <johannes@sipsolutions.net> writes:
>> +static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
>> +{
>> + return invoke_tx_handlers_early(tx) ||
>> invoke_tx_handlers_late(tx);
>> +}
>
> Ugh, please, no, don't be tricky where it's not necessary. Now every
> person reading this has to first look up the return type, and then the
> return value, and make sure they understand that success is actually
> the value 0 ... that's way too much to ask.
Noted. Any objections to turning these into bool return types?
I'll go through and fix your other comments and send a new version.
Thanks for the feedback :)
-Toke
^ permalink raw reply
* linux-4.8-rcX: ath9k traceback
From: Mimi Zohar @ 2016-08-31 22:24 UTC (permalink / raw)
To: QCA ath9k Development; +Cc: ath9k-devel, linux-wireless, Luis R. Rodriguez
Hi,
There weren't any problems on linux-4.7 kernels. I'm getting the
following traceback on linux-4.8-rc1/-rc4 kernels. Let me know if you
need any additional information.
[ 64.006529] WARNING: CPU: 3 PID: 94 at drivers/net/wireless/ath/ath9k/beacon.c:642 ath9k_beacon_config+0x12c/0x140 [ath9k]
[ 64.008714] Modules linked in: ip6t_rpfilter ip6t_REJECT nf_reject_ipv6 xt_conntrack ebtable_nat ebtable_broute bridge stp llc ebtable_filter ebtables ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle ip6table_security ip6table_raw ip6table_filter ip6_tables iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack iptable_mangle iptable_security iptable_raw bnep dm_crypt arc4 ath9k ath9k_common ath9k_hw ath mac80211 snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic intel_rapl coretemp kvm_intel snd_hda_intel snd_intel_sst_acpi snd_intel_sst_core kvm snd_soc_sst_mfld_platform snd_hda_codec snd_soc_core snd_hwdep cfg80211 ath3k snd_hda_core snd_compress btusb btrtl btbcm snd_soc_sst_match btintel bluetooth vfat irqbypass uvcvideo crct10dif_pclmul
[ 64.018692] crc32_pclmul fat snd_seq videobuf2_vmalloc iTCO_wdt videobuf2_memops crc32c_intel hid_sensor_rotation hid_rmi hid_sensor_magn_3d ghash_clmulni_intel iTCO_vendor_support videobuf2_v4l2 hid_sensor_als dcdbas intel_cstate dell_smm_hwmon hid_sensor_incl_3d hid_sensor_accel_3d hid_sensor_gyro_3d i2c_i801 hid_sensor_trigger i2c_smbus snd_seq_device pcspkr videobuf2_core mei_txe hid_sensor_iio_common shpchp lpc_ich mei videodev industrialio_triggered_buffer kfifo_buf snd_pcm industrialio joydev media rfkill_gpio snd_timer i2c_designware_platform i2c_designware_core rfkill snd dw_dmac dell_smo8800 wmi soundcore dw_dmac_core i915 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm hid_multitouch sdhci_acpi serio_raw sdhci mmc_core video i2c_hid hid_sensor_hub mfd_core
[ 64.035203] CPU: 3 PID: 94 Comm: kworker/u8:2 Not tainted 4.8.0-rc4+ #664
[ 64.038046] Hardware name: Dell Inc. Inspiron 11 - 3147/0TWP67, BIOS A09 11/13/2015
[ 64.040929] Workqueue: phy0 ieee80211_iface_work [mac80211]
[ 64.043783] 0000000000000286 0000000089a65213 ffff880173023608 ffffffff813b8cce
[ 64.046668] 0000000000000000 0000000000000000 ffff880173023648 ffffffff8109005b
[ 64.049536] 00000282a0869df7 ffff880171869580 0000000000000000 ffff8801787cc028
[ 64.052402] Call Trace:
[ 64.055257] [<ffffffff813b8cce>] dump_stack+0x63/0x85
[ 64.058133] [<ffffffff8109005b>] __warn+0xcb/0xf0
[ 64.061006] [<ffffffff8109018d>] warn_slowpath_null+0x1d/0x20
[ 64.063918] [<ffffffffa0866efc>] ath9k_beacon_config+0x12c/0x140 [ath9k]
[ 64.066867] [<ffffffffa086b346>] ath9k_calculate_summary_state+0x126/0x370 [ath9k]
[ 64.069836] [<ffffffffa086bda6>] ath9k_bss_info_changed+0x186/0x1a0 [ath9k]
[ 64.072840] [<ffffffffa0741d95>] ieee80211_bss_info_change_notify+0xb5/0x1d0 [mac80211]
[ 64.075867] [<ffffffffa07ac352>] ieee80211_assoc_success+0x68d/0x9bc [mac80211]
[ 64.078873] [<ffffffff8117ca7d>] ? irq_work_queue+0x6d/0x80
[ 64.081877] [<ffffffff810e71b4>] ? wake_up_klogd+0x34/0x40
[ 64.084860] [<ffffffff810e76f1>] ? console_unlock+0x531/0x560
[ 64.087822] [<ffffffff810e79db>] ? vprintk_emit+0x2bb/0x520
[ 64.090769] [<ffffffff810e7e19>] ? vprintk_default+0x29/0x40
thanks,
Mimi
^ permalink raw reply
* Re: [PATCH v4] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Johannes Berg @ 2016-08-31 21:06 UTC (permalink / raw)
To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless
In-Reply-To: <20160830131548.6014-1-toke@toke.dk>
On Tue, 2016-08-30 at 15:15 +0200, Toke Høiland-Jørgensen wrote:
> @@ -829,10 +844,16 @@ ieee80211_tx_h_sequence(struct
> ieee80211_tx_data *tx)
> */
> if (!ieee80211_is_data_qos(hdr->frame_control) ||
> is_multicast_ether_addr(hdr->addr1)) {
> - /* driver should assign sequence number */
> - info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
> - /* for pure STA mode without beacons, we can do it
> */
> - hdr->seq_ctrl = cpu_to_le16(tx->sdata-
> >sequence_number);
> + fragnum = 0;
> + seq = cpu_to_le16(tx->sdata->sequence_number);
> + skb_queue_walk(&tx->skbs, skb) {
> + info = IEEE80211_SKB_CB(skb);
> + hdr = (struct ieee80211_hdr *)skb->data;
> + /* driver should assign sequence number */
> + info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
> + /* for pure STA mode without beacons, we can
> do it */
> + hdr->seq_ctrl = seq | fragnum++;
I would very much prefer you kept fragnum assignment in the
fragmentation handler.
Also, you just broke this on big endian, please run sparse on your
patches if you don't see these things directly.
> + if (!fast_tx ||
> + !ieee80211_xmit_fast_finish(sta->sdata, sta,
> fast_tx, skb,
> + false)) {
> + /* fast xmit was started, but fails to
> finish */
> + ieee80211_free_txskb(hw, skb);
> + goto begin;
> + }
That obviously cannot happen, it can't fail to finish. See the comments
in xmit_fast() and the return values ...
> +static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
> +{
> + return invoke_tx_handlers_early(tx) ||
> invoke_tx_handlers_late(tx);
> +}
Ugh, please, no, don't be tricky where it's not necessary. Now every
person reading this has to first look up the return type, and then the
return value, and make sure they understand that success is actually
the value 0 ... that's way too much to ask.
> +ieee80211_tx_result
> +ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
> +{
> + struct sk_buff *skb;
> + ieee80211_tx_result r;
> +
> + skb_queue_walk(&tx->skbs, skb) {
> + r = ieee80211_tx_h_michael_mic_add_skb(tx, skb);
> + if (r != TX_CONTINUE)
> + return r;
> + }
> + return TX_CONTINUE;
> +}
You just broke TKIP completely again. Adding the MMIC and fragmentation
are not commutative operations.
johannes
^ permalink raw reply
* Re: [v4,2/2] mwifiex: add cfg80211 testmode support
From: Brian Norris @ 2016-08-31 19:40 UTC (permalink / raw)
To: Amitkumar Karwar
Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam, Xinming Hu
In-Reply-To: <1469525960-6643-2-git-send-email-akarwar@marvell.com>
On Tue, Jul 26, 2016 at 03:09:20PM +0530, Amitkumar Karwar wrote:
> From: Xinming Hu <huxm@marvell.com>
>
> This patch adds cfg80211 testmode support so that userspace tools can
> download necessary commands to firmware during manufacturing mode tests.
>
> Signed-off-by: Xinming <huxm@marvell.com>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> ---
> v4: Used cfg80211 testmode interface instead of wext in 2/2 patch.(Kalle Valo)
> v3: Add "select WIRELESS_EXT" in Kconfig to resolve kbuild test robot errors.
> WEXT_PRIV seems to have a dependency with WIRELESS_EXT.
> v2: 1) Sequence of these two patches are changed to resolve compilation
> error seen if only 1/2 is applied.
> 2) Add "select WEXT_PRIV" in Kconfig to resolve warnings reported by
> kbuild test robot.
> ---
> drivers/net/wireless/marvell/mwifiex/cfg80211.c | 83 +++++++++++++++++++++++++
> 1 file changed, 83 insertions(+)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> index 235fb39..86b31b1 100644
> --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> @@ -3919,6 +3919,88 @@ static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
> return ret;
> }
>
> +#ifdef CONFIG_NL80211_TESTMODE
> +
> +enum mwifiex_tm_attr {
> + __MWIFIEX_TM_ATTR_INVALID = 0,
> + MWIFIEX_TM_ATTR_CMD = 1,
> + MWIFIEX_TM_ATTR_DATA = 2,
> +
> + /* keep last */
> + __MWIFIEX_TM_ATTR_AFTER_LAST,
> + MWIFIEX_TM_ATTR_MAX = __MWIFIEX_TM_ATTR_AFTER_LAST - 1,
> +};
> +
> +static const struct nla_policy mwifiex_tm_policy[MWIFIEX_TM_ATTR_MAX + 1] = {
> + [MWIFIEX_TM_ATTR_CMD] = { .type = NLA_U32 },
> + [MWIFIEX_TM_ATTR_DATA] = { .type = NLA_BINARY,
> + .len = MWIFIEX_SIZE_OF_CMD_BUFFER },
> +};
> +
> +enum mwifiex_tm_cmd {
> + MWIFIEX_TM_CMD_HOSTCMD = 0,
> +};
> +
> +int mwifiex_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,
This function should be static, no?
Brian
> + void *data, int len)
> +{
> + struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
> + struct mwifiex_ds_misc_cmd *hostcmd;
> + struct nlattr *tb[MWIFIEX_TM_ATTR_MAX + 1];
> + struct mwifiex_adapter *adapter;
> + struct sk_buff *skb;
> + int err;
> +
> + if (!priv)
> + return -EINVAL;
> + adapter = priv->adapter;
> +
> + err = nla_parse(tb, MWIFIEX_TM_ATTR_MAX, data, len,
> + mwifiex_tm_policy);
> + if (err)
> + return err;
> +
> + if (!tb[MWIFIEX_TM_ATTR_CMD])
> + return -EINVAL;
> +
> + switch (nla_get_u32(tb[MWIFIEX_TM_ATTR_CMD])) {
> + case MWIFIEX_TM_CMD_HOSTCMD:
> + if (!tb[MWIFIEX_TM_ATTR_DATA])
> + return -EINVAL;
> +
> + hostcmd = kzalloc(sizeof(*hostcmd), GFP_KERNEL);
> + if (!hostcmd)
> + return -ENOMEM;
> +
> + hostcmd->len = nla_len(tb[MWIFIEX_TM_ATTR_DATA]);
> + memcpy(hostcmd->cmd, nla_data(tb[MWIFIEX_TM_ATTR_DATA]),
> + hostcmd->len);
> +
> + if (mwifiex_send_cmd(priv, 0, 0, 0, hostcmd, true)) {
> + dev_err(priv->adapter->dev, "Failed to process hostcmd\n");
> + return -EFAULT;
> + }
> +
> + /* process hostcmd response*/
> + skb = cfg80211_testmode_alloc_reply_skb(wiphy, hostcmd->len);
> + if (!skb)
> + return -ENOMEM;
> + err = nla_put(skb, MWIFIEX_TM_ATTR_DATA,
> + hostcmd->len, hostcmd->cmd);
> + if (err) {
> + kfree_skb(skb);
> + return -EMSGSIZE;
> + }
> +
> + err = cfg80211_testmode_reply(skb);
> + kfree(hostcmd);
> + return err;
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +#endif
> +
> static int
> mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
> struct net_device *dev,
> @@ -4031,6 +4113,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
> .tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch,
> .add_station = mwifiex_cfg80211_add_station,
> .change_station = mwifiex_cfg80211_change_station,
> + CFG80211_TESTMODE_CMD(mwifiex_tm_cmd)
> .get_channel = mwifiex_cfg80211_get_channel,
> .start_radar_detection = mwifiex_cfg80211_start_radar_detection,
> .channel_switch = mwifiex_cfg80211_channel_switch,
^ permalink raw reply
* Re: [v4,1/2] mwifiex: add manufacturing mode support
From: Brian Norris @ 2016-08-31 19:34 UTC (permalink / raw)
To: Amitkumar Karwar; +Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam
In-Reply-To: <1469525960-6643-1-git-send-email-akarwar@marvell.com>
Hi,
On Tue, Jul 26, 2016 at 03:09:19PM +0530, Amitkumar Karwar wrote:
> By default normal mode is chosen when driver is loaded. This
> patch adds a provision to choose manufacturing mode via module
> parameters.
>
> Below command loads driver in manufacturing mode
> insmod mwifiex.ko mfg_mode=1.
>
> Tested-by: chunfan chen <jeffc@marvell.com>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> ---
> v4: Removed mfg_firmware module parameter and hardcoded the firmware name
> in driver(Kalle Valo).
> ---
> drivers/net/wireless/marvell/mwifiex/cmdevt.c | 8 ++++++++
> drivers/net/wireless/marvell/mwifiex/init.c | 22 +++++++++++++++-------
> drivers/net/wireless/marvell/mwifiex/main.c | 25 +++++++++++++++++++++----
> drivers/net/wireless/marvell/mwifiex/main.h | 2 ++
> drivers/net/wireless/marvell/mwifiex/pcie.c | 2 +-
> drivers/net/wireless/marvell/mwifiex/sdio.c | 2 +-
> drivers/net/wireless/marvell/mwifiex/usb.c | 2 +-
> 7 files changed, 49 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> index d433aa0..636cfa0 100644
> --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> @@ -595,6 +595,14 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
> return -1;
> }
> }
> + /* We don't expect commands in manufacturing mode. They are cooked
> + * in application and ready to download buffer is passed to the driver
> + */
You have the alignment wrong here. Needs an extra space.
> + if (adapter->mfg_mode && cmd_no) {
> + dev_dbg(adapter->dev, "Ignoring commands in manufacturing mode\n");
> + return -1;
> + }
> +
>
> /* Get a new command node */
> cmd_node = mwifiex_get_cmd_node(adapter);
> diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
> index 1489c90..82839d9 100644
> --- a/drivers/net/wireless/marvell/mwifiex/init.c
> +++ b/drivers/net/wireless/marvell/mwifiex/init.c
> @@ -298,6 +298,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
> memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
> adapter->arp_filter_size = 0;
> adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
> + adapter->mfg_mode = mfg_mode;
> adapter->key_api_major_ver = 0;
> adapter->key_api_minor_ver = 0;
> eth_broadcast_addr(adapter->perm_addr);
> @@ -553,15 +554,22 @@ int mwifiex_init_fw(struct mwifiex_adapter *adapter)
> return -1;
> }
> }
> + if (adapter->mfg_mode) {
> + adapter->hw_status = MWIFIEX_HW_STATUS_READY;
> + ret = -EINPROGRESS;
> + } else {
> + for (i = 0; i < adapter->priv_num; i++) {
> + if (adapter->priv[i]) {
> + ret = mwifiex_sta_init_cmd(adapter->priv[i],
> + first_sta, true);
> + if (ret == -1)
> + return -1;
> +
> + first_sta = false;
> + }
> +
>
> - for (i = 0; i < adapter->priv_num; i++) {
> - if (adapter->priv[i]) {
> - ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta,
> - true);
> - if (ret == -1)
> - return -1;
>
> - first_sta = false;
> }
> }
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
> index db4925d..7fbf74b 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.c
> +++ b/drivers/net/wireless/marvell/mwifiex/main.c
> @@ -23,6 +23,7 @@
> #include "11n.h"
>
> #define VERSION "1.0"
> +#define MFG_FIRMWARE "mwifiex_mfg.bin"
>
> static unsigned int debug_mask = MWIFIEX_DEFAULT_DEBUG_MASK;
> module_param(debug_mask, uint, 0);
> @@ -36,6 +37,9 @@ static unsigned short driver_mode;
> module_param(driver_mode, ushort, 0);
> MODULE_PARM_DESC(driver_mode,
> "station=0x1(default), ap-sta=0x3, station-p2p=0x5, ap-sta-p2p=0x7");
> +bool mfg_mode;
Does this really need to be global? It's only actually used in init.c,
so could it help to move it to init.c and make it static?
> +module_param(mfg_mode, bool, 0);
> +MODULE_PARM_DESC(mfg_mode, "0:disable 1:enable (bool)");
That's not a very helpful description. Perhaps you could mention in a
word or two what this mode means?
Brian
>
> /*
> * This function registers the device and performs all the necessary
> @@ -559,10 +563,12 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
> goto done;
> }
> /* Wait for mwifiex_init to complete */
> - wait_event_interruptible(adapter->init_wait_q,
> - adapter->init_wait_q_woken);
> - if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
> - goto err_init_fw;
> + if (!adapter->mfg_mode) {
> + wait_event_interruptible(adapter->init_wait_q,
> + adapter->init_wait_q_woken);
> + if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
> + goto err_init_fw;
> + }
>
> priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
> if (mwifiex_register_cfg80211(adapter)) {
> @@ -666,6 +672,17 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
> {
> int ret;
>
> + /* Override default firmware with manufacturing one if
> + * manufacturing mode is enabled
> + */
> + if (mfg_mode) {
> + if (strlcpy(adapter->fw_name, MFG_FIRMWARE,
> + sizeof(adapter->fw_name)) >=
> + sizeof(adapter->fw_name)) {
> + pr_err("%s: fw_name too long!\n", __func__);
> + return -1;
> + }
> + }
> ret = request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name,
> adapter->dev, GFP_KERNEL, adapter,
> mwifiex_fw_dpc);
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
> index 5902600..fcc2af35 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.h
> +++ b/drivers/net/wireless/marvell/mwifiex/main.h
> @@ -58,6 +58,7 @@
> #include "sdio.h"
>
> extern const char driver_version[];
> +extern bool mfg_mode;
>
> struct mwifiex_adapter;
> struct mwifiex_private;
> @@ -990,6 +991,7 @@ struct mwifiex_adapter {
> u32 drv_info_size;
> bool scan_chan_gap_enabled;
> struct sk_buff_head rx_data_q;
> + bool mfg_mode;
> struct mwifiex_chan_stats *chan_stats;
> u32 num_in_chan_stats;
> int survey_idx;
> diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
> index 453ab6a..a6af85d 100644
> --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> @@ -225,7 +225,7 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
> if (!adapter || !adapter->priv_num)
> return;
>
> - if (user_rmmod) {
> + if (user_rmmod && !adapter->mfg_mode) {
> #ifdef CONFIG_PM_SLEEP
> if (adapter->is_suspended)
> mwifiex_pcie_resume(&pdev->dev);
> diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
> index d3e1561..6dba409 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sdio.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
> @@ -289,7 +289,7 @@ mwifiex_sdio_remove(struct sdio_func *func)
>
> mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num);
>
> - if (user_rmmod) {
> + if (user_rmmod && !adapter->mfg_mode) {
> if (adapter->is_suspended)
> mwifiex_sdio_resume(adapter->dev);
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
> index 0857575..ba616ec 100644
> --- a/drivers/net/wireless/marvell/mwifiex/usb.c
> +++ b/drivers/net/wireless/marvell/mwifiex/usb.c
> @@ -611,7 +611,7 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
> if (!adapter->priv_num)
> return;
>
> - if (user_rmmod) {
> + if (user_rmmod && !adapter->mfg_mode) {
> #ifdef CONFIG_PM
> if (adapter->is_suspended)
> mwifiex_usb_resume(intf);
^ 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