* Re: [PATCH v2 1/2] mwifiex: reset card->adapter during device unregister
From: Brian Norris @ 2016-10-05 16:30 UTC (permalink / raw)
To: Amitkumar Karwar
Cc: linux-wireless@vger.kernel.org, Cathy Luo, Nishant Sarmukadam,
rajatja@google.com, Xinming Hu
In-Reply-To: <8ec683dc72a746909157fca4dcbd10e8@SC-EXCH04.marvell.com>
Hi,
On Wed, Oct 05, 2016 at 02:04:53PM +0000, Amitkumar Karwar wrote:
> > From: Brian Norris [mailto:briannorris@chromium.org]
> > Sent: Wednesday, October 05, 2016 3:28 AM
> > To: Amitkumar Karwar
> > Cc: linux-wireless@vger.kernel.org; Cathy Luo; Nishant Sarmukadam;
> > rajatja@google.com; briannorris@google.com; Xinming Hu
> > Subject: Re: [PATCH v2 1/2] mwifiex: reset card->adapter during device
> > unregister
> >
> > Hi,
> >
> > On Tue, Oct 04, 2016 at 10:38:24PM +0530, Amitkumar Karwar wrote:
> > > --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > > +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > > @@ -3042,6 +3042,7 @@ static void mwifiex_unregister_dev(struct
> > mwifiex_adapter *adapter)
> > > pci_disable_msi(pdev);
> > > }
> > > }
> > > + card->adapter = NULL;
> >
> > I think you have a similar problem here as in patch 2; there is no
> > locking to protect fields in struct pcie_service_card or struct
> > sdio_mmc_card below. That problem kind of already exists, except that
> > you only write the value of card->adapter once at registration time, so
> > it's not actually unsafe. But now that you're introducing a second
> > write, you have a problem.
> >
> > Brian
> >
>
> We have a global "add_remove_card_sem" semaphore in our code for
> synchronizing initialization and teardown threads. Ideally "init +
> teardown/reboot" should not have a race issue with this logic
>
> Later there was a loophole introduced in this after using async
> firmware download API. During initialization, firmware downloads
> asynchronously in a separate thread where might have released the
> semaphore. I am working on a patch to fix this.
>
> So "card->adapter" doesn't need to have locking. Even if we have two
> write operations, those two threads can't run simultaneously due to
> above mentioned logic.
What about writes racing with reads? You have lots of unsynchronized
cases that read this, although most of them should be halted by now
(e.g., cmd processing). I was looking at suspend() in particular, which
I thought you were looking at in this patch series.
Brian
^ permalink raw reply
* Re: [-next] wlcore: sdio: drop kfree for memory allocated with devm_kzalloc
From: Kalle Valo @ 2016-10-05 16:05 UTC (permalink / raw)
To: Wei Yongjun; +Cc: Bruno Herrera, Tony Lindgren, Wei Yongjun, linux-wireless
In-Reply-To: <1475073516-7328-1-git-send-email-weiyj.lk@gmail.com>
Wei Yongjun <weiyj.lk@gmail.com> wrote:
> From: Wei Yongjun <weiyongjun1@huawei.com>
>
> It's not necessary to free memory allocated with devm_kzalloc
> and using kfree leads to a double free.
>
> Fixes: d776fc86b82f ("wlcore: sdio: Populate config firmware data")
> Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
> Acked-by: Tony Lindgren <tony@atomide.com>
Patch applied to wireless-drivers.git, thanks.
f38b7c254753 wlcore: sdio: drop kfree for memory allocated with devm_kzalloc
--
https://patchwork.kernel.org/patch/9353985/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH v4] ath9k: Switch to using mac80211 intermediate software queues.
From: Kalle Valo @ 2016-10-05 15:50 UTC (permalink / raw)
To: Toke Høiland-Jørgensen
Cc: linux-wireless, make-wifi-fast, ath9k-devel, Tim Shepard,
Felix Fietkau
In-Reply-To: <87k2dm6git.fsf@toke.dk>
Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk> writes:
> Kalle Valo <kvalo@codeaurora.org> writes:
>
>> Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk> writes:
>>
>> I understand your point, but I don't want to rush this to 4.9 and then
>> start getting lots of bug reports and eventually forced to revert it. If
>> we just found a new serious regression the chances are that there are
>> more lurking somewhere and this patch is just not ready yet.
>
> So, the changes to mac80211 that fixes the known regressions of this
> patch have gone in.
I guess you mean this commit:
bb42f2d13ffc mac80211: Move reorder-sensitive TX handlers to after TXQ dequ=
eue
(Just making sure that I have the same commit in my tree when I apply this)
> Any chance of seeing this merged during the current merge window? :)
I sent last new feature ("-next") patches for 4.9 last week, sorry. So
this has to wait for 4.10.
And I assume I need to take v5:
https://patchwork.kernel.org/patch/9311037/
--=20
Kalle Valo
^ permalink raw reply
* Re: [PATCHv4] mac80211: check A-MSDU inner frame source address on AP interfaces
From: Johannes Berg @ 2016-10-05 14:59 UTC (permalink / raw)
To: Michael Braun
Cc: linux-wireless, projekt-wlan, kvalo, akarwar, nishants,
Larry.Finger, Jes.Sorensen
In-Reply-To: <1475661751-26262-1-git-send-email-michael-dev@fami-braun.de>
On Wed, 2016-10-05 at 12:02 +0200, Michael Braun wrote:
> When using WPA security, the station and thus the required key is
> identified by its mac address when packets are received. So a
> station usually cannot spoof its source mac address.
>
> But when a station sends an A-MSDU frame, port control and crypto
> is done using the outer mac address, while the packets delivered
> and forwarded use the inner mac address.
> This might affect ARP/IP filtering on the AccessPoint.
>
> IEEE 802.11-2012 mandates that the outer source mac address should
> match the inner source address (section 8.3.2.2). For the destination
> mac address, matching is not required, as a wifi client may send all
> its traffic to the AP in order to have it forwarded.
>
> Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
So as you can see by my own version of this patch, I'm not super happy
with the way you did things here :)
Obviously, the commit log is now pretty much wrong here in your patch,
since you do much more than that now and don't focus on the SA only.
> @@ -1436,7 +1436,8 @@ static void
> iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm,
>
> memcpy(skb_put(pkt, pktsize), pktdata,
> pktsize);
>
> - if (ieee80211_data_to_8023(pkt, vif->addr,
> vif->type))
> + if (ieee80211_data_to_8023(pkt, NULL, vif-
> >addr,
> + vif->type))
> goto report;
I did something similar in the first patch I sent, but without changing
the drivers (by using a static inline and a new function name)
> void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct
> sk_buff_head *list,
> - const u8 *addr, enum nl80211_iftype
> iftype,
> + const u8 *addr,
> + enum nl80211_iftype iftype,
> const unsigned int extra_headroom,
> - bool has_80211_header);
> + const u8 *ta, const u8 *ra, bool
> is_4addr,
> + bool is_tdls_data);
Instead of adding 4 new arguments, (ta, ra, is_4addr, is_tdls_data), I
opted to just add two (check_da and check_sa) and make those NULL when
no checks are desired.
I *think* that works equivalently, but it'd be great if you could take
a look.
I had also removed the has_80211_header argument in patch 2, so we
don't clutter this thing as much.
> - if (is_multicast_ether_addr(hdr->addr1) &&
> - ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
> - rx->sdata->u.vlan.sta) ||
> - (rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
> - rx->sdata->u.mgd.use_4addr)))
> + is_4addr = ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN
> &&
> + rx->sdata->u.vlan.sta) ||
> + (rx->sdata->vif.type == NL80211_IFTYPE_STATION
> &&
> + rx->sdata->u.mgd.use_4addr));
> + if (is_multicast_ether_addr(hdr->addr1) && is_4addr)
> return RX_DROP_UNUSABLE;
This also conflicts with the earlier patch I sent to just always drop
when it's multicast.
> skb->dev = dev;
> __skb_queue_head_init(&frame_list);
>
> + if (ieee80211_data_to_8023(skb, ð_80211, dev->dev_addr,
> + rx->sdata->vif.type) < 0)
> + return RX_DROP_UNUSABLE;
> +
> + is_tdls_data = !ieee80211_has_tods(fc) &&
> !ieee80211_has_fromds(fc);
> ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
> rx->sdata->vif.type,
> - rx->local->hw.extra_tx_headroom,
> true);
> + rx->local->hw.extra_tx_headroom,
> + eth_80211.h_source,
> + eth_80211.h_dest, is_4addr,
> is_tdls_data);
Because you're passing eth_80211.h_* unconditionally, you need those
extra arguments, but I don't see why my approach wouldn't work.
> + /* limit inner src/dst checks depending on iftype */
> + switch (iftype) {
> + case NL80211_IFTYPE_AP:
> + case NL80211_IFTYPE_AP_VLAN:
> + if (is_4addr)
> + ta = NULL;
> + ra = NULL;
> + break;
> + case NL80211_IFTYPE_ADHOC:
> + break;
> + case NL80211_IFTYPE_STATION:
> + if (is_4addr || !is_tdls_data)
> + ta = NULL;
> + if (is_4addr)
> + ra = NULL;
> + break;
> + default:
> + ta = NULL;
> + ra = NULL;
> }
I have this in mac80211, which imho makes it easier.
I had half in mind to actually pass something like "expected frame
type", which wouldn't just be iftype, but be more like "AP, CLIENT,
TDLS, MESH, IBSS, ...", but it ultimately seemed too complex.
johannes
^ permalink raw reply
* [RFC 3/3] mac80211: validate DA/SA during A-MSDU decapsulation
From: Johannes Berg @ 2016-10-05 14:44 UTC (permalink / raw)
To: linux-wireless; +Cc: Michael Braun, Johannes Berg
In-Reply-To: <1475678690-29226-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
As pointed out by Michael Braun, we don't check inner L2 addresses
during A-MSDU decapsulation, leading to the possibility that, for
example, a station associated to an AP sends frames as though they
came from somewhere else.
Fix this problem by letting cfg80211 validate the addresses, as
indicated by passing in the ones that need to be validated.
Reported-by: Michael Braun <michael-dev@fami-braun.de>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/rx.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index cf53fe1a0aa2..a47bbc973f2d 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2299,6 +2299,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
struct sk_buff_head frame_list;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
struct ethhdr ethhdr;
+ const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
if (unlikely(!ieee80211_is_data(fc)))
return RX_CONTINUE;
@@ -2322,6 +2323,23 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
default:
return RX_DROP_UNUSABLE;
}
+ check_da = NULL;
+ check_sa = NULL;
+ } else switch (rx->sdata->vif.type) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ check_da = NULL;
+ break;
+ case NL80211_IFTYPE_STATION:
+ if (!rx->sta ||
+ !test_sta_flag(rx->sta, WLAN_STA_TDLS_PEER))
+ check_sa = NULL;
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ check_sa = NULL;
+ break;
+ default:
+ break;
}
if (is_multicast_ether_addr(hdr->addr1))
@@ -2338,7 +2356,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
rx->sdata->vif.type,
rx->local->hw.extra_tx_headroom,
- NULL, NULL);
+ check_da, check_sa);
while (!skb_queue_empty(&frame_list)) {
rx->skb = __skb_dequeue(&frame_list);
--
2.8.1
^ permalink raw reply related
* [RFC 1/3] cfg80211: let ieee80211_amsdu_to_8023s() take only header-less SKB
From: Johannes Berg @ 2016-10-05 14:44 UTC (permalink / raw)
To: linux-wireless; +Cc: Michael Braun, Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
There's only a single case where has_80211_header is passed as true,
which is in mac80211. Given that there's only simple code that needs
to be done before calling it, export that function from cfg80211
instead and let mac80211 call it itself.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
.../net/wireless/marvell/mwifiex/11n_rxreorder.c | 2 +-
drivers/staging/rtl8723au/core/rtw_recv.c | 2 +-
include/net/cfg80211.h | 31 +++++++++++++++-------
net/mac80211/rx.c | 8 +++++-
net/wireless/util.c | 24 ++++-------------
5 files changed, 36 insertions(+), 31 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
index 94480123efa3..e9f462e3730b 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -45,7 +45,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
- priv->wdev.iftype, 0, false);
+ priv->wdev.iftype, 0);
while (!skb_queue_empty(&list)) {
struct rx_packet_hdr *rx_hdr;
diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c
index 150dabc2a58d..e1873c906c42 100644
--- a/drivers/staging/rtl8723au/core/rtw_recv.c
+++ b/drivers/staging/rtl8723au/core/rtw_recv.c
@@ -1687,7 +1687,7 @@ int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe)
skb_pull(skb, prframe->attrib.hdrlen);
__skb_queue_head_init(&skb_list);
- ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0, false);
+ ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0);
while (!skb_queue_empty(&skb_list)) {
sub_skb = __skb_dequeue(&skb_list);
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fe78f02a242e..f372eadd1963 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4040,14 +4040,29 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
*/
/**
+ * ieee80211_data_to_8023_exthdr - convert an 802.11 data frame to 802.3
+ * @skb: the 802.11 data frame
+ * @ehdr: pointer to a &struct ethhdr that will get the header, instead
+ * of it being pushed into the SKB
+ * @addr: the device MAC address
+ * @iftype: the virtual interface type
+ * Return: 0 on success. Non-zero on error.
+ */
+int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+ const u8 *addr, enum nl80211_iftype iftype);
+
+/**
* ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
* @skb: the 802.11 data frame
* @addr: the device MAC address
* @iftype: the virtual interface type
* Return: 0 on success. Non-zero on error.
*/
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
- enum nl80211_iftype iftype);
+static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+ enum nl80211_iftype iftype)
+{
+ return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype);
+}
/**
* ieee80211_data_from_8023 - convert an 802.3 frame to 802.11
@@ -4065,22 +4080,20 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
/**
* ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame
*
- * Decode an IEEE 802.11n A-MSDU frame and convert it to a list of
- * 802.3 frames. The @list will be empty if the decode fails. The
- * @skb is consumed after the function returns.
+ * Decode an IEEE 802.11 A-MSDU and convert it to a list of 802.3 frames.
+ * The @list will be empty if the decode fails. The @skb must be fully
+ * header-less before being passed in here; it is freed in this function.
*
- * @skb: The input IEEE 802.11n A-MSDU frame.
+ * @skb: The input A-MSDU frame without any headers.
* @list: The output list of 802.3 frames. It must be allocated and
* initialized by by the caller.
* @addr: The device MAC address.
* @iftype: The device interface type.
* @extra_headroom: The hardware extra headroom for SKBs in the @list.
- * @has_80211_header: Set it true if SKB is with IEEE 802.11 header.
*/
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom,
- bool has_80211_header);
+ const unsigned int extra_headroom);
/**
* cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 3ac2f1cba317..de2d75fa5c51 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2298,6 +2298,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
__le16 fc = hdr->frame_control;
struct sk_buff_head frame_list;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+ struct ethhdr ethhdr;
if (unlikely(!ieee80211_is_data(fc)))
return RX_CONTINUE;
@@ -2329,9 +2330,14 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
skb->dev = dev;
__skb_queue_head_init(&frame_list);
+ if (ieee80211_data_to_8023_exthdr(skb, ðhdr,
+ rx->sdata->vif.addr,
+ rx->sdata->vif.type))
+ return RX_DROP_UNUSABLE;
+
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
rx->sdata->vif.type,
- rx->local->hw.extra_tx_headroom, true);
+ rx->local->hw.extra_tx_headroom);
while (!skb_queue_empty(&frame_list)) {
rx->skb = __skb_dequeue(&frame_list);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 8edce22d1b93..e36ede840b88 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -420,8 +420,8 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
}
EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
-static int __ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
- const u8 *addr, enum nl80211_iftype iftype)
+int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+ const u8 *addr, enum nl80211_iftype iftype)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct {
@@ -525,13 +525,7 @@ static int __ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
return 0;
}
-
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
- enum nl80211_iftype iftype)
-{
- return __ieee80211_data_to_8023(skb, NULL, addr, iftype);
-}
-EXPORT_SYMBOL(ieee80211_data_to_8023);
+EXPORT_SYMBOL(ieee80211_data_to_8023_exthdr);
int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
enum nl80211_iftype iftype,
@@ -745,25 +739,18 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom,
- bool has_80211_header)
+ const unsigned int extra_headroom)
{
unsigned int hlen = ALIGN(extra_headroom, 4);
struct sk_buff *frame = NULL;
u16 ethertype;
u8 *payload;
- int offset = 0, remaining, err;
+ int offset = 0, remaining;
struct ethhdr eth;
bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb);
bool reuse_skb = false;
bool last = false;
- if (has_80211_header) {
- err = __ieee80211_data_to_8023(skb, ð, addr, iftype);
- if (err)
- goto out;
- }
-
while (!last) {
unsigned int subframe_len;
int len;
@@ -819,7 +806,6 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
purge:
__skb_queue_purge(list);
- out:
dev_kfree_skb(skb);
}
EXPORT_SYMBOL(ieee80211_amsdu_to_8023s);
--
2.8.1
^ permalink raw reply related
* [RFC 2/3] cfg80211: add ability to check DA/SA in A-MSDU decapsulation
From: Johannes Berg @ 2016-10-05 14:44 UTC (permalink / raw)
To: linux-wireless; +Cc: Michael Braun, Johannes Berg
In-Reply-To: <1475678690-29226-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
We should not accept arbitrary DA/SA inside A-MSDUs, it could be used
to circumvent protections, like allowing a station to send frames and
make them seem to come from somewhere else.
Add the necessary infrastructure in cfg80211 to allow such checks, in
further patches we'll start using them.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c | 2 +-
drivers/staging/rtl8723au/core/rtw_recv.c | 2 +-
include/net/cfg80211.h | 5 ++++-
net/mac80211/rx.c | 3 ++-
net/wireless/util.c | 14 ++++++++++++--
5 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
index e9f462e3730b..274dd5a1574a 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -45,7 +45,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
- priv->wdev.iftype, 0);
+ priv->wdev.iftype, 0, NULL, NULL);
while (!skb_queue_empty(&list)) {
struct rx_packet_hdr *rx_hdr;
diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c
index e1873c906c42..d2a9ae2fe51a 100644
--- a/drivers/staging/rtl8723au/core/rtw_recv.c
+++ b/drivers/staging/rtl8723au/core/rtw_recv.c
@@ -1687,7 +1687,7 @@ int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe)
skb_pull(skb, prframe->attrib.hdrlen);
__skb_queue_head_init(&skb_list);
- ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0);
+ ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0, NULL, NULL);
while (!skb_queue_empty(&skb_list)) {
sub_skb = __skb_dequeue(&skb_list);
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f372eadd1963..7df600c463eb 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4090,10 +4090,13 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
* @addr: The device MAC address.
* @iftype: The device interface type.
* @extra_headroom: The hardware extra headroom for SKBs in the @list.
+ * @check_da: DA to check in the inner ethernet header, or NULL
+ * @check_sa: SA to check in the inner ethernet header, or NULL
*/
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom);
+ const unsigned int extra_headroom,
+ const u8 *check_da, const u8 *check_sa);
/**
* cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index de2d75fa5c51..cf53fe1a0aa2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2337,7 +2337,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
rx->sdata->vif.type,
- rx->local->hw.extra_tx_headroom);
+ rx->local->hw.extra_tx_headroom,
+ NULL, NULL);
while (!skb_queue_empty(&frame_list)) {
rx->skb = __skb_dequeue(&frame_list);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index e36ede840b88..5ea12afc7706 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -739,7 +739,8 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom)
+ const unsigned int extra_headroom,
+ const u8 *check_da, const u8 *check_sa)
{
unsigned int hlen = ALIGN(extra_headroom, 4);
struct sk_buff *frame = NULL;
@@ -767,8 +768,17 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
goto purge;
offset += sizeof(struct ethhdr);
- /* reuse skb for the last subframe */
last = remaining <= subframe_len + padding;
+
+ /* FIXME: should we really accept multicast DA? */
+ if ((check_da && !is_multicast_ether_addr(eth.h_dest) &&
+ !ether_addr_equal(check_da, eth.h_dest)) ||
+ (check_sa && !ether_addr_equal(check_sa, eth.h_source))) {
+ offset += len + padding;
+ continue;
+ }
+
+ /* reuse skb for the last subframe */
if (!skb_is_nonlinear(skb) && !reuse_frag && last) {
skb_pull(skb, offset);
frame = skb;
--
2.8.1
^ permalink raw reply related
* Issue with rt61-pci
From: Eddi De Pieri @ 2016-10-05 14:15 UTC (permalink / raw)
To: linux-wireless
Hi,
I have a router with onboard a rt2661 pci card and it use rt61pci driver.
With latest openwrt (it use compat wireless, so even the kernel isn't
the latest, the driver is near to linux-next) I get:
Lede-Trunk/Openwrt 15 and trunk:
by using the wifi card(AP mode) dmesg show:
[ 257.472000] ieee80211 phy1: rt61pci_txdone: Warning - TX status
report missed for entry 28
[ 257.480000] ieee80211 phy1: rt61pci_txdone: Warning - TX status
report missed for entry 29
[ 257.488000] ieee80211 phy1: rt61pci_txdone: Warning - TX status
report missed for entry 30
[ 257.496000] ieee80211 phy1: rt61pci_txdone: Warning - TX status
report missed for entry 31
[ 257.504000] ieee80211 phy1: rt61pci_txdone: Warning - TX status
report missed for entry 1
(don't remember which distribution i used to get this log... but all
suffer of the same issue)
and after few seconds of usage the wifi card stop working and it need
a reboot or rmmod rt61-pci/modprobe to make it work again for few
seconds
root@OpenWrt:/lib/firmware# lspci -v
00:01.0 Network controller: Ralink corp. RT2600 802.11 MIMO
Subsystem: Ralink corp. Device 2661
Flags: bus master, slow devsel, latency 64, IRQ 39
Memory at 30000000 (32-bit, non-prefetchable) [size=32K]
Memory at <unassigned> (32-bit, non-prefetchable) [size=2]
Memory at <unassigned> (32-bit, non-prefetchable) [size=2]
Memory at <unassigned> (32-bit, non-prefetchable) [size=2]
Memory at <unassigned> (32-bit, non-prefetchable) [size=2]
Memory at <unassigned> (32-bit, non-prefetchable) [size=2]
Expansion ROM at <unassigned> [disabled] [size=2]
Capabilities: [40] Power Management version 2
Kernel driver in use: rt61pci
lspci: Unable to load libkmod resources: error -12
root@OpenWrt:/proc/irq/39# cat /proc/interrupts
CPU0
0: 0 MIPS 0 smp_ipi0
1: 0 MIPS 1 smp_ipi1
7: 7906287 MIPS 7 timer
8: 0 bcm6345-periph-intc 0 bcm63xx_timer
10: 27 bcm6345-periph-intc 2 bcm63xx_uart
13: 1 bcm6345-periph-intc 5 ohci_hcd:usb2
14: 6 bcm6345-periph-intc 6 eth1
17: 0 bcm6345-periph-intc 9 phy_interrupt
18: 0 bcm6345-periph-intc 10 ehci_hcd:usb1
25: 168436 bcm6345-periph-intc 17 eth1
26: 96231 bcm6345-periph-intc 18 eth1
39: 492016 bcm6345-periph-intc 31 rt61pci
ERR: 0
root@OpenWrt:/proc/irq/39#
it seems that other people even on desktop systems get same error and
is not clear if it is solved on latest ubuntu as well there is already
a ticket opened on openwrt: https://dev.openwrt.org/ticket/18228
On Openwrt 12.09 work correctly.
Have you any idea about what could have introduced this regression?
ATTITUDE ADJUSTMENT (12.09, r36088)
root@OpenWrt:/# cat /proc/version
Linux version 3.3.8 (blogic@Debian-60-squeeze-64-minimal) (gcc version
4.6.3 20120201 (prerelease) (Linaro GCC 4.6-2012.02) ) #1 Sat Mar 23
18:09:20 UTC 2013
root@OpenWrt:/# cat /proc/interrupts
CPU0
2: 0 MIPS cascade_ip2
7: 479612 MIPS timer
8: 0 bcm63xx_ipic bcm63xx_timer
10: 18149 bcm63xx_ipic bcm63xx_uart
14: 19 bcm63xx_ipic eth1
17: 0 bcm63xx_ipic phy_interrupt
25: 247853 bcm63xx_ipic eth1
26: 117400 bcm63xx_ipic eth1
39: 552385 bcm63xx_ipic 0000:00:01.0
ERR: 0
root@OpenWrt:/# lspci -v
00:01.0 Network controller: Ralink corp. RT2600 802.11 MIMO
Subsystem: Ralink corp. Device 2661
Flags: bus master, slow devsel, latency 64, IRQ 39
Memory at 30000000 (32-bit, non-prefetchable) [size=32K]
Capabilities: [40] Power Management version 2
Kernel driver in use: rt61pci
01:1e.0 CardBus bridge: Broadcom Corporation Device 6358
Subsystem: Broadcom Corporation Device 6358
Flags: bus master, slow devsel, latency 0, IRQ 39
Bus: primary=01, secondary=02, subordinate=05, sec-latency=176
Memory window 0: 00000000-00000fff
Memory window 1: 00000001-00000fff
I/O window 0: 00000000-00000003
I/O window 1: 00000000-00000003
Please, can you give me some hint to troubleshoot this issue?
Regards
Eddi De Pieri
^ permalink raw reply
* RE: [PATCH v2 1/2] mwifiex: reset card->adapter during device unregister
From: Amitkumar Karwar @ 2016-10-05 14:04 UTC (permalink / raw)
To: Brian Norris
Cc: linux-wireless@vger.kernel.org, Cathy Luo, Nishant Sarmukadam,
rajatja@google.com, briannorris@google.com, Xinming Hu
In-Reply-To: <20161004215814.GB31652@localhost>
Hi Brian,
> From: Brian Norris [mailto:briannorris@chromium.org]
> Sent: Wednesday, October 05, 2016 3:28 AM
> To: Amitkumar Karwar
> Cc: linux-wireless@vger.kernel.org; Cathy Luo; Nishant Sarmukadam;
> rajatja@google.com; briannorris@google.com; Xinming Hu
> Subject: Re: [PATCH v2 1/2] mwifiex: reset card->adapter during device
> unregister
>
> Hi,
>
> On Tue, Oct 04, 2016 at 10:38:24PM +0530, Amitkumar Karwar wrote:
> > From: Xinming Hu <huxm@marvell.com>
> >
> > card->adapter gets initialized during device registration.
> > As it's not cleared, we may end up accessing invalid memory in some
> > corner cases. This patch fixes the problem.
> >
> > Signed-off-by: Xinming Hu <huxm@marvell.com>
> > Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> > ---
> > v2: Same as v1
> > ---
> > drivers/net/wireless/marvell/mwifiex/pcie.c | 1 +
> > drivers/net/wireless/marvell/mwifiex/sdio.c | 1 +
> > 2 files changed, 2 insertions(+)
> >
> > diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > index f1eeb73..ba9e068 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > @@ -3042,6 +3042,7 @@ static void mwifiex_unregister_dev(struct
> mwifiex_adapter *adapter)
> > pci_disable_msi(pdev);
> > }
> > }
> > + card->adapter = NULL;
>
> I think you have a similar problem here as in patch 2; there is no
> locking to protect fields in struct pcie_service_card or struct
> sdio_mmc_card below. That problem kind of already exists, except that
> you only write the value of card->adapter once at registration time, so
> it's not actually unsafe. But now that you're introducing a second
> write, you have a problem.
>
> Brian
>
We have a global "add_remove_card_sem" semaphore in our code for synchronizing initialization and teardown threads. Ideally "init + teardown/reboot" should not have a race issue with this logic
Later there was a loophole introduced in this after using async firmware download API. During initialization, firmware downloads asynchronously in a separate thread where might have released the semaphore. I am working on a patch to fix this.
So "card->adapter" doesn't need to have locking. Even if we have two write operations, those two threads can't run simultaneously due to above mentioned logic.
Regards,
Amitkumar
^ permalink raw reply
* Re: [PATCH v4] ath9k: Switch to using mac80211 intermediate software queues.
From: Toke Høiland-Jørgensen @ 2016-10-05 14:02 UTC (permalink / raw)
To: Kalle Valo
Cc: linux-wireless, make-wifi-fast, ath9k-devel, Tim Shepard,
Felix Fietkau
In-Reply-To: <877fb8ug0x.fsf@kamboji.qca.qualcomm.com>
Kalle Valo <kvalo@codeaurora.org> writes:
> Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk> writes:
>
>>>>> This is great work but due to the regressions I'm not sure if this
>>>>> will be ready for 4.9. To get more testing time I wonder if we should
>>>>> wait for 4.10? IMHO applying this in the end of the cycle is too risky
>>>>> and we should try to maximise the time linux-next by applying this
>>>>> just after -rc1 is released.
>>>>>
>>>>> Thoughts?
>>>>
>>>> Well, now that we understand what is causing the throughput regression=
s,
>>>> fixing them should be fairly straight forward (yeah, famous last words,
>>>> but still...). I already have a patch for the fast path and will go po=
ke
>>>> at the slow path next. It'll probably require another workaround or tw=
o,
>>>> so I guess it won't be the architecturally clean ideal solution; but it
>>>> would make it possible to have something that works for 4.9 and then
>>>> iterate for a cleaner design for 4.10.
>>>
>>> But if we try to rush this to 4.9 it won't be in linux-next for long. We
>>> are now in -rc3 and let's say that the patches are ready to apply in two
>>> weeks. That would leave us only two weeks of -next time before the merge
>>> window, which I think is not enough for a controversial patch like this
>>> one. There might be other bugs lurking which haven't been found yet.
>>
>> What, other hidden bugs? Unpossible! :)
>
> Yeah, right ;)
>
>> Would it be possible to merge the partial solution (which is ready now,
>> basically) and fix the slow path in a separate patch later?
>
> What do you mean with partial solution? You mean ath9k users would
> suffer from regressions until they are fixed? We can't do that.
>
>> (Just spit-balling here; I'm still fairly new to this process. But I am
>> concerned that we'll hit a catch-22 where we can't get wider testing
>> before it's "ready" and we can't prove that it's "ready" until we've had
>> wider testing...)
>
> I understand your point, but I don't want to rush this to 4.9 and then
> start getting lots of bug reports and eventually forced to revert it. If
> we just found a new serious regression the chances are that there are
> more lurking somewhere and this patch is just not ready yet.
So, the changes to mac80211 that fixes the known regressions of this
patch have gone in. Any chance of seeing this merged during the current
merge window? :)
-Toke
^ permalink raw reply
* Re: [PATCH] cfg80211: let ieee80211_amsdu_to_8023s() take only 802.3 header
From: Johannes Berg @ 2016-10-05 13:57 UTC (permalink / raw)
To: linux-wireless; +Cc: Michael Braun
In-Reply-To: <1475674414-23086-1-git-send-email-johannes@sipsolutions.net>
On Wed, 2016-10-05 at 15:33 +0200, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> There's only a single case where has_80211_header is passed as true,
> which is in mac80211. Given that it's only a very simple check that
> needs to be done before calling it (calling
> __ieee80211_data_to_8023()
> and checking its return value), simple move that into the caller in
> order to simplify this function. The only additional cost this adds
> is the extra skb_push(), so reduce that by using __skb_push() as we
> know there's enough space, having pulled just before.
Obviously this is broken ... we need to have a frame without the outer
802.3 header, not with it, passed into the function.
johannes
^ permalink raw reply
* [PATCH] cfg80211: let ieee80211_amsdu_to_8023s() take only 802.3 header
From: Johannes Berg @ 2016-10-05 13:33 UTC (permalink / raw)
To: linux-wireless; +Cc: Michael Braun, Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
There's only a single case where has_80211_header is passed as true,
which is in mac80211. Given that it's only a very simple check that
needs to be done before calling it (calling __ieee80211_data_to_8023()
and checking its return value), simple move that into the caller in
order to simplify this function. The only additional cost this adds
is the extra skb_push(), so reduce that by using __skb_push() as we
know there's enough space, having pulled just before.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
.../net/wireless/marvell/mwifiex/11n_rxreorder.c | 2 +-
drivers/staging/rtl8723au/core/rtw_recv.c | 2 +-
include/net/cfg80211.h | 7 +++---
net/mac80211/rx.c | 6 ++++-
net/wireless/util.c | 26 +++++-----------------
5 files changed, 15 insertions(+), 28 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
index 94480123efa3..e9f462e3730b 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -45,7 +45,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
- priv->wdev.iftype, 0, false);
+ priv->wdev.iftype, 0);
while (!skb_queue_empty(&list)) {
struct rx_packet_hdr *rx_hdr;
diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c
index 150dabc2a58d..e1873c906c42 100644
--- a/drivers/staging/rtl8723au/core/rtw_recv.c
+++ b/drivers/staging/rtl8723au/core/rtw_recv.c
@@ -1687,7 +1687,7 @@ int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe)
skb_pull(skb, prframe->attrib.hdrlen);
__skb_queue_head_init(&skb_list);
- ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0, false);
+ ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0);
while (!skb_queue_empty(&skb_list)) {
sub_skb = __skb_dequeue(&skb_list);
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fe78f02a242e..8d1a67fc2983 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4067,7 +4067,8 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
*
* Decode an IEEE 802.11n A-MSDU frame and convert it to a list of
* 802.3 frames. The @list will be empty if the decode fails. The
- * @skb is consumed after the function returns.
+ * @skb must already have been converted to 802.3 format. It is
+ * consumed after the function returns.
*
* @skb: The input IEEE 802.11n A-MSDU frame.
* @list: The output list of 802.3 frames. It must be allocated and
@@ -4075,12 +4076,10 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
* @addr: The device MAC address.
* @iftype: The device interface type.
* @extra_headroom: The hardware extra headroom for SKBs in the @list.
- * @has_80211_header: Set it true if SKB is with IEEE 802.11 header.
*/
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom,
- bool has_80211_header);
+ const unsigned int extra_headroom);
/**
* cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6175db385ba7..3a912e6c585f 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2323,9 +2323,13 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
skb->dev = dev;
__skb_queue_head_init(&frame_list);
+ if (ieee80211_data_to_8023(skb, rx->sdata->vif.addr,
+ rx->sdata->vif.type))
+ return RX_DROP_UNUSABLE;
+
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
rx->sdata->vif.type,
- rx->local->hw.extra_tx_headroom, true);
+ rx->local->hw.extra_tx_headroom);
while (!skb_queue_empty(&frame_list)) {
rx->skb = __skb_dequeue(&frame_list);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 8edce22d1b93..ed22d0336f1b 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -420,8 +420,8 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
}
EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
-static int __ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
- const u8 *addr, enum nl80211_iftype iftype)
+int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+ enum nl80211_iftype iftype)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct {
@@ -519,18 +519,10 @@ static int __ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
pskb_pull(skb, hdrlen);
- if (!ehdr)
- ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
- memcpy(ehdr, &tmp, sizeof(tmp));
+ memcpy(__skb_push(skb, sizeof(tmp)), &tmp, sizeof(tmp));
return 0;
}
-
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
- enum nl80211_iftype iftype)
-{
- return __ieee80211_data_to_8023(skb, NULL, addr, iftype);
-}
EXPORT_SYMBOL(ieee80211_data_to_8023);
int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
@@ -745,25 +737,18 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom,
- bool has_80211_header)
+ const unsigned int extra_headroom)
{
unsigned int hlen = ALIGN(extra_headroom, 4);
struct sk_buff *frame = NULL;
u16 ethertype;
u8 *payload;
- int offset = 0, remaining, err;
+ int offset = 0, remaining;
struct ethhdr eth;
bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb);
bool reuse_skb = false;
bool last = false;
- if (has_80211_header) {
- err = __ieee80211_data_to_8023(skb, ð, addr, iftype);
- if (err)
- goto out;
- }
-
while (!last) {
unsigned int subframe_len;
int len;
@@ -819,7 +804,6 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
purge:
__skb_queue_purge(list);
- out:
dev_kfree_skb(skb);
}
EXPORT_SYMBOL(ieee80211_amsdu_to_8023s);
--
2.8.1
^ permalink raw reply related
* [PATCH] [wl18xx] Fix memory leakage if kzalloc fails
From: Souptick Joarder @ 2016-10-05 13:09 UTC (permalink / raw)
To: linux-wireless
This patch is added to properly handle memory leak if kzalloc fails
in wl18xx_scan_send() and wl18xx_scan_sched_scan_config()
Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
Signed-off-by: Rameshwar Sahu <sahu.rameshwar73@gmail.com>
---
drivers/net/wireless/ti/wl18xx/scan.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/scan.c b/drivers/net/wireless/ti/wl18xx/scan.c
index 4e522154..aed22e1 100644
--- a/drivers/net/wireless/ti/wl18xx/scan.c
+++ b/drivers/net/wireless/ti/wl18xx/scan.c
@@ -41,14 +41,13 @@ static void wl18xx_adjust_channels(struct wl18xx_cmd_scan_params *cmd,
static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct cfg80211_scan_request *req)
{
- struct wl18xx_cmd_scan_params *cmd;
+ struct wl18xx_cmd_scan_params *cmd = NULL;
struct wlcore_scan_channels *cmd_channels = NULL;
int ret;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
- ret = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
/* scan on the dev role if the regular one is not started */
@@ -59,7 +58,7 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (WARN_ON(cmd->role_id == WL12XX_INVALID_ROLE_ID)) {
ret = -EINVAL;
- goto out;
+ goto err_cmd_free;
}
cmd->scan_type = SCAN_TYPE_SEARCH;
@@ -84,7 +83,7 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
cmd_channels = kzalloc(sizeof(*cmd_channels), GFP_KERNEL);
if (!cmd_channels) {
ret = -ENOMEM;
- goto out;
+ goto err_cmd_free;
}
wlcore_set_scan_chan_params(wl, cmd_channels, req->channels,
@@ -153,6 +152,7 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
out:
kfree(cmd_channels);
+err_cmd_free:
kfree(cmd);
return ret;
}
@@ -171,7 +171,7 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req,
struct ieee80211_scan_ies *ies)
{
- struct wl18xx_cmd_scan_params *cmd;
+ struct wl18xx_cmd_scan_params *cmd = NULL;
struct wlcore_scan_channels *cmd_channels = NULL;
struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
int ret;
@@ -185,15 +185,14 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
- ret = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
cmd->role_id = wlvif->role_id;
if (WARN_ON(cmd->role_id == WL12XX_INVALID_ROLE_ID)) {
ret = -EINVAL;
- goto out;
+ goto err_cmd_free;
}
cmd->scan_type = SCAN_TYPE_PERIODIC;
@@ -218,7 +217,7 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
cmd_channels = kzalloc(sizeof(*cmd_channels), GFP_KERNEL);
if (!cmd_channels) {
ret = -ENOMEM;
- goto out;
+ goto err_cmd_free;
}
/* configure channels */
@@ -296,6 +295,7 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
out:
kfree(cmd_channels);
+err_cmd_free:
kfree(cmd);
return ret;
}
--
1.9.1
^ permalink raw reply related
* Test mail please ignore
From: Souptick Joarder @ 2016-10-05 13:03 UTC (permalink / raw)
To: linux-wireless
^ permalink raw reply
* RE: [PATCH v2 2/2] mwifiex: check hw_status in suspend and resume handlers
From: Amitkumar Karwar @ 2016-10-05 12:26 UTC (permalink / raw)
To: Brian Norris
Cc: linux-wireless@vger.kernel.org, Cathy Luo, Nishant Sarmukadam,
rajatja@google.com, briannorris@google.com, Xinming Hu
In-Reply-To: <20161004210435.GA31652@localhost>
Hi Brian,
Thanks for your thorough review.
> From: Brian Norris [mailto:briannorris@chromium.org]
> Sent: Wednesday, October 05, 2016 2:35 AM
> To: Amitkumar Karwar
> Cc: linux-wireless@vger.kernel.org; Cathy Luo; Nishant Sarmukadam;
> rajatja@google.com; briannorris@google.com; Xinming Hu
> Subject: Re: [PATCH v2 2/2] mwifiex: check hw_status in suspend and
> resume handlers
>
> Hi,
>
> On Tue, Oct 04, 2016 at 10:38:25PM +0530, Amitkumar Karwar wrote:
> > From: Xinming Hu <huxm@marvell.com>
> >
> > We have observed a kernel crash when system immediately suspends after
> > booting. There is a race between suspend and driver initialization
> > paths.
> > This patch adds hw_status checks to fix the problem
> >
> > Signed-off-by: Xinming Hu <huxm@marvell.com>
> > Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> > ---
> > v2: Return failure in suspend/resume handler in this scenario.
> > ---
> > drivers/net/wireless/marvell/mwifiex/pcie.c | 10 ++++++----
> > 1 file changed, 6 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > index ba9e068..fa6bf85 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> > @@ -122,9 +122,10 @@ static int mwifiex_pcie_suspend(struct device
> > *dev)
> >
> > if (pdev) {
> > card = pci_get_drvdata(pdev);
> > - if (!card || !card->adapter) {
> > + if (!card || !card->adapter ||
> > + card->adapter->hw_status != MWIFIEX_HW_STATUS_READY) {
>
> Wait, is there no locking on the 'hw_status' field? That is inherently
> an unsafe race all on its own; you're not guaranteed that this will be
> read/written atomically. And you also aren't guaranteed that writes to
> this happen in the order they appear in the code -- in other words,
> reading this flag doesn't necessarily guarantee that initialization is
> actually complete (even if that's very likely to be true, given that
> it's probably just a single-instruction word-access, and any prior HW
> polling or interrupts likely have done some synchronization and can't be
> reordered).
> actually complete
Here is the brief info on how "hw_status" flag is updated.
1) It gets changed incrementally during initialization.
MWIFIEX_HW_STATUS_INITIALIZING -> MWIFIEX_HW_STATUS_INIT_DONE -> MWIFIEX_HW_STATUS_READY
2) Status will remain READY once driver+firmware is up and running.
3) Below is status during teardown
MWIFIEX_HW_STATUS_READY -> MWIFIEX_HW_STATUS_RESET -> MWIFIEX_HW_STATUS_CLOSING -> MWIFIEX_HW_STATUS_NOT_READY
As the events occur one after another, we don't expect a race and don't need locking here for the flag. Flag status MWIFIEX_HW_STATUS_READY guarantees that initialization is completed.
In worst case scenario, only first system suspend attempt issued immediately after system boot will be aborted with BUSY error. I think, that should be fine.
Let me know if you have any concerns.
>
> This is probably better than nothing, but it's not very good.
>
> > pr_err("Card or adapter structure is not valid\n");
> > - return 0;
> > + return -EBUSY;
>
> So the above cases all mean that the driver hasn't finished loading,
> right?
>
> !card => can't happen (PCIe probe() would have failed
> mwifiex_add_card()), but fine to check
NULL "card" or "card->adapter" pointers are expected in below cases
1) Driver initialization failed after downloading the firmware. Driver is performing cleanup in init failure path. Now system suspends.
2) Race of teardown + suspend
>
> !card->adapter => only happens after patch 1; i.e., when tearing down
> the device and detaching it from the driver
>
> card->adapter->hw_status != MWIFIEX_HW_STATUS_READY => FW is not loaded
> (i.e., in the process of starting or stopping FW?)
>
> I guess all of those cases make sense to be -EBUSY.
Yes. we can keep -EBUSY for all of the cases.
>
> > }
> > } else {
> > pr_err("PCIE device is not specified\n");
>
> I was going to complain about this branch (!pdev) returning 0, since
> that looked asymmetric. But this case will never happen, actually, since
> to_pci_dev() is just doing struct offset arithmetic on struct device,
> and struct device is never going to be NULL. It probably makes more
> sense to just remove this branch entirely, but that's for another patch.
Thanks for pointing this out. I will create separate patch for this.
>
> > @@ -166,9 +167,10 @@ static int mwifiex_pcie_resume(struct device
> > *dev)
> >
> > if (pdev) {
> > card = pci_get_drvdata(pdev);
> > - if (!card || !card->adapter) {
> > + if (!card || !card->adapter ||
> > + card->adapter->hw_status != MWIFIEX_HW_STATUS_READY) {
>
> Same complaint, except if you've screwed up here, you probably already
> screwed up in suspend().
>
> Brian
>
> > pr_err("Card or adapter structure is not valid\n");
> > - return 0;
> > + return -EBUSY;
> > }
> > } else {
> > pr_err("PCIE device is not specified\n");
> > --
> > 1.9.1
> >
Regards,
Amitkumar
^ permalink raw reply
* Re: [PATCH 3/3] mac80211: multicast to unicast conversion
From: Johannes Berg @ 2016-10-05 11:58 UTC (permalink / raw)
To: michael-dev; +Cc: linux-wireless, projekt-wlan, netdev
In-Reply-To: <1690671fb30f19c53c7883a5207c5721@fami-braun.de>
On Wed, 2016-10-05 at 13:40 +0200, michael-dev wrote:
> Am 05.10.2016 12:19, schrieb Johannes Berg:
> >
> > >
> > > on both ends. Furthermore, I've seen a few mobile phone stations
> > > locally that indicate qos support but won't complete DHCP if
> > > their broadcasts are encapsulated as A-MSDU. Though they work
> > > fine with this series approach.
> >
> > Presumably those phones also don't even try to use DMS, right?
>
> When I traced this two years ago, almost no device indicated DMS
> support, even though almost all seem to accepted multicast in unicast
> a-msdu frames.
Right, that's what I suspected. I'm a bit surprised they accepted
multicast in unicast A-MSDU too, though I don't actually see any big
problem with it.
> > How did you determine that it "works fine"?
>
> First, I tested this manually using my own devices or asked friends.
[snip
Thanks!
> > I see at least one undesirable impact of this, which DMS doesn't
> > have; it breaks a client's MUST NOT requirement from RFC 1122:
>
> Okay, so this cannot go into linux, right?
I'm not necessarily saying that, I just think we need to be careful
documenting possibly unexpected/undesired side-effects.
> > > + * @set_ap_unicast: set the multicast to unicast flag for a AP
> > > interface
> >
> > That API name isn't very descriptive, I'm sure we can do something
> > better there.
>
> proposal: "request multicast packets to be trasnmitted as unicast" ?
I was thinking more of the function name ("set_ap_unicast") which by
itself makes no sense - set_multicast_to_unicast or something like that
would be better, no?
> > Also, perhaps we should structure this already like we would DMS,
> > with a per-station toggle or even list of multicast addresses?
>
> should be possible, yes
I'm mostly handwaving though, haven't really looked at what DMS really
would require from the API, even assuming that hostapd would implement
all the action frame handling etc.
It's quite possible that on the *client* side, mac80211 should
implement the DMS client, if supported, and perhaps only if enabled by
some kind of configuration knob.
> > Was this not documented but also intended to apply to its dependent
> > VLANs?
>
> it was intended as a per per-BSS toggle, so it applies to all
> dependent VLANs automatically.
makes sense, but you should document it in the API documentation, which
today says "for a AP interface" or so (see above)
(btw - writing that out I see that it should be "an AP interface" too)
> >
> > >
> > > +/* Check if multicast to unicast conversion is needed and do it.
> > > + * Returns 1 if skb was freed and should not be send out. */
> >
> > wrong comment style :)
>
> you mean the */ at end of line instead of on a new line?
yeah, no big deal though.
I've also mostly gone back to non-davem style with /* also on its own
line, but it's not so important. :)
> > > + unicast = nla_data(info->attrs[NL80211_ATTR_UNICAST]);
> >
> > What's this supposed to mean?
>
> this was supposed to be nla_get_u8.
Shouldn't it just be nla_get_flag()? I mean, why do you have a u8 with
values 0/1 rather than just flag attribute absent/present?
Anyway, perhaps this needs to change to take DMS/per-station into
account?
Then again, this kind of setting - global multicast-to-unicast -
fundamentally *cannot* be done on a per-station basis, since if you
enable it for one station and not for another, the first station that
has it enabled would get the packets twice...
johannes
^ permalink raw reply
* [PATCH] [wl18xx] Fix memory leakage if kzalloc fails
From: Souptick Joarder @ 2016-10-05 11:50 UTC (permalink / raw)
To: linux-wireless; +Cc: sahu.rameshwar73
This patch is added to properly handle memory leak if kzalloc fails
in wl18xx_scan_send() and wl18xx_scan_sched_scan_config()
Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
Signed-off-by: Rameshwar Sahu <sahu.rameshwar73@gmail.com>
---
drivers/net/wireless/ti/wl18xx/scan.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ti/wl18xx/scan.c b/drivers/net/wireless/ti/wl18xx/scan.c
index 4e522154..aed22e1 100644
--- a/drivers/net/wireless/ti/wl18xx/scan.c
+++ b/drivers/net/wireless/ti/wl18xx/scan.c
@@ -41,14 +41,13 @@ static void wl18xx_adjust_channels(struct wl18xx_cmd_scan_params *cmd,
static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct cfg80211_scan_request *req)
{
- struct wl18xx_cmd_scan_params *cmd;
+ struct wl18xx_cmd_scan_params *cmd = NULL;
struct wlcore_scan_channels *cmd_channels = NULL;
int ret;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
- ret = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
/* scan on the dev role if the regular one is not started */
@@ -59,7 +58,7 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (WARN_ON(cmd->role_id == WL12XX_INVALID_ROLE_ID)) {
ret = -EINVAL;
- goto out;
+ goto err_cmd_free;
}
cmd->scan_type = SCAN_TYPE_SEARCH;
@@ -84,7 +83,7 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
cmd_channels = kzalloc(sizeof(*cmd_channels), GFP_KERNEL);
if (!cmd_channels) {
ret = -ENOMEM;
- goto out;
+ goto err_cmd_free;
}
wlcore_set_scan_chan_params(wl, cmd_channels, req->channels,
@@ -153,6 +152,7 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
out:
kfree(cmd_channels);
+err_cmd_free:
kfree(cmd);
return ret;
}
@@ -171,7 +171,7 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req,
struct ieee80211_scan_ies *ies)
{
- struct wl18xx_cmd_scan_params *cmd;
+ struct wl18xx_cmd_scan_params *cmd = NULL;
struct wlcore_scan_channels *cmd_channels = NULL;
struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
int ret;
@@ -185,15 +185,14 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
- ret = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
cmd->role_id = wlvif->role_id;
if (WARN_ON(cmd->role_id == WL12XX_INVALID_ROLE_ID)) {
ret = -EINVAL;
- goto out;
+ goto err_cmd_free;
}
cmd->scan_type = SCAN_TYPE_PERIODIC;
@@ -218,7 +217,7 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
cmd_channels = kzalloc(sizeof(*cmd_channels), GFP_KERNEL);
if (!cmd_channels) {
ret = -ENOMEM;
- goto out;
+ goto err_cmd_free;
}
/* configure channels */
@@ -296,6 +295,7 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
out:
kfree(cmd_channels);
+err_cmd_free:
kfree(cmd);
return ret;
}
--
1.9.1
^ permalink raw reply related
* Re: [PATCH 3/3] mac80211: multicast to unicast conversion
From: michael-dev @ 2016-10-05 11:40 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, projekt-wlan, netdev
In-Reply-To: <1475662791.4994.39.camel@sipsolutions.net>
Am 05.10.2016 12:19, schrieb Johannes Berg:
>> on both ends. Furthermore, I've seen a few mobile phone stations
>> locally that indicate qos support but won't complete DHCP if their
>> broadcasts are encapsulated as A-MSDU. Though they work fine with
>> this series approach.
>=20
> Presumably those phones also don't even try to use DMS, right?
When I traced this two years ago, almost no device indicated DMS=20
support, even though almost all seem to accepted multicast in unicast=20
a-msdu frames.
>=20
>> This patch therefore does not opt to implement DMS but instead just
>> replicates the packet and changes the destination address. As this
>> works fine with ARP, IPv4 and IPv6, it is limited to these protocols
>> and normal 802.11 multicast frames are send out for all other payload
>> protocols.
>=20
> How did you determine that it "works fine"?
First, I tested this manually using my own devices or asked friends. I=20
think this covered at least a recent debian x64 with an intel wireless=20
card, a windows 7 x64 with an intel wireless card, an android phone, an=20
ios phone and some recent macbook. Manually testing included visiting an=20
IPv6 only website (this network uses IPv6 router advertismentens (RA)=20
but no DHCPv6), so RA is accepted and ND working. Additionally,=20
arping'ing these station using broadcast arp request worked fine, so=20
broadcast arp requests are working. Finally, DHCP worked fine and UPNP=20
multicast discovery for some closed source media streaming wireless=20
device was reported working.
Next, that change was rolled out. It is now in use for at least three=20
years with about 300 simulatenously online stations and >2000 currently=20
registered devices and there hasn't been a single problem report that=20
could be related to that change. Though, e.g. our samsung galaxy users=20
report consistently that their devices refuse to connect using WPA-PSK=20
as our network advertises FT-PSK next to WPA-PSK and I learned that=20
there was at least one device there that did not like the=20
multicast-as-unicast-amsdu packets due to a user problem report.
> I see at least one undesirable impact of this, which DMS doesn't have;
> it breaks a client's MUST NOT requirement from RFC 1122:
Okay, so this cannot go into linux, right?
The thing I dislike most about DMS is that it is client driven, that is=20
an AP will only apply unicast conversion if a station actively requests=20
so.
> You should split the patch into cfg80211 and mac80211, IMHO it's big
> enough to do that.
ok
>> + * @set_ap_unicast: set the multicast to unicast flag for a AP
>> interface
>=20
> That API name isn't very descriptive, I'm sure we can do something
> better there.
proposal: "request multicast packets to be trasnmitted as unicast" ?
> Also, perhaps we should structure this already like we would DMS, with
> a per-station toggle or even list of multicast addresses?
should be possible, yes
>> +static int ieee80211_set_ap_unicast(struct wiphy *wiphy, struct
>> net_device *dev,
>> + =C2=A0=C2=A0=C2=A0=C2=A0const bool unicast)
>> +{
>> + struct ieee80211_sub_if_data *sdata =3D
>> IEEE80211_DEV_TO_SUB_IF(dev);
>> +
>> + if (sdata->vif.type !=3D NL80211_IFTYPE_AP)
>> + return -1;
>=20
> Was this not documented but also intended to apply to its dependent
> VLANs?
it was intended as a per per-BSS toggle, so it applies to all dependent=20
VLANs automatically.
>> +/* Check if multicast to unicast conversion is needed and do it.
>> + * Returns 1 if skb was freed and should not be send out. */
>=20
> wrong comment style :)
you mean the */ at end of line instead of on a new line?
>> + unicast =3D nla_data(info->attrs[NL80211_ATTR_UNICAST]);
>=20
> What's this supposed to mean?
this was supposed to be nla_get_u8.
michael
^ permalink raw reply
* Re: [PATCH 3/3] mac80211: multicast to unicast conversion
From: Johannes Berg @ 2016-10-05 10:19 UTC (permalink / raw)
To: Michael Braun; +Cc: linux-wireless, projekt-wlan, netdev
In-Reply-To: <1475643324-2845-3-git-send-email-michael-dev@fami-braun.de>
+netdev
> IEEE802.11-2012 proposes directed multicast service (DMS) using A-
> MSDU frames and a station initiated control protocol. It has the
> advantage that the station can recover the destination multicast mac
> address, but it is not backward compatible with non QOS stations and
> does not enable the administrator of a BSS to force this mode of
> operation within a BSS. Additionally, it would require both the ap
> and the station to implement the control protocol, which is optional
> on both ends. Furthermore, I've seen a few mobile phone stations
> locally that indicate qos support but won't complete DHCP if their
> broadcasts are encapsulated as A-MSDU. Though they work fine with
> this series approach.
Presumably those phones also don't even try to use DMS, right?
> This patch therefore does not opt to implement DMS but instead just
> replicates the packet and changes the destination address. As this
> works fine with ARP, IPv4 and IPv6, it is limited to these protocols
> and normal 802.11 multicast frames are send out for all other payload
> protocols.
How did you determine that it "works fine"?
I see at least one undesirable impact of this, which DMS doesn't have;
it breaks a client's MUST NOT requirement from RFC 1122:
An ICMP error message MUST NOT be sent as the result of
receiving:
[...]
* a datagram sent as a link-layer broadcast, or
[...]
since the client can no longer realize that the datagram was in fact
sent as a link-layer broadcast (or multicast).
> include/net/cfg80211.h | 5 ++
> include/uapi/linux/nl80211.h | 7 +++
> net/mac80211/cfg.c | 14 ++++++
> net/mac80211/debugfs_netdev.c | 29 ++++++++++++
> net/mac80211/ieee80211_i.h | 1 +
> net/mac80211/tx.c | 103
> ++++++++++++++++++++++++++++++++++++++++++
> net/wireless/nl80211.c | 33 ++++++++++++++
> net/wireless/rdev-ops.h | 11 +++++
> net/wireless/trace.h | 19 ++++++++
> 9 files changed, 222 insertions(+)
You should split the patch into cfg80211 and mac80211, IMHO it's big
enough to do that.
> + * @set_ap_unicast: set the multicast to unicast flag for a AP
> interface
That API name isn't very descriptive, I'm sure we can do something
better there.
Also, perhaps we should structure this already like we would DMS, with
a per-station toggle or even list of multicast addresses?
> @@ -2261,6 +2266,8 @@ enum nl80211_attrs {
>
> NL80211_ATTR_MESH_PEER_AID,
>
> + NL80211_ATTR_UNICAST,
missing docs, but likely doesn't matter after the comment above
> +static int ieee80211_set_ap_unicast(struct wiphy *wiphy, struct
> net_device *dev,
> + const bool unicast)
> +{
> + struct ieee80211_sub_if_data *sdata =
> IEEE80211_DEV_TO_SUB_IF(dev);
> +
> + if (sdata->vif.type != NL80211_IFTYPE_AP)
> + return -1;
Was this not documented but also intended to apply to its dependent
VLANs?
> +static ssize_t
> +ieee80211_if_fmt_unicast(const struct ieee80211_sub_if_data *sdata,
> + char *buf, int buflen)
> +{
> + const struct ieee80211_if_ap *ifap = &sdata->u.ap;
> +
> + return snprintf(buf, buflen, "0x%x\n", ifap->unicast);
> +}
> +
> +static ssize_t
> +ieee80211_if_parse_unicast(struct ieee80211_sub_if_data *sdata,
> + const char *buf, int buflen)
> +{
> + struct ieee80211_if_ap *ifap = &sdata->u.ap;
> + u8 val;
> + int ret;
> +
> + ret = kstrtou8(buf, 0, &val);
> + if (ret)
> + return ret;
> +
> + ifap->unicast = val ? 1 : 0;
> +
> + return buflen;
> +}
> +
> +IEEE80211_IF_FILE_RW(unicast);
No need for this, at least the setter, any more.
> +/* Check if multicast to unicast conversion is needed and do it.
> + * Returns 1 if skb was freed and should not be send out. */
wrong comment style :)
> +static int
> +ieee80211_tx_multicast_to_unicast(struct ieee80211_sub_if_data
> *sdata,
> + struct sk_buff *skb,
> u32 info_flags)
> +{
> + struct ieee80211_local *local = sdata->local;
> + const struct ethhdr *eth = (void *)skb->data;
> + const struct vlan_ethhdr *ethvlan = (void *)skb->data;
> + struct sta_info *sta, *prev = NULL;
> + struct sk_buff *cloned_skb;
> + u16 ethertype;
> +
> + /* multicast to unicast conversion only for AP interfaces */
> + switch (sdata->vif.type) {
> + case NL80211_IFTYPE_AP_VLAN:
> + sta = rcu_dereference(sdata->u.vlan.sta);
> + if (sta) /* 4addr */
> + return 0;
> + case NL80211_IFTYPE_AP:
> + break;
> + default:
> + return 0;
> + }
> +
> + /* check runtime toggle for this bss */
> + if (!sdata->bss->unicast)
> + return 0;
> +
> + /* check if this is a multicast frame */
> + if (!is_multicast_ether_addr(eth->h_dest))
> + return 0;
That should probably come first, would make this far easier to read.
> + if (unlikely(!memcmp(eth->h_source, sta->sta.addr,
> ETH_ALEN)))
> + /* do not send back to source */
> + continue;
ether_addr_something, instead of memcmp?
> + if (unlikely(is_multicast_ether_addr(sta-
> >sta.addr))) {
> + WARN_ONCE(1, "sta with multicast address
> %pM",
> + sta->sta.addr);
> + continue;
> + }
Err, no, remove this... it cannot happen. We could move the check into
cfg80211 from mac80211, but we surely shouldn't add it into the TX
hotpath!
> + if (prev) {
> + cloned_skb = skb_clone(skb, GFP_ATOMIC);
> + if (likely(!ieee80211_change_da(cloned_skb,
> prev)))
> + ieee80211_subif_start_xmit(cloned_sk
> b,
> + cloned_sk
> b->dev);
I'm not very happy with this recursion, but I guess it can't be avoided
easily. However, you can easily call the more
sensible __ieee80211_subif_start_xmit() instead of this one.
> + unicast = nla_data(info->attrs[NL80211_ATTR_UNICAST]);
What's this supposed to mean?
johannes
^ permalink raw reply
* [PATCHv4] mac80211: check A-MSDU inner frame source address on AP interfaces
From: Michael Braun @ 2016-10-05 10:02 UTC (permalink / raw)
To: johannes
Cc: Michael Braun, linux-wireless, projekt-wlan, kvalo, akarwar,
nishants, Larry.Finger, Jes.Sorensen
When using WPA security, the station and thus the required key is
identified by its mac address when packets are received. So a
station usually cannot spoof its source mac address.
But when a station sends an A-MSDU frame, port control and crypto
is done using the outer mac address, while the packets delivered
and forwarded use the inner mac address.
This might affect ARP/IP filtering on the AccessPoint.
IEEE 802.11-2012 mandates that the outer source mac address should
match the inner source address (section 8.3.2.2). For the destination
mac address, matching is not required, as a wifi client may send all
its traffic to the AP in order to have it forwarded.
Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
To: johannes@sipsolutions.net
Cc: linux-wireless@vger.kernel.org
Cc: projekt-wlan@fem.tu-ilmenau.de
Cc: kvalo@codeaurora.org
Cc: akarwar@marvell.com
Cc: nishants@marvell.com
Cc: Larry.Finger@lwfinger.net
Cc: Jes.Sorensen@redhat.com
v4: check for IBSS, STATION, TDLS data frame
---
drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 3 +-
.../net/wireless/marvell/mwifiex/11n_rxreorder.c | 3 +-
drivers/staging/rtl8723au/core/rtw_recv.c | 2 +-
include/net/cfg80211.h | 16 ++++---
net/mac80211/rx.c | 25 ++++++++---
net/wireless/util.c | 52 +++++++++++++++-------
6 files changed, 70 insertions(+), 31 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 4fdc3da..05dcaef 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -1436,7 +1436,8 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm,
memcpy(skb_put(pkt, pktsize), pktdata, pktsize);
- if (ieee80211_data_to_8023(pkt, vif->addr, vif->type))
+ if (ieee80211_data_to_8023(pkt, NULL, vif->addr,
+ vif->type))
goto report;
wakeup.packet = pkt->data;
wakeup.packet_present_len = pkt->len;
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
index a74cc43..298e447 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -45,7 +45,8 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
- priv->wdev.iftype, 0, false);
+ priv->wdev.iftype, 0, NULL, NULL, 0,
+ 0);
while (!skb_queue_empty(&list)) {
struct rx_packet_hdr *rx_hdr;
diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c
index 150dabc..8f39a8b 100644
--- a/drivers/staging/rtl8723au/core/rtw_recv.c
+++ b/drivers/staging/rtl8723au/core/rtw_recv.c
@@ -1687,7 +1687,7 @@ int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe)
skb_pull(skb, prframe->attrib.hdrlen);
__skb_queue_head_init(&skb_list);
- ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0, false);
+ ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0, NULL, NULL, 0, 0);
while (!skb_queue_empty(&skb_list)) {
sub_skb = __skb_dequeue(&skb_list);
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index beb7610..b550314 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3905,12 +3905,13 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
/**
* ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
* @skb: the 802.11 data frame
+ * @ehdr: (out) buffer for source/destination address (optional)
* @addr: the device MAC address
* @iftype: the virtual interface type
* Return: 0 on success. Non-zero on error.
*/
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
- enum nl80211_iftype iftype);
+int ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
+ const u8 *addr, enum nl80211_iftype iftype);
/**
* ieee80211_data_from_8023 - convert an 802.3 frame to 802.11
@@ -3938,12 +3939,17 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
* @addr: The device MAC address.
* @iftype: The device interface type.
* @extra_headroom: The hardware extra headroom for SKBs in the @list.
- * @has_80211_header: Set it true if SKB is with IEEE 802.11 header.
+ * @ta: transmitter address (or NULL)
+ * @ra: receiver address (or NULL)
+ * @is_4addr: indicates that interface is in 4addr mode
+ * @is_tlds_data: indicates that frame as been received from TLDS peer
*/
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
- const u8 *addr, enum nl80211_iftype iftype,
+ const u8 *addr,
+ enum nl80211_iftype iftype,
const unsigned int extra_headroom,
- bool has_80211_header);
+ const u8 *ta, const u8 *ra, bool is_4addr,
+ bool is_tdls_data);
/**
* cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9dce3b1..3d8d889 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2090,7 +2090,8 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta)
return -1;
- ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
+ ret = ieee80211_data_to_8023(rx->skb, NULL, sdata->vif.addr,
+ sdata->vif.type);
if (ret < 0)
return ret;
@@ -2243,6 +2244,9 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
__le16 fc = hdr->frame_control;
struct sk_buff_head frame_list;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+ struct ethhdr eth_80211;
+ bool is_4addr;
+ bool is_tdls_data;
if (unlikely(!ieee80211_is_data(fc)))
return RX_CONTINUE;
@@ -2258,19 +2262,26 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
!rx->sdata->u.vlan.sta)
return RX_DROP_UNUSABLE;
- if (is_multicast_ether_addr(hdr->addr1) &&
- ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- rx->sdata->u.vlan.sta) ||
- (rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
- rx->sdata->u.mgd.use_4addr)))
+ is_4addr = ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+ rx->sdata->u.vlan.sta) ||
+ (rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
+ rx->sdata->u.mgd.use_4addr));
+ if (is_multicast_ether_addr(hdr->addr1) && is_4addr)
return RX_DROP_UNUSABLE;
skb->dev = dev;
__skb_queue_head_init(&frame_list);
+ if (ieee80211_data_to_8023(skb, ð_80211, dev->dev_addr,
+ rx->sdata->vif.type) < 0)
+ return RX_DROP_UNUSABLE;
+
+ is_tdls_data = !ieee80211_has_tods(fc) && !ieee80211_has_fromds(fc);
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
rx->sdata->vif.type,
- rx->local->hw.extra_tx_headroom, true);
+ rx->local->hw.extra_tx_headroom,
+ eth_80211.h_source,
+ eth_80211.h_dest, is_4addr, is_tdls_data);
while (!skb_queue_empty(&frame_list)) {
rx->skb = __skb_dequeue(&frame_list);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index b7d1592..84da5c2 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -414,8 +414,8 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
}
EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
-static int __ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
- const u8 *addr, enum nl80211_iftype iftype)
+int ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
+ const u8 *addr, enum nl80211_iftype iftype)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct {
@@ -519,12 +519,6 @@ static int __ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
return 0;
}
-
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
- enum nl80211_iftype iftype)
-{
- return __ieee80211_data_to_8023(skb, NULL, addr, iftype);
-}
EXPORT_SYMBOL(ieee80211_data_to_8023);
int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
@@ -738,24 +732,41 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
}
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
- const u8 *addr, enum nl80211_iftype iftype,
+ const u8 *addr,
+ enum nl80211_iftype iftype,
const unsigned int extra_headroom,
- bool has_80211_header)
+ const u8 *ta, const u8 *ra, bool is_4addr,
+ bool is_tdls_data)
{
unsigned int hlen = ALIGN(extra_headroom, 4);
struct sk_buff *frame = NULL;
u16 ethertype;
u8 *payload;
- int offset = 0, remaining, err;
+ int offset = 0, remaining;
struct ethhdr eth;
bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb);
bool reuse_skb = false;
bool last = false;
- if (has_80211_header) {
- err = __ieee80211_data_to_8023(skb, ð, addr, iftype);
- if (err)
- goto out;
+ /* limit inner src/dst checks depending on iftype */
+ switch (iftype) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ if (is_4addr)
+ ta = NULL;
+ ra = NULL;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ break;
+ case NL80211_IFTYPE_STATION:
+ if (is_4addr || !is_tdls_data)
+ ta = NULL;
+ if (is_4addr)
+ ra = NULL;
+ break;
+ default:
+ ta = NULL;
+ ra = NULL;
}
while (!last) {
@@ -768,6 +779,16 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
subframe_len = sizeof(struct ethhdr) + len;
padding = (4 - subframe_len) & 0x3;
+ if (unlikely(ta && !ether_addr_equal(ta, eth.h_source)))
+ goto purge;
+ /* for unicast frames, we accept multicast inner MSDUs
+ * to enable multicast to unicast conversion
+ */
+ if (unlikely(ra && !ether_addr_equal(ra, eth.h_dest) &&
+ (is_multicast_ether_addr(ra) ||
+ !is_multicast_ether_addr(eth.h_dest))))
+ goto purge;
+
/* the last MSDU has no padding */
remaining = skb->len - offset;
if (subframe_len > remaining)
@@ -813,7 +834,6 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
purge:
__skb_queue_purge(list);
- out:
dev_kfree_skb(skb);
}
EXPORT_SYMBOL(ieee80211_amsdu_to_8023s);
--
2.1.4
^ permalink raw reply related
* Re: [PATCH 2/3] mac80211: filter multicast data packets on AP / AP_VLAN
From: Johannes Berg @ 2016-10-05 10:01 UTC (permalink / raw)
To: Michael Braun; +Cc: linux-wireless, projekt-wlan
In-Reply-To: <1475643324-2845-2-git-send-email-michael-dev@fami-braun.de>
Please also add "v3" to the subject line, e.g. using --subject-prefix
'PATCH v3' when using git send-email.
> +static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
> +{
> + // add num_mcast_sta_vlan using name num_mcast_sta
Please don't use // style comments.
> +static inline void
> +ieee80211_vif_inc_num_mcast(struct ieee80211_sub_if_data *sdata)
> +{
> + if (sdata->vif.type != NL80211_IFTYPE_AP &&
> + sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
> + return;
That's pointless, given this:
> + if (sdata->vif.type == NL80211_IFTYPE_AP)
> + atomic_inc(&sdata->u.ap.num_mcast_sta);
> + else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
> + atomic_inc(&sdata->u.vlan.num_mcast_sta);
> +}
> +
> +static inline void
> +ieee80211_vif_dec_num_mcast(struct ieee80211_sub_if_data *sdata)
> +{
> + if (sdata->vif.type != NL80211_IFTYPE_AP &&
> + sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
> + return;
> +
> + if (sdata->vif.type == NL80211_IFTYPE_AP)
> + atomic_dec(&sdata->u.ap.num_mcast_sta);
> + else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
> + atomic_dec(&sdata->u.vlan.num_mcast_sta);
Same here.
> +}
> +
> +/* This function returns the number of multicast stations connected
> to this
> + * interface. It returns -1 if that number is not tracked, that is
> for netdevs
> + * not in AP or AP_VLAN mode or when using 4addr. */
> +static inline int
> +ieee80211_vif_get_num_mcast_if(struct ieee80211_sub_if_data *sdata)
> +{
> + if (sdata->vif.type == NL80211_IFTYPE_AP)
> + return atomic_read(&sdata->u.ap.num_mcast_sta);
> + else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
> + !sdata->u.vlan.sta)
> + return atomic_read(&sdata->u.vlan.num_mcast_sta);
> + else
> + return -1;
All the "else" branches are useless since you return immediately inside
each if.
> - } else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP &&
> - ieee80211_is_data(hdr->frame_control) &&
> - !atomic_read(&tx->sdata->u.ap.num_mcast_sta))) {
> + } else if (unlikely(ieee80211_vif_get_num_mcast_if(tx->sdata) == 0 &&
> + ieee80211_is_data(hdr->frame_control))) {
any particular reason to invert the order of the checks? seems checking
for data first should be faster/cheaper from the cache, than accessing
the counters?
johannes
^ permalink raw reply
* Re: [PATCH 2/3] mac80211: filter multicast data packets on AP / AP_VLAN
From: Johannes Berg @ 2016-10-05 9:56 UTC (permalink / raw)
To: Michael Braun; +Cc: linux-wireless, projekt-wlan
In-Reply-To: <1475643324-2845-2-git-send-email-michael-dev@fami-braun.de>
> Therefore, two new num_mcast_sta like counters are added: one for the
> number of authorized stations connected to an AP_VLAN interface and
> one for the number of authorized stations connected to the bss and
> not assigned to any AP_VLAN. The already existing num_mcast_sta
> counter is left unchanged as it is used by SMPS.
I think this is no longer accurate?
johannes
^ permalink raw reply
* [PATCH v2] mac80211: discard multicast and 4-addr A-MSDUs
From: Johannes Berg @ 2016-10-05 9:51 UTC (permalink / raw)
To: linux-wireless; +Cc: M . Braun, Felix Fietkau, Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
In mac80211, multicast A-MSDUs are accepted in many cases that
they shouldn't be accepted in:
* drop A-MSDUs with a multicast A1 (RA), as required by the
spec in 9.11 (802.11-2012 version)
* drop A-MSDUs with a 4-addr header, since the fourth address
can't actually be useful for them; unless 4-address frame
format is actually requested, even though the fourth address
is still not useful in this case, but ignored
Accepting the first case, in particular, is very problematic
since it allows anyone else with possession of a GTK to send
unicast frames encapsulated in a multicast A-MSDU, even when
the AP has client isolation enabled.
Cc: stable@vger.kernel.org
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/rx.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6175db385ba7..3ac2f1cba317 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2308,16 +2308,22 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
if (!(status->rx_flags & IEEE80211_RX_AMSDU))
return RX_CONTINUE;
- if (ieee80211_has_a4(hdr->frame_control) &&
- rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- !rx->sdata->u.vlan.sta)
- return RX_DROP_UNUSABLE;
+ if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
+ switch (rx->sdata->vif.type) {
+ case NL80211_IFTYPE_AP_VLAN:
+ if (!rx->sdata->u.vlan.sta)
+ return RX_DROP_UNUSABLE;
+ break;
+ case NL80211_IFTYPE_STATION:
+ if (!rx->sdata->u.mgd.use_4addr)
+ return RX_DROP_UNUSABLE;
+ break;
+ default:
+ return RX_DROP_UNUSABLE;
+ }
+ }
- if (is_multicast_ether_addr(hdr->addr1) &&
- ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- rx->sdata->u.vlan.sta) ||
- (rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
- rx->sdata->u.mgd.use_4addr)))
+ if (is_multicast_ether_addr(hdr->addr1))
return RX_DROP_UNUSABLE;
skb->dev = dev;
--
2.8.1
^ permalink raw reply related
* Re: [PATCH] mac80211: discard multicast and 4-addr A-MSDUs
From: Johannes Berg @ 2016-10-05 9:39 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless; +Cc: M . Braun
In-Reply-To: <1475660290.4994.21.camel@sipsolutions.net>
> Do you remember why you explicitly added code to *not* accept 4-addr
> frames in non-4addr AP_VLAN, but no other cases? This seems oddly
> specific.
>
Oh, maybe that's because more checks are done
in __ieee80211_data_to_8023().
johannes
^ permalink raw reply
* [PATCH] rsi: update in boot parameters
From: Prameela Rani Garnepudi @ 2016-10-05 9:35 UTC (permalink / raw)
To: linux-wireless
Cc: kvalo, johannes.berg, hofrat, xypron.glpk, prameela.garnepudi,
Prameela Rani Garnepudi
Added more clock switch fields in boot parameters configured to device
Signed-off-by: Prameela Rani Garnepudi <prameela.j04cs@gmail.com>
---
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 110 ++++++++++++++++++++---------
drivers/net/wireless/rsi/rsi_boot_params.h | 101 ++++++++++++++++++--------
2 files changed, 149 insertions(+), 62 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 35c14cc..046b354 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -18,6 +18,7 @@
#include "rsi_mgmt.h"
#include "rsi_common.h"
+/* Bootup Parameters for 20MHz */
static struct bootup_params boot_params_20 = {
.magic_number = cpu_to_le16(0x5aa5),
.crystal_good_time = 0x0,
@@ -28,14 +29,15 @@ static struct bootup_params boot_params_20 = {
.rtls_timestamp_en = 0x0,
.host_spi_intr_cfg = 0x0,
.device_clk_info = {{
+ /* WLAN params */
.pll_config_g = {
.tapll_info_g = {
- .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_20 << 8)|
- (TA_PLL_M_VAL_20)),
- .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_20),
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_20 << 8) |
+ (TAPLL_M_VAL_20)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_20),
},
.pll960_info_g = {
- .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8)|
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8) |
(PLL960_N_VAL_20)),
.pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20),
.pll_reg_3 = 0x0,
@@ -45,21 +47,27 @@ static struct bootup_params boot_params_20 = {
}
},
.switch_clk_g = {
- .switch_clk_info = cpu_to_le16(BIT(3)),
+ .switch_umac_clk = 0x0,
+ .switch_qspi_clk = 0x0,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x1,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
.bbp_lmac_clk_reg_val = cpu_to_le16(0x121),
.umac_clock_reg_config = 0x0,
.qspi_uart_clock_reg_config = 0x0
}
},
+ /* Bluetooth params */
{
.pll_config_g = {
.tapll_info_g = {
- .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_20 << 8)|
- (TA_PLL_M_VAL_20)),
- .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_20),
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_20 << 8) |
+ (TAPLL_M_VAL_20)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_20),
},
.pll960_info_g = {
- .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8)|
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8) |
(PLL960_N_VAL_20)),
.pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20),
.pll_reg_3 = 0x0,
@@ -69,21 +77,27 @@ static struct bootup_params boot_params_20 = {
}
},
.switch_clk_g = {
- .switch_clk_info = 0x0,
+ .switch_umac_clk = 0x0,
+ .switch_qspi_clk = 0x0,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x0,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
.bbp_lmac_clk_reg_val = 0x0,
.umac_clock_reg_config = 0x0,
.qspi_uart_clock_reg_config = 0x0
}
},
+ /* Zigbee params */
{
.pll_config_g = {
.tapll_info_g = {
- .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_20 << 8)|
- (TA_PLL_M_VAL_20)),
- .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_20),
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_20 << 8) |
+ (TAPLL_M_VAL_20)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_20),
},
.pll960_info_g = {
- .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8)|
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8) |
(PLL960_N_VAL_20)),
.pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20),
.pll_reg_3 = 0x0,
@@ -93,12 +107,18 @@ static struct bootup_params boot_params_20 = {
}
},
.switch_clk_g = {
- .switch_clk_info = 0x0,
+ .switch_umac_clk = 0x0,
+ .switch_qspi_clk = 0x0,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x0,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
.bbp_lmac_clk_reg_val = 0x0,
.umac_clock_reg_config = 0x0,
.qspi_uart_clock_reg_config = 0x0
}
} },
+ /* ULP Params */
.buckboost_wakeup_cnt = 0x0,
.pmu_wakeup_wait = 0x0,
.shutdown_wait_time = 0x0,
@@ -106,9 +126,13 @@ static struct bootup_params boot_params_20 = {
.wdt_prog_value = 0x0,
.wdt_soc_rst_delay = 0x0,
.dcdc_operation_mode = 0x0,
- .soc_reset_wait_cnt = 0x0
+ .soc_reset_wait_cnt = 0x0,
+ .waiting_time_at_fresh_sleep = 0x0,
+ .max_threshold_to_avoid_sleep = 0x0,
+ .beacon_resedue_alg_en = 0,
};
+/* Bootup parameters for 40MHz */
static struct bootup_params boot_params_40 = {
.magic_number = cpu_to_le16(0x5aa5),
.crystal_good_time = 0x0,
@@ -119,14 +143,15 @@ static struct bootup_params boot_params_40 = {
.rtls_timestamp_en = 0x0,
.host_spi_intr_cfg = 0x0,
.device_clk_info = {{
+ /* WLAN params */
.pll_config_g = {
.tapll_info_g = {
- .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_40 << 8)|
- (TA_PLL_M_VAL_40)),
- .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_40),
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_40 << 8) |
+ (TAPLL_M_VAL_40)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_40),
},
.pll960_info_g = {
- .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8)|
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8) |
(PLL960_N_VAL_40)),
.pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40),
.pll_reg_3 = 0x0,
@@ -136,21 +161,27 @@ static struct bootup_params boot_params_40 = {
}
},
.switch_clk_g = {
- .switch_clk_info = cpu_to_le16(0x09),
+ .switch_umac_clk = 0x1,
+ .switch_qspi_clk = 0x0,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x1,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
.bbp_lmac_clk_reg_val = cpu_to_le16(0x1121),
.umac_clock_reg_config = cpu_to_le16(0x48),
.qspi_uart_clock_reg_config = 0x0
}
},
+ /* Bluetooth Params */
{
.pll_config_g = {
.tapll_info_g = {
- .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_40 << 8)|
- (TA_PLL_M_VAL_40)),
- .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_40),
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_40 << 8) |
+ (TAPLL_M_VAL_40)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_40),
},
.pll960_info_g = {
- .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8)|
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8) |
(PLL960_N_VAL_40)),
.pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40),
.pll_reg_3 = 0x0,
@@ -160,21 +191,27 @@ static struct bootup_params boot_params_40 = {
}
},
.switch_clk_g = {
- .switch_clk_info = 0x0,
+ .switch_umac_clk = 0x0,
+ .switch_qspi_clk = 0x0,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x0,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
.bbp_lmac_clk_reg_val = 0x0,
.umac_clock_reg_config = 0x0,
.qspi_uart_clock_reg_config = 0x0
}
},
+ /* Zigbee Params */
{
.pll_config_g = {
.tapll_info_g = {
- .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_40 << 8)|
- (TA_PLL_M_VAL_40)),
- .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_40),
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_40 << 8) |
+ (TAPLL_M_VAL_40)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_40),
},
.pll960_info_g = {
- .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8)|
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8) |
(PLL960_N_VAL_40)),
.pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40),
.pll_reg_3 = 0x0,
@@ -184,12 +221,18 @@ static struct bootup_params boot_params_40 = {
}
},
.switch_clk_g = {
- .switch_clk_info = 0x0,
+ .switch_umac_clk = 0x0,
+ .switch_qspi_clk = 0x0,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x0,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
.bbp_lmac_clk_reg_val = 0x0,
.umac_clock_reg_config = 0x0,
.qspi_uart_clock_reg_config = 0x0
}
} },
+ /* ULP Params */
.buckboost_wakeup_cnt = 0x0,
.pmu_wakeup_wait = 0x0,
.shutdown_wait_time = 0x0,
@@ -197,7 +240,10 @@ static struct bootup_params boot_params_40 = {
.wdt_prog_value = 0x0,
.wdt_soc_rst_delay = 0x0,
.dcdc_operation_mode = 0x0,
- .soc_reset_wait_cnt = 0x0
+ .soc_reset_wait_cnt = 0x0,
+ .waiting_time_at_fresh_sleep = 0x0,
+ .max_threshold_to_avoid_sleep = 0x0,
+ .beacon_resedue_alg_en = 0,
};
static u16 mcs[] = {13, 26, 39, 52, 78, 104, 117, 130};
diff --git a/drivers/net/wireless/rsi/rsi_boot_params.h b/drivers/net/wireless/rsi/rsi_boot_params.h
index 5e2721f..9f5d61d 100644
--- a/drivers/net/wireless/rsi/rsi_boot_params.h
+++ b/drivers/net/wireless/rsi/rsi_boot_params.h
@@ -17,71 +17,77 @@
#ifndef __RSI_BOOTPARAMS_HEADER_H__
#define __RSI_BOOTPARAMS_HEADER_H__
-#define CRYSTAL_GOOD_TIME BIT(0)
-#define BOOTUP_MODE_INFO BIT(1)
-#define WIFI_TAPLL_CONFIGS BIT(5)
-#define WIFI_PLL960_CONFIGS BIT(6)
-#define WIFI_AFEPLL_CONFIGS BIT(7)
-#define WIFI_SWITCH_CLK_CONFIGS BIT(8)
+#define CRYSTAL_GOOD_TIME BIT(0)
+#define BOOTUP_MODE_INFO BIT(1)
+#define WIFI_TAPLL_CONFIGS BIT(5)
+#define WIFI_PLL960_CONFIGS BIT(6)
+#define WIFI_AFEPLL_CONFIGS BIT(7)
+#define WIFI_SWITCH_CLK_CONFIGS BIT(8)
-#define TA_PLL_M_VAL_20 8
-#define TA_PLL_N_VAL_20 1
-#define TA_PLL_P_VAL_20 4
+#define TAPLL_M_VAL_20 8
+#define TAPLL_N_VAL_20 1
+#define TAPLL_P_VAL_20 4
-#define PLL960_M_VAL_20 0x14
-#define PLL960_N_VAL_20 0
-#define PLL960_P_VAL_20 5
+#define PLL960_M_VAL_20 0x14
+#define PLL960_N_VAL_20 0
+#define PLL960_P_VAL_20 5
-#define UMAC_CLK_40MHZ 40
+#define UMAC_CLK_40MHZ 40
-#define TA_PLL_M_VAL_40 46
-#define TA_PLL_N_VAL_40 3
-#define TA_PLL_P_VAL_40 3
+#define TAPLL_M_VAL_40 46
+#define TAPLL_N_VAL_40 3
+#define TAPLL_P_VAL_40 3
-#define PLL960_M_VAL_40 0x14
-#define PLL960_N_VAL_40 0
-#define PLL960_P_VAL_40 5
+#define PLL960_M_VAL_40 0x14
+#define PLL960_N_VAL_40 0
+#define PLL960_P_VAL_40 5
#define UMAC_CLK_20BW \
- (((TA_PLL_M_VAL_20 + 1) * 40) / \
- ((TA_PLL_N_VAL_20 + 1) * (TA_PLL_P_VAL_20 + 1)))
+ (((TAPLL_M_VAL_20 + 1) * 40) / \
+ ((TAPLL_N_VAL_20 + 1) * (TAPLL_P_VAL_20 + 1)))
#define VALID_20 \
(WIFI_PLL960_CONFIGS | WIFI_AFEPLL_CONFIGS | WIFI_SWITCH_CLK_CONFIGS)
#define UMAC_CLK_40BW \
- (((TA_PLL_M_VAL_40 + 1) * 40) / \
- ((TA_PLL_N_VAL_40 + 1) * (TA_PLL_P_VAL_40 + 1)))
+ (((TAPLL_M_VAL_40 + 1) * 40) / \
+ ((TAPLL_N_VAL_40 + 1) * (TAPLL_P_VAL_40 + 1)))
#define VALID_40 \
(WIFI_PLL960_CONFIGS | WIFI_AFEPLL_CONFIGS | WIFI_SWITCH_CLK_CONFIGS | \
WIFI_TAPLL_CONFIGS | CRYSTAL_GOOD_TIME | BOOTUP_MODE_INFO)
-/* structure to store configs related to TAPLL programming */
+/* TAPLL programming configurations */
struct tapll_info {
__le16 pll_reg_1;
__le16 pll_reg_2;
} __packed;
-/* structure to store configs related to PLL960 programming */
+/* PLL960 programming configurations */
struct pll960_info {
__le16 pll_reg_1;
__le16 pll_reg_2;
__le16 pll_reg_3;
} __packed;
-/* structure to store configs related to AFEPLL programming */
+/* AFEPLL programming configurations */
struct afepll_info {
__le16 pll_reg;
} __packed;
-/* structure to store configs related to pll configs */
+/* PLL configurations */
struct pll_config {
struct tapll_info tapll_info_g;
struct pll960_info pll960_info_g;
struct afepll_info afepll_info_g;
} __packed;
-/* structure to store configs related to UMAC clk programming */
+/* UMAC clk programming configurations */
struct switch_clk {
- __le16 switch_clk_info;
+ __le16 switch_umac_clk : 1; /* If set rest is valid */
+ __le16 switch_qspi_clk : 1; /* If set qspi clk will be changed */
+ __le16 switch_slp_clk_2_32 : 1;
+ __le16 switch_bbp_lmac_clk_reg : 1;
+ __le16 switch_mem_ctrl_cfg : 1;
+ __le16 reserved : 11;
+
/* If switch_bbp_lmac_clk_reg is set then this value will be programmed
* into reg
*/
@@ -99,11 +105,43 @@ struct device_clk_info {
struct bootup_params {
__le16 magic_number;
+#define LOADED_TOKEN 0x5AA5 /* Bootup params are installed by host
+ * or OTP/FLASH (Bootloader)
+ */
+#define ROM_TOKEN 0x55AA /* Bootup params are taken from ROM
+ * itself in MCU mode.
+ */
__le16 crystal_good_time;
__le32 valid;
+#define CRYSTAL_GOOD_TIME BIT(0)
+#define BOOTUP_MODE_INFO BIT(1)
+#define DIGITAL_LOOP_BACK_PARAMS BIT(2)
+#define RTLS_TIMESTAMP_EN BIT(3)
+#define HOST_SPI_INTR_CFG BIT(4)
+#define WIFI_TAPLL_CONFIGS BIT(5)
+#define WIFI_PLL960_CONFIGS BIT(6)
+#define WIFI_AFEPLL_CONFIGS BIT(7)
+#define WIFI_SWITCH_CLK_CONFIGS BIT(8)
+#define BT_TAPLL_CONFIGS BIT(9)
+#define BT_PLL960_CONFIGS BIT(10)
+#define BT_AFEPLL_CONFIGS BIT(11)
+#define BT_SWITCH_CLK_CONFIGS BIT(12)
+#define ZB_TAPLL_CONFIGS BIT(13)
+#define ZB_PLL960_CONFIGS BIT(14)
+#define ZB_AFEPLL_CONFIGS BIT(15)
+#define ZB_SWITCH_CLK_CONFIGS BIT(16)
+#define BUCKBOOST_WAIT_INFO BIT(17)
+#define PMU_WAKEUP_SHUTDOWN_W BIT(18)
+#define WDT_PROG_VALUES BIT(19)
+#define WDT_RESET_DELAY_VALUE BIT(20)
+#define DCDC_OPERATION_MODE_VALID BIT(21)
+#define PMU_SLP_CLKOUT_SEL BIT(22)
+#define SOC_RESET_WAIT_CNT BIT(23)
__le32 reserved_for_valids;
__le16 bootup_mode_info;
- /* configuration used for digital loop back */
+#define BT_COEXIST BIT(0)
+#define BOOTUP_MODE (BIT(2) | BIT(1))
+#define CUR_DEV_MODE (bootup_params.bootup_mode_info >> 1)
__le16 digital_loop_back_params;
__le16 rtls_timestamp_en;
__le16 host_spi_intr_cfg;
@@ -122,5 +160,8 @@ struct bootup_params {
/* dcdc modes configs */
__le32 dcdc_operation_mode;
__le32 soc_reset_wait_cnt;
+ __le32 waiting_time_at_fresh_sleep;
+ __le32 max_threshold_to_avoid_sleep;
+ u8 beacon_resedue_alg_en;
} __packed;
#endif
--
2.4.11
^ permalink raw reply related
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