* Re: [PATCH] brcmfmac: implement more accurate skb tracking
From: Dan Williams @ 2016-09-26 14:59 UTC (permalink / raw)
To: Rafał Miłecki, Arend Van Spriel
Cc: Kalle Valo, Franky Lin, Hante Meuleman, Pieter-Paul Giesberts,
Franky Lin, linux-wireless@vger.kernel.org,
open list:BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER,
Network Development, Linux Kernel Mailing List,
Rafał Miłecki
In-Reply-To: <CACna6rwnLb3sEPmdx6uhYMstVn04WbP2xzznsjnwgguEXn04=w@mail.gmail.com>
On Mon, 2016-09-26 at 14:13 +0200, Rafał Miłecki wrote:
> On 26 September 2016 at 13:46, Arend Van Spriel
> <arend.vanspriel@broadcom.com> wrote:
> >
> > On 26-9-2016 12:23, Rafał Miłecki wrote:
> > >
> > > From: Rafał Miłecki <rafal@milecki.pl>
> > >
> > > We need to track 802.1x packets to know if there are any pending
> > > ones
> > > for transmission. This is required for performing key update in
> > > the
> > > firmware.
> >
> > The problem we are trying to solve is a pretty old one. The problem
> > is
> > that wpa_supplicant uses two separate code paths: EAPOL messaging
> > through data path and key configuration though nl80211.
>
> Can I find it described/reported somewhere?
If I understand the issue correctly, you can find all this in the
supplicant code. Once the supplicant has done whatever it wants to do
with the data frames that just happen to be EAPOL it then sends the
keys down to the driver with nl80211.
But it sounds like, instead of sniffing EAPOL frames in the driver skb
tracking and sniffing ETH_P_PAE, you should probably implement support
for NL80211_CMD_CRIT_PROTOCOL_START/NL80211_CMD_CRIT_PROTOCOL_STOP and
key off the passed-in NL80211_CRIT_PROTO_EAPOL. At least at the
beginning of connection setup only EAPOL packets will be allowed
anyway.
It doesn't seem like the supplicant uses NL80211_CRIT_PROTO_EAPOL yet,
but that should also be fixed in the supplicant itself. You should
probably get some comments from Jouni on how he'd like to see all this
work. But generally the less specific sniffing of frames in drivers,
likely the better.
Dan
>
> >
> > >
> > > Unfortunately our old tracking code wasn't very accurate. It was
> > > treating skb as pending as soon as it was passed by the netif.
> > > Actual
> > > handling packet to the firmware was happening later as brcmfmac
> > > internally queues them and uses its own worker(s).
> >
> > That does not seem right. As soon as we get a 1x packet we need to
> > wait
> > with key configuration regardless whether it is still in the driver
> > or
> > handed over to firmware already.
>
> OK, thanks.
^ permalink raw reply
* Re: [1/3] hostap: Use memdup_user() rather than duplicating its implementation
From: Kalle Valo @ 2016-09-26 14:19 UTC (permalink / raw)
To: SF Markus Elfring
Cc: linux-wireless, netdev, Jouni Malinen, LKML, kernel-janitors,
Julia Lawall
In-Reply-To: <efa66c16-7998-9ceb-0be6-d62dd249a2dc@users.sourceforge.net>
SF Markus Elfring <elfring@users.sourceforge.net> wrote:
> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Sat, 20 Aug 2016 18:19:43 +0200
>
> Reuse existing functionality from memdup_user() instead of keeping
> duplicate source code.
>
> This issue was detected by using the Coccinelle software.
>
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
Patch set to Rejected.
[1/3] hostap: Use memdup_user() rather than duplicating i... 2016-08-20 SF Markus El Rejected
Reason: A similar patch is already applied.
Applying: hostap: Use memdup_user() rather than duplicating its implementation
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging drivers/net/wireless/intersil/hostap/hostap_ioctl.c
CONFLICT (content): Merge conflict in drivers/net/wireless/intersil/hostap/hostap_ioctl.c
Failed to merge in the changes.
Patch failed at 0001 hostap: Use memdup_user() rather than duplicating its implementation
--
https://patchwork.kernel.org/patch/9306999/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: wil6200
From: Lior David @ 2016-09-26 12:49 UTC (permalink / raw)
To: Vikram, linux-wireless
In-Reply-To: <CALZLQ=biEM2efkYhkr6PYu7wn_CJTJ9LQg+0VJvf2rMgmKPS9w@mail.gmail.com>
On 9/25/2016 6:15 PM, Vikram wrote:
> Hi,
>
> Could you please let me know as to how to change the mode of wil6200
> chip from WBE to WiFi?
>
> Regards,
> Vikram
>
What is the exact device you are using? Older devices have firmware that only
supports WBE mode.
Thanks,
Lior
^ permalink raw reply
* Re: [PATCH] brcmfmac: implement more accurate skb tracking
From: Rafał Miłecki @ 2016-09-26 12:38 UTC (permalink / raw)
To: Arend Van Spriel
Cc: Kalle Valo, Franky Lin, Hante Meuleman, Pieter-Paul Giesberts,
Franky Lin, linux-wireless@vger.kernel.org,
open list:BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER,
Network Development, Linux Kernel Mailing List,
Rafał Miłecki
In-Reply-To: <CACna6rwnLb3sEPmdx6uhYMstVn04WbP2xzznsjnwgguEXn04=w@mail.gmail.com>
On 26 September 2016 at 14:13, Rafa=C5=82 Mi=C5=82ecki <zajec5@gmail.com> w=
rote:
> On 26 September 2016 at 13:46, Arend Van Spriel
> <arend.vanspriel@broadcom.com> wrote:
>> On 26-9-2016 12:23, Rafa=C5=82 Mi=C5=82ecki wrote:
>>> From: Rafa=C5=82 Mi=C5=82ecki <rafal@milecki.pl>
>>>
>>> We need to track 802.1x packets to know if there are any pending ones
>>> for transmission. This is required for performing key update in the
>>> firmware.
>>
>> The problem we are trying to solve is a pretty old one. The problem is
>> that wpa_supplicant uses two separate code paths: EAPOL messaging
>> through data path and key configuration though nl80211.
>
> Can I find it described/reported somewhere?
>
>
>>> Unfortunately our old tracking code wasn't very accurate. It was
>>> treating skb as pending as soon as it was passed by the netif. Actual
>>> handling packet to the firmware was happening later as brcmfmac
>>> internally queues them and uses its own worker(s).
>>
>> That does not seem right. As soon as we get a 1x packet we need to wait
>> with key configuration regardless whether it is still in the driver or
>> handed over to firmware already.
>
> OK, thanks.
Actually, it's not OK. I was trying to report/describe/discuss this
problem for over a week. I couldn't get much of answer from you.
I had to come with a patch I worked on for quite some time. Only then
you decided to react and reply with a reason for a nack. I see this
patch may be wrong (but it's still hard to know what's going wrong
without a proper hostapd bug report). I'd expect you to somehow work &
communicate with open source community.
--=20
Rafa=C5=82
^ permalink raw reply
* Re: [PATCH] brcmfmac: implement more accurate skb tracking
From: Arend Van Spriel @ 2016-09-26 12:20 UTC (permalink / raw)
To: Rafał Miłecki
Cc: Kalle Valo, Franky Lin, Hante Meuleman, Pieter-Paul Giesberts,
Franky Lin, linux-wireless@vger.kernel.org,
open list:BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER,
Network Development, Linux Kernel Mailing List,
Rafał Miłecki
In-Reply-To: <CACna6rwnLb3sEPmdx6uhYMstVn04WbP2xzznsjnwgguEXn04=w@mail.gmail.com>
On 26-9-2016 14:13, Rafał Miłecki wrote:
> On 26 September 2016 at 13:46, Arend Van Spriel
> <arend.vanspriel@broadcom.com> wrote:
>> On 26-9-2016 12:23, Rafał Miłecki wrote:
>>> From: Rafał Miłecki <rafal@milecki.pl>
>>>
>>> We need to track 802.1x packets to know if there are any pending ones
>>> for transmission. This is required for performing key update in the
>>> firmware.
>>
>> The problem we are trying to solve is a pretty old one. The problem is
>> that wpa_supplicant uses two separate code paths: EAPOL messaging
>> through data path and key configuration though nl80211.
>
> Can I find it described/reported somewhere?
Not sure. It is something that I recall from working at Intersil so back
in the prism days.
Regards,
Arend
>>> Unfortunately our old tracking code wasn't very accurate. It was
>>> treating skb as pending as soon as it was passed by the netif. Actual
>>> handling packet to the firmware was happening later as brcmfmac
>>> internally queues them and uses its own worker(s).
>>
>> That does not seem right. As soon as we get a 1x packet we need to wait
>> with key configuration regardless whether it is still in the driver or
>> handed over to firmware already.
>
> OK, thanks.
>
^ permalink raw reply
* Re: [PATCH] brcmfmac: implement more accurate skb tracking
From: Rafał Miłecki @ 2016-09-26 12:13 UTC (permalink / raw)
To: Arend Van Spriel
Cc: Kalle Valo, Franky Lin, Hante Meuleman, Pieter-Paul Giesberts,
Franky Lin, linux-wireless@vger.kernel.org,
open list:BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER,
Network Development, Linux Kernel Mailing List,
Rafał Miłecki
In-Reply-To: <09084e8b-829d-9a13-ae16-a493438216ac@broadcom.com>
On 26 September 2016 at 13:46, Arend Van Spriel
<arend.vanspriel@broadcom.com> wrote:
> On 26-9-2016 12:23, Rafa=C5=82 Mi=C5=82ecki wrote:
>> From: Rafa=C5=82 Mi=C5=82ecki <rafal@milecki.pl>
>>
>> We need to track 802.1x packets to know if there are any pending ones
>> for transmission. This is required for performing key update in the
>> firmware.
>
> The problem we are trying to solve is a pretty old one. The problem is
> that wpa_supplicant uses two separate code paths: EAPOL messaging
> through data path and key configuration though nl80211.
Can I find it described/reported somewhere?
>> Unfortunately our old tracking code wasn't very accurate. It was
>> treating skb as pending as soon as it was passed by the netif. Actual
>> handling packet to the firmware was happening later as brcmfmac
>> internally queues them and uses its own worker(s).
>
> That does not seem right. As soon as we get a 1x packet we need to wait
> with key configuration regardless whether it is still in the driver or
> handed over to firmware already.
OK, thanks.
^ permalink raw reply
* Re: [PATCH] brcmfmac: implement more accurate skb tracking
From: Arend Van Spriel @ 2016-09-26 11:46 UTC (permalink / raw)
To: Rafał Miłecki, Kalle Valo
Cc: Franky Lin, Hante Meuleman, Pieter-Paul Giesberts, Franky Lin,
linux-wireless, brcm80211-dev-list.pdl, netdev, linux-kernel,
Rafał Miłecki
In-Reply-To: <20160926102348.8695-1-zajec5@gmail.com>
On 26-9-2016 12:23, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
>
> We need to track 802.1x packets to know if there are any pending ones
> for transmission. This is required for performing key update in the
> firmware.
The problem we are trying to solve is a pretty old one. The problem is
that wpa_supplicant uses two separate code paths: EAPOL messaging
through data path and key configuration though nl80211.
> Unfortunately our old tracking code wasn't very accurate. It was
> treating skb as pending as soon as it was passed by the netif. Actual
> handling packet to the firmware was happening later as brcmfmac
> internally queues them and uses its own worker(s).
That does not seem right. As soon as we get a 1x packet we need to wait
with key configuration regardless whether it is still in the driver or
handed over to firmware already.
Regards,
Arend
> Other than that it was hard to handle freeing packets. Everytime we had
> to determine (in more generic funcions) if packet was counted as pending
> 802.1x one or not. It was causing some problems, e.g. it wasn't clear if
> brcmf_flowring_delete should free skb directly or not.
>
> This patch introduces 2 separated functions for tracking skbs. This
> simplifies logic, fixes brcmf_flowring_delete (maybe other hidden bugs
> as well) and allows further simplifications. Thanks to better accuracy
> is also increases time window for key update (and lowers timeout risk).
>
> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
> ---
> This was successfully tested with 4366b1. Can someone give it a try with
> some USB/SDIO device, please?
> ---
> .../wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 11 +++++++
> .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 12 +++++++-
> .../wireless/broadcom/brcm80211/brcmfmac/core.c | 36 ++++++++++++++++------
> .../wireless/broadcom/brcm80211/brcmfmac/core.h | 2 ++
> .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 14 +++++++--
> .../wireless/broadcom/brcm80211/brcmfmac/proto.h | 11 +++++++
> .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 8 +++++
> .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 10 ++++++
> 8 files changed, 91 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
> index d1bc51f..3e40244 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
> @@ -326,6 +326,16 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
> return 0;
> }
>
> +static int brcmf_proto_bcdc_hdr_get_ifidx(struct brcmf_pub *drvr,
> + struct sk_buff *skb)
> +{
> + struct brcmf_proto_bcdc_header *h;
> +
> + h = (struct brcmf_proto_bcdc_header *)(skb->data);
> +
> + return BCDC_GET_IF_IDX(h);
> +}
> +
> static int
> brcmf_proto_bcdc_txdata(struct brcmf_pub *drvr, int ifidx, u8 offset,
> struct sk_buff *pktbuf)
> @@ -373,6 +383,7 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
> }
>
> drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull;
> + drvr->proto->hdr_get_ifidx = brcmf_proto_bcdc_hdr_get_ifidx;
> drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
> drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
> drvr->proto->txdata = brcmf_proto_bcdc_txdata;
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
> index 03404cb..fef9d02 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
> @@ -43,6 +43,7 @@
> #include "chip.h"
> #include "bus.h"
> #include "debug.h"
> +#include "proto.h"
> #include "sdio.h"
> #include "core.h"
> #include "common.h"
> @@ -772,6 +773,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
> int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,
> struct sk_buff_head *pktq)
> {
> + struct brcmf_pub *pub = sdiodev->bus_if->drvr;
> struct sk_buff *skb;
> u32 addr = sdiodev->sbwad;
> int err;
> @@ -784,10 +786,18 @@ int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,
>
> if (pktq->qlen == 1 || !sdiodev->sg_support)
> skb_queue_walk(pktq, skb) {
> + struct brcmf_if *ifp;
> + int ifidx;
> +
> + ifidx = brcmf_proto_hdr_get_ifidx(pub, skb);
> + ifp = brcmf_get_ifp(pub, ifidx);
> + brcmf_tx_passing_skb(ifp, skb);
> err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true,
> addr, skb);
> - if (err)
> + if (err) {
> + brcmf_tx_regained_skb(ifp, skb);
> break;
> + }
> }
> else
> err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, true, addr,
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
> index bc3d8ab..7cdc1f6 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
> @@ -247,9 +247,6 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
> goto done;
> }
>
> - if (eh->h_proto == htons(ETH_P_PAE))
> - atomic_inc(&ifp->pend_8021x_cnt);
> -
> /* determine the priority */
> if (skb->priority == 0 || skb->priority > 7)
> skb->priority = cfg80211_classify8021d(skb, NULL);
> @@ -388,20 +385,41 @@ void brcmf_rx_event(struct device *dev, struct sk_buff *skb)
> brcmu_pkt_buf_free_skb(skb);
> }
>
> -void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
> +/**
> + * brcmf_tx_passing_skb - Let core know skb is being passed to the firmware
> + *
> + * Core code needs to track state of some skbs. This function should be called
> + * every time skb is going to be passed to the firmware for transmitting.
> + */
> +void brcmf_tx_passing_skb(struct brcmf_if *ifp, struct sk_buff *skb)
> {
> - struct ethhdr *eh;
> - u16 type;
> + struct ethhdr *eh = (struct ethhdr *)(skb->data);
>
> - eh = (struct ethhdr *)(txp->data);
> - type = ntohs(eh->h_proto);
> + if (eh->h_proto == htons(ETH_P_PAE))
> + atomic_inc(&ifp->pend_8021x_cnt);
> +}
>
> - if (type == ETH_P_PAE) {
> +/**
> + * brcmf_tx_regained_skb - Let core know skb is not being fw processed anymore
> + *
> + * This function should be called every time skb is returned from the firmware
> + * processing for whatever reason. It usually happens after successful
> + * transmission but may be also due to some error.
> + */
> +void brcmf_tx_regained_skb(struct brcmf_if *ifp, struct sk_buff *skb)
> +{
> + struct ethhdr *eh = (struct ethhdr *)(skb->data);
> +
> + if (eh->h_proto == htons(ETH_P_PAE)) {
> atomic_dec(&ifp->pend_8021x_cnt);
> +
> if (waitqueue_active(&ifp->pend_8021x_wait))
> wake_up(&ifp->pend_8021x_wait);
> }
> +}
>
> +void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
> +{
> if (!success)
> ifp->stats.tx_errors++;
>
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
> index f16cfc9..80478b5 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
> @@ -215,6 +215,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
> void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked);
> void brcmf_txflowblock_if(struct brcmf_if *ifp,
> enum brcmf_netif_stop_reason reason, bool state);
> +void brcmf_tx_passing_skb(struct brcmf_if *ifp, struct sk_buff *skb);
> +void brcmf_tx_regained_skb(struct brcmf_if *ifp, struct sk_buff *skb);
> void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
> void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
> void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
> index 2b9a2bc..2a25eea 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
> @@ -701,17 +701,22 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
>
> count = BRCMF_MSGBUF_TX_FLUSH_CNT2 - BRCMF_MSGBUF_TX_FLUSH_CNT1;
> while (brcmf_flowring_qlen(flow, flowid)) {
> + u8 ifidx = brcmf_flowring_ifidx_get(flow, flowid);
> + struct brcmf_if *ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
> +
> skb = brcmf_flowring_dequeue(flow, flowid);
> if (skb == NULL) {
> brcmf_err("No SKB, but qlen %d\n",
> brcmf_flowring_qlen(flow, flowid));
> break;
> }
> + brcmf_tx_passing_skb(ifp, skb);
> skb_orphan(skb);
> if (brcmf_msgbuf_alloc_pktid(msgbuf->drvr->bus_if->dev,
> msgbuf->tx_pktids, skb, ETH_HLEN,
> &physaddr, &pktid)) {
> brcmf_flowring_reinsert(flow, flowid, skb);
> + brcmf_tx_regained_skb(ifp, skb);
> brcmf_err("No PKTID available !!\n");
> break;
> }
> @@ -720,6 +725,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
> brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
> msgbuf->tx_pktids, pktid);
> brcmf_flowring_reinsert(flow, flowid, skb);
> + brcmf_tx_regained_skb(ifp, skb);
> break;
> }
> count++;
> @@ -728,7 +734,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
>
> tx_msghdr->msg.msgtype = MSGBUF_TYPE_TX_POST;
> tx_msghdr->msg.request_id = cpu_to_le32(pktid);
> - tx_msghdr->msg.ifidx = brcmf_flowring_ifidx_get(flow, flowid);
> + tx_msghdr->msg.ifidx = ifidx;
> tx_msghdr->flags = BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3;
> tx_msghdr->flags |= (skb->priority & 0x07) <<
> BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT;
> @@ -857,6 +863,7 @@ brcmf_msgbuf_process_ioctl_complete(struct brcmf_msgbuf *msgbuf, void *buf)
> static void
> brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
> {
> + struct brcmf_if *ifp;
> struct brcmf_commonring *commonring;
> struct msgbuf_tx_status *tx_status;
> u32 idx;
> @@ -876,8 +883,9 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
> commonring = msgbuf->flowrings[flowid];
> atomic_dec(&commonring->outstanding_tx);
>
> - brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx),
> - skb, true);
> + ifp = brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx);
> + brcmf_tx_regained_skb(ifp, skb);
> + brcmf_txfinalize(ifp, skb, true);
> }
>
>
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
> index 57531f4..453cc5a 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
> @@ -16,6 +16,7 @@
> #ifndef BRCMFMAC_PROTO_H
> #define BRCMFMAC_PROTO_H
>
> +#include "core.h"
>
> enum proto_addr_mode {
> ADDR_INDIRECT = 0,
> @@ -29,6 +30,7 @@ struct brcmf_skb_reorder_data {
> struct brcmf_proto {
> int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
> struct sk_buff *skb, struct brcmf_if **ifp);
> + int (*hdr_get_ifidx)(struct brcmf_pub *drvr, struct sk_buff *skb);
> int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
> void *buf, uint len);
> int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
> @@ -64,6 +66,15 @@ static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
> ifp = &tmp;
> return drvr->proto->hdrpull(drvr, do_fws, skb, ifp);
> }
> +
> +static inline int brcmf_proto_hdr_get_ifidx(struct brcmf_pub *drvr,
> + struct sk_buff *skb)
> +{
> + if (!drvr->proto->hdr_get_ifidx)
> + return -ENOTSUPP;
> + return drvr->proto->hdr_get_ifidx(drvr, skb);
> +}
> +
> static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx,
> uint cmd, void *buf, uint len)
> {
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> index b892dac..4dc96bd 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> @@ -42,6 +42,7 @@
> #include "sdio.h"
> #include "chip.h"
> #include "firmware.h"
> +#include "proto.h"
> #include "core.h"
> #include "common.h"
>
> @@ -2240,6 +2241,7 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq)
> static int brcmf_sdio_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
> uint chan)
> {
> + struct brcmf_pub *pub = bus->sdiodev->bus_if->drvr;
> int ret;
> struct sk_buff *pkt_next, *tmp;
>
> @@ -2263,7 +2265,13 @@ done:
> if (ret == 0)
> bus->tx_seq = (bus->tx_seq + pktq->qlen) % SDPCM_SEQ_WRAP;
> skb_queue_walk_safe(pktq, pkt_next, tmp) {
> + struct brcmf_if *ifp;
> + int ifidx;
> +
> __skb_unlink(pkt_next, pktq);
> + ifidx = brcmf_proto_hdr_get_ifidx(pub, pkt_next);
> + ifp = brcmf_get_ifp(pub, ifidx);
> + brcmf_tx_regained_skb(ifp, pkt_next);
> brcmf_txcomplete(bus->sdiodev->dev, pkt_next, ret == 0);
> }
> return ret;
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
> index 2f978a3..d2f81c7 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
> @@ -26,6 +26,7 @@
> #include "bus.h"
> #include "debug.h"
> #include "firmware.h"
> +#include "proto.h"
> #include "usb.h"
> #include "core.h"
> #include "common.h"
> @@ -476,12 +477,16 @@ static void brcmf_usb_tx_complete(struct urb *urb)
> {
> struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
> struct brcmf_usbdev_info *devinfo = req->devinfo;
> + struct brcmf_pub *pub = devinfo->bus_pub.bus->drvr;
> + struct brcmf_if *ifp;
> unsigned long flags;
>
> brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status,
> req->skb);
> brcmf_usb_del_fromq(devinfo, req);
>
> + ifp = brcmf_get_ifp(pub, brcmf_proto_hdr_get_ifidx(pub, req->skb));
> + brcmf_tx_regained_skb(ifp, req->skb);
> brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0);
> req->skb = NULL;
> brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount);
> @@ -598,7 +603,9 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
> static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
> {
> struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
> + struct brcmf_pub *pub = devinfo->bus_pub.bus->drvr;
> struct brcmf_usbreq *req;
> + struct brcmf_if *ifp;
> int ret;
> unsigned long flags;
>
> @@ -622,6 +629,8 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
> skb->data, skb->len, brcmf_usb_tx_complete, req);
> req->urb->transfer_flags |= URB_ZERO_PACKET;
> brcmf_usb_enq(devinfo, &devinfo->tx_postq, req, NULL);
> + ifp = brcmf_get_ifp(pub, brcmf_proto_hdr_get_ifidx(pub, skb));
> + brcmf_tx_passing_skb(ifp, skb);
> ret = usb_submit_urb(req->urb, GFP_ATOMIC);
> if (ret) {
> brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n");
> @@ -629,6 +638,7 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
> req->skb = NULL;
> brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req,
> &devinfo->tx_freecount);
> + brcmf_tx_regained_skb(ifp, skb);
> goto fail;
> }
>
>
^ permalink raw reply
* Re: [PATCH 1/2] brcmfmac: initialize fws(ignal) for BCDC protocol only
From: Arend Van Spriel @ 2016-09-26 11:28 UTC (permalink / raw)
To: Rafał Miłecki, Kalle Valo
Cc: Franky Lin, Hante Meuleman, Pieter-Paul Giesberts, Franky Lin,
linux-wireless, brcm80211-dev-list.pdl, netdev, linux-kernel,
Rafał Miłecki
In-Reply-To: <20160924204419.10213-1-zajec5@gmail.com>
On 24-9-2016 22:44, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
>
> There are two protocols used by Broadcom FullMAC devices: BCDC and
> msgbuf. They use different ways for (some part of) communication with
> the firmware. Firmware Signaling is required for the first one only
> (BCDC).
>
> So far we were always initializing fws and always calling it's skb
> processing function. It was fws that was passing skb processing to the
> protocol specific function. It was redundant for the msgbuf case.
>
> Simply taking few lines of code out of fws allows us to totally avoid
> using it. This simplifies code flow, saves some memory & will allow
> further optimizations like not compiling fwsignal.c.
Hi Rafał,
Conceptually fwsignal is part of BCDC so you are indeed right when
saying it is not needed for msgbuf. The signalling is actually part of
the BCDC message overhead so I would rather see fwsignal only being used
in BCDC code. Could try and do that on top of this patch, but I would
prefer dropping these patches.
Regards,
Arend
> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
> ---
> .../wireless/broadcom/brcm80211/brcmfmac/core.c | 24 ++++++++++++++++------
> .../broadcom/brcm80211/brcmfmac/fwsignal.c | 17 ++++++---------
> .../broadcom/brcm80211/brcmfmac/fwsignal.h | 1 +
> 3 files changed, 25 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
> index 27cd50a..bc3d8ab 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
> @@ -250,7 +250,17 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
> if (eh->h_proto == htons(ETH_P_PAE))
> atomic_inc(&ifp->pend_8021x_cnt);
>
> - ret = brcmf_fws_process_skb(ifp, skb);
> + /* determine the priority */
> + if (skb->priority == 0 || skb->priority > 7)
> + skb->priority = cfg80211_classify8021d(skb, NULL);
> +
> + if (drvr->fws && brcmf_fws_skbs_queueing(drvr->fws)) {
> + ret = brcmf_fws_process_skb(ifp, skb);
> + } else {
> + ret = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
> + if (ret < 0)
> + brcmf_txfinalize(ifp, skb, false);
> + }
>
> done:
> if (ret) {
> @@ -405,7 +415,7 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
> struct brcmf_if *ifp;
>
> /* await txstatus signal for firmware if active */
> - if (brcmf_fws_fc_active(drvr->fws)) {
> + if (drvr->fws && brcmf_fws_fc_active(drvr->fws)) {
> if (!success)
> brcmf_fws_bustxfail(drvr->fws, txp);
> } else {
> @@ -1006,11 +1016,13 @@ int brcmf_bus_start(struct device *dev)
> }
> brcmf_feat_attach(drvr);
>
> - ret = brcmf_fws_init(drvr);
> - if (ret < 0)
> - goto fail;
> + if (bus_if->proto_type == BRCMF_PROTO_BCDC) {
> + ret = brcmf_fws_init(drvr);
> + if (ret < 0)
> + goto fail;
>
> - brcmf_fws_add_interface(ifp);
> + brcmf_fws_add_interface(ifp);
> + }
>
> drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev,
> drvr->settings->p2p_enable);
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
> index a190f53..495eaf8 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
> @@ -2100,16 +2100,6 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
> int rc = 0;
>
> brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto));
> - /* determine the priority */
> - if ((skb->priority == 0) || (skb->priority > 7))
> - skb->priority = cfg80211_classify8021d(skb, NULL);
> -
> - if (fws->avoid_queueing) {
> - rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
> - if (rc < 0)
> - brcmf_txfinalize(ifp, skb, false);
> - return rc;
> - }
>
> /* set control buffer information */
> skcb->if_flags = 0;
> @@ -2155,7 +2145,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
> struct brcmf_fws_info *fws = ifp->drvr->fws;
> struct brcmf_fws_mac_descriptor *entry;
>
> - if (!ifp->ndev)
> + if (!fws || !ifp->ndev)
> return;
>
> entry = &fws->desc.iface[ifp->ifidx];
> @@ -2442,6 +2432,11 @@ void brcmf_fws_deinit(struct brcmf_pub *drvr)
> kfree(fws);
> }
>
> +bool brcmf_fws_skbs_queueing(struct brcmf_fws_info *fws)
> +{
> + return !fws->avoid_queueing;
> +}
> +
> bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
> {
> if (!fws->creditmap_received)
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
> index ef0ad85..8f7c1d7 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
> @@ -20,6 +20,7 @@
>
> int brcmf_fws_init(struct brcmf_pub *drvr);
> void brcmf_fws_deinit(struct brcmf_pub *drvr);
> +bool brcmf_fws_skbs_queueing(struct brcmf_fws_info *fws);
> bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
> void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb);
> int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
>
^ permalink raw reply
* Re: [2/2] mwifiex: fix unaligned read in mwifiex_config_scan()
From: Kalle Valo @ 2016-09-26 11:19 UTC (permalink / raw)
To: Petri Gynther; +Cc: linux-wireless, davem, joe, akarwar, Petri Gynther
In-Reply-To: <1471057200-58166-2-git-send-email-pgynther@google.com>
Petri Gynther <pgynther@google.com> wrote:
> $ iwconfig mlan0 essid MySSID
> [ 36.930000] Path: /sbin/iwconfig
> [ 36.930000] CPU: 0 PID: 203 Comm: iwconfig Not tainted 4.7.0 #2
> [ 36.940000] task: 866f83a0 ti: 866a6000 task.ti: 866a6000
> [ 36.940000]
> [ECR ]: 0x00230400 => Misaligned r/w from 0x8677f403
> [ 36.960000] [EFA ]: 0x8677f403
> [ 36.960000] [BLINK ]: mwifiex_scan_networks+0x17a/0x198c [mwifiex]
> [ 36.960000] [ERET ]: mwifiex_scan_networks+0x18a/0x198c [mwifiex]
> [ 36.980000] [STAT32]: 0x00000206 : K E2 E1
> [ 36.980000] BTA: 0x700736e2 SP: 0x866a7d0c FP: 0x5faddc84
> [ 37.000000] LPS: 0x806a37ec LPE: 0x806a37fa LPC: 0x00000000
> [ 37.000000] r00: 0x8677f401 r01: 0x8668aa08 r02: 0x00000001
> r03: 0x00000000 r04: 0x8668b600 r05: 0x8677f406
> r06: 0x8702b600 r07: 0x00000000 r08: 0x8702b600
> r09: 0x00000000 r10: 0x870b3b00 r11: 0x00000000
> r12: 0x00000000
> [ 37.040000]
> [ 37.040000] Stack Trace:
> [ 37.040000] mwifiex_scan_networks+0x18a/0x198c [mwifiex]
>
> Root cause:
> mwifiex driver calls is_zero_ether_addr() against byte-aligned address:
>
> drivers/net/wireless/marvell/mwifiex/fw.h:
> struct mwifiex_scan_cmd_config {
> /*
> * BSS mode to be sent in the firmware command
> */
> u8 bss_mode;
>
> /* Specific BSSID used to filter scan results in the firmware */
> u8 specific_bssid[ETH_ALEN];
>
> ...
> } __packed;
>
> drivers/net/wireless/marvell/mwifiex/scan.c:
> mwifiex_config_scan(..., struct mwifiex_scan_cmd_config *scan_cfg_out, ...)
> ...
> if (adapter->ext_scan &&
> !is_zero_ether_addr(scan_cfg_out->specific_bssid)) {
> ...
> }
>
> Since firmware-related struct mwifiex_scan_cmd_config cannot be changed,
> we need to use the new function is_zero_ether_addr_unaligned() here.
>
> This is v2 of the original patch:
> [PATCH] Modify is_zero_ether_addr() to handle byte-aligned addresses
>
> Per Joe's suggestion -- instead of modifying is_zero_ether_addr() --
> add is_zero_ether_addr_unaligned() and use it where needed.
>
> Cc: Kalle Valo <kvalo@codeaurora.org>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Joe Perches <joe@perches.com>
> Cc: Amitkumar Karwar <akarwar@marvell.com>
> Signed-off-by: Petri Gynther <pgynther@google.com>
Patch set to Rejected.
Reason: As is_zero_ether_addr_unaligned() patch is not applied I can't take
this. Please resend if that patch is accepted.
--
https://patchwork.kernel.org/patch/9306999/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: pull-request: iwlwifi-next 2016-09-19-2
From: Kalle Valo @ 2016-09-26 11:12 UTC (permalink / raw)
To: Luca Coelho; +Cc: linux-wireless, linuxwifi
In-Reply-To: <1474275007.5664.96.camel@coelho.fi>
Luca Coelho <luca@coelho.fi> writes:
> Please drop my previous pull-request. =C2=A0There was a compilation error
> that I missed to due a missing flag in my .config. =C2=A0I fixed it now a=
nd
> this is the new pull request that includes the fix.
>
> Here we go again, now I'm almost catching up with the pending stuff in
> our internal tree, just in time for 4.9.=C2=A0=C2=A0This pull contains a =
bunch of
> fixes to DQA and new HW support code, a few new features and some
> cleanups.=C2=A0=C2=A0More details in the tag description.
>
> Let me know if everything's fine (or not). :)
>
> Luca.
>
>
> The following changes since commit 80ba4f1d365af206b9e818d17d22fed02fe5de=
f0:
>
> mwifiex: fix null pointer deference when adapter is null (2016-09-17 18=
:26:32 +0300)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git =
tags/iwlwifi-next-for-kalle-2016-09-19-2
Pulled, thanks.
--=20
Kalle Valo
^ permalink raw reply
* Re: [PATCH v2 RESEND] qtnfmac: announcement of new FullMAC driver for Quantenna chipsets
From: Kalle Valo @ 2016-09-26 10:56 UTC (permalink / raw)
To: IgorMitsyanko
Cc: johannes, linux-wireless, Avinash Patil, Dmitrii Lebed,
Sergei Maksimenko, Sergey Matyukevich, Bindu Therthala,
Huizhao Wang, Kamlesh Rath
In-Reply-To: <99f0c921-1230-0896-2bc5-4a12eb81dca1@quantenna.com>
IgorMitsyanko <igor.mitsyanko.os@quantenna.com> writes:
> On 09/17/2016 04:46 PM, Kalle Valo wrote:
>> <igor.mitsyanko.os@quantenna.com> writes:
>>
>>> +/* Supported rates to be advertised to the cfg80211 */
>>> +static struct ieee80211_rate qtnf_rates[] = {
>>> + {.bitrate = 10, .hw_value = 2, },
>>> + {.bitrate = 20, .hw_value = 4, },
>>> + {.bitrate = 55, .hw_value = 11, },
>>> + {.bitrate = 110, .hw_value = 22, },
>>> + {.bitrate = 60, .hw_value = 12, },
>>> + {.bitrate = 90, .hw_value = 18, },
>>> + {.bitrate = 120, .hw_value = 24, },
>>> + {.bitrate = 180, .hw_value = 36, },
>>> + {.bitrate = 240, .hw_value = 48, },
>>> + {.bitrate = 360, .hw_value = 72, },
>>> + {.bitrate = 480, .hw_value = 96, },
>>> + {.bitrate = 540, .hw_value = 108, },
>>> +};
>>> +
>>> +/* Channel definitions to be advertised to cfg80211 */
>>> +static struct ieee80211_channel qtnf_channels_2ghz[] = {
>>> + {.center_freq = 2412, .hw_value = 1, },
>>> + {.center_freq = 2417, .hw_value = 2, },
>>> + {.center_freq = 2422, .hw_value = 3, },
>>> + {.center_freq = 2427, .hw_value = 4, },
>>> + {.center_freq = 2432, .hw_value = 5, },
>>> + {.center_freq = 2437, .hw_value = 6, },
>>> + {.center_freq = 2442, .hw_value = 7, },
>>> + {.center_freq = 2447, .hw_value = 8, },
>>> + {.center_freq = 2452, .hw_value = 9, },
>>> + {.center_freq = 2457, .hw_value = 10, },
>>> + {.center_freq = 2462, .hw_value = 11, },
>>> + {.center_freq = 2467, .hw_value = 12, },
>>> + {.center_freq = 2472, .hw_value = 13, },
>>> + {.center_freq = 2484, .hw_value = 14, },
>>> +};
>> I guess some of these static variables could be also const, but didn't
>> check.
>
> We did some changes to this code recently: will get bands info
> (channel list, rates, capabilities etc) from wireless device itself,
> it will be in next patch revision.
For the initial submission please freeze the driver, otherwise it's pain
to review as the driver changes too much in-between review rounds. So at
this stage only minimal changes, please.
You can continue adding new features and making changes, but do those as
follow up patches and use the initial submission as the baseline for the
new patches. Once the driver is applied you can submit the rest of the
patches adding new features and they will be reviewed similarly like all
other wireless patches.
>>> +static int
>>> +qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
>>> + const struct qlink_event_sta_assoc *sta_assoc,
>>> + u16 len)
>>> +{
>>> + const u8 *sta_addr;
>>> + u16 frame_control;
>>> + struct station_info sinfo = { 0 };
>>> + size_t payload_len;
>>> + u16 tlv_type;
>>> + u16 tlv_value_len;
>>> + size_t tlv_full_len;
>>> + const struct qlink_tlv_hdr *tlv;
>>> +
>>> + if (unlikely(len < sizeof(*sta_assoc))) {
>>> + pr_err("%s: payload is too short (%u < %zu)\n", __func__,
>>> + len, sizeof(*sta_assoc));
>>> + return -EINVAL;
>>> + }
>>
>> I see unlikely() used a lot, I counted 145 times. Not a big issue but I
>> don't see the point. In hot path I understand using it, but not
>> everywhere.
>
> Agree, but would you suggest that we remove the ones that we already
> have but that are not really needed?
Up to you really. This isn't important, just something I found a bit
odd.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v2 RESEND] qtnfmac: announcement of new FullMAC driver for Quantenna chipsets
From: Kalle Valo @ 2016-09-26 10:45 UTC (permalink / raw)
To: IgorMitsyanko
Cc: johannes, linux-wireless, Avinash Patil, Dmitrii Lebed,
Sergei Maksimenko, Sergey Matyukevich, Bindu Therthala,
Huizhao Wang, Kamlesh Rath
In-Reply-To: <dfdaca87-dfbd-4677-fbff-45127ccd2e0c@quantenna.com>
IgorMitsyanko <igor.mitsyanko.os@quantenna.com> writes:
> On 09/17/2016 04:56 PM, Kalle Valo wrote:
>> <igor.mitsyanko.os@quantenna.com> writes:
>>
>>> +/* FW names */
>>> +
>>> +#define QTN_PCI_FW_NAME "pearl-linux.lzma.img"
>>
>> The firmware name gives no indication what this file is about (remember
>> that linux-firmware.git has a lot of files). Please name it properly,
>> don't just use what is used in by firmware build scripts :) Take into
>> account also future hw support, all firmware files need to coexist in
>> the same repository without user invention. In a way the firmware
>> filename is part of kernel/userspace interface and needs to be stable.
>>
>> For example, you could use something like "qtnfmac/qsr10g.img" (assuming
>> qsr10g is the name of chip).
>
> Ok, we will reconsider our naming conventions, take into account more
> devices that we need to support in the future.
> I'm thinking about something like:
> qtn/fmac_qsr10g.img <---- FullMAC QSR10G device
> qtn/fmac_qsr1000.img <---- FullMAC QSR1000 device
> qtn/smac_qsr10g.img <---- SoftMAC QSR10G
> qtn/smac_qsr10000.img <----- SoftMAC QSR1000
> etc
Looks good to me.
--
Kalle Valo
^ permalink raw reply
* [PATCH] rsi: update in vap_capabilities frame to device
From: Prameela Rani Garnepudi @ 2016-09-26 10:33 UTC (permalink / raw)
To: linux-wireless
Cc: kvalo, johannes.berg, hofrat, xypron.glpk, prameela.garnepudi,
Prameela Rani Garnepudi
added vap status(add/delete) field in vap capabilities frame to device
added sending vap capabilites frame(with vap status 'delete') in remove interface
Signed-off-by: Prameela Rani Garnepudi <prameela.j04cs@gmail.com>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 12 ++++++++----
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 8 ++++++--
drivers/net/wireless/rsi/rsi_mgmt.h | 9 ++++++++-
3 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index dbb2389..d5b17b1 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -304,13 +304,15 @@ static int rsi_mac80211_add_interface(struct ieee80211_hw *hw,
if (!adapter->sc_nvifs) {
++adapter->sc_nvifs;
adapter->vifs[0] = vif;
- ret = rsi_set_vap_capabilities(common, STA_OPMODE);
+ ret = rsi_set_vap_capabilities(common,
+ STA_OPMODE,
+ VAP_ADD);
}
break;
default:
rsi_dbg(ERR_ZONE,
- "%s: Interface type %d not supported\n", __func__,
- vif->type);
+ "%s: Interface type %d not supported\n",
+ __func__, vif->type);
}
mutex_unlock(&common->mutex);
@@ -332,8 +334,10 @@ static void rsi_mac80211_remove_interface(struct ieee80211_hw *hw,
struct rsi_common *common = adapter->priv;
mutex_lock(&common->mutex);
- if (vif->type == NL80211_IFTYPE_STATION)
+ if (vif->type == NL80211_IFTYPE_STATION) {
adapter->sc_nvifs--;
+ rsi_set_vap_capabilities(common, STA_OPMODE, VAP_DELETE);
+ }
if (!memcmp(adapter->vifs[0], vif, sizeof(struct ieee80211_vif)))
adapter->vifs[0] = NULL;
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 35c14cc..c41bb4f 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -617,7 +617,9 @@ static int rsi_program_bb_rf(struct rsi_common *common)
*
* Return: 0 on success, corresponding negative error code on failure.
*/
-int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode)
+int rsi_set_vap_capabilities(struct rsi_common *common,
+ enum opmode mode,
+ u8 vap_status)
{
struct sk_buff *skb = NULL;
struct rsi_vap_caps *vap_caps;
@@ -626,7 +628,8 @@ int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode)
struct ieee80211_conf *conf = &hw->conf;
u16 vap_id = 0;
- rsi_dbg(MGMT_TX_ZONE, "%s: Sending VAP capabilities frame\n", __func__);
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending VAP capabilities frame\n", __func__);
skb = dev_alloc_skb(sizeof(struct rsi_vap_caps));
if (!skb) {
@@ -642,6 +645,7 @@ int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode)
FRAME_DESC_SZ) |
(RSI_WIFI_MGMT_Q << 12));
vap_caps->desc_word[1] = cpu_to_le16(VAP_CAPABILITIES);
+ vap_caps->desc_word[2] = cpu_to_le16(vap_status << 8);
vap_caps->desc_word[4] = cpu_to_le16(mode |
(common->channel_width << 8));
vap_caps->desc_word[7] = cpu_to_le16((vap_id << 8) |
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 3741173..d155358 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -145,6 +145,12 @@ enum opmode {
AP_OPMODE = 2
};
+enum vap_status {
+ VAP_ADD = 1,
+ VAP_DELETE = 2,
+ VAP_UPDATE = 3
+};
+
extern struct ieee80211_rate rsi_rates[12];
extern const u16 rsi_mcsrates[8];
@@ -287,7 +293,8 @@ static inline u8 rsi_get_channel(u8 *addr)
}
int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg);
-int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode);
+int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode,
+ u8 vap_status);
int rsi_send_aggregation_params_frame(struct rsi_common *common, u16 tid,
u16 ssn, u8 buf_size, u8 event);
int rsi_hal_load_key(struct rsi_common *common, u8 *data, u16 key_len,
--
2.4.11
^ permalink raw reply related
* [PATCH] brcmfmac: implement more accurate skb tracking
From: Rafał Miłecki @ 2016-09-26 10:23 UTC (permalink / raw)
To: Kalle Valo
Cc: Arend van Spriel, Franky Lin, Hante Meuleman,
Pieter-Paul Giesberts, Franky Lin, linux-wireless,
brcm80211-dev-list.pdl, netdev, linux-kernel,
Rafał Miłecki
From: Rafał Miłecki <rafal@milecki.pl>
We need to track 802.1x packets to know if there are any pending ones
for transmission. This is required for performing key update in the
firmware.
Unfortunately our old tracking code wasn't very accurate. It was
treating skb as pending as soon as it was passed by the netif. Actual
handling packet to the firmware was happening later as brcmfmac
internally queues them and uses its own worker(s).
Other than that it was hard to handle freeing packets. Everytime we had
to determine (in more generic funcions) if packet was counted as pending
802.1x one or not. It was causing some problems, e.g. it wasn't clear if
brcmf_flowring_delete should free skb directly or not.
This patch introduces 2 separated functions for tracking skbs. This
simplifies logic, fixes brcmf_flowring_delete (maybe other hidden bugs
as well) and allows further simplifications. Thanks to better accuracy
is also increases time window for key update (and lowers timeout risk).
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
This was successfully tested with 4366b1. Can someone give it a try with
some USB/SDIO device, please?
---
.../wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 11 +++++++
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 12 +++++++-
.../wireless/broadcom/brcm80211/brcmfmac/core.c | 36 ++++++++++++++++------
.../wireless/broadcom/brcm80211/brcmfmac/core.h | 2 ++
.../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 14 +++++++--
.../wireless/broadcom/brcm80211/brcmfmac/proto.h | 11 +++++++
.../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 8 +++++
.../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 10 ++++++
8 files changed, 91 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
index d1bc51f..3e40244 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
@@ -326,6 +326,16 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
return 0;
}
+static int brcmf_proto_bcdc_hdr_get_ifidx(struct brcmf_pub *drvr,
+ struct sk_buff *skb)
+{
+ struct brcmf_proto_bcdc_header *h;
+
+ h = (struct brcmf_proto_bcdc_header *)(skb->data);
+
+ return BCDC_GET_IF_IDX(h);
+}
+
static int
brcmf_proto_bcdc_txdata(struct brcmf_pub *drvr, int ifidx, u8 offset,
struct sk_buff *pktbuf)
@@ -373,6 +383,7 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
}
drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull;
+ drvr->proto->hdr_get_ifidx = brcmf_proto_bcdc_hdr_get_ifidx;
drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
drvr->proto->txdata = brcmf_proto_bcdc_txdata;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 03404cb..fef9d02 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -43,6 +43,7 @@
#include "chip.h"
#include "bus.h"
#include "debug.h"
+#include "proto.h"
#include "sdio.h"
#include "core.h"
#include "common.h"
@@ -772,6 +773,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,
struct sk_buff_head *pktq)
{
+ struct brcmf_pub *pub = sdiodev->bus_if->drvr;
struct sk_buff *skb;
u32 addr = sdiodev->sbwad;
int err;
@@ -784,10 +786,18 @@ int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,
if (pktq->qlen == 1 || !sdiodev->sg_support)
skb_queue_walk(pktq, skb) {
+ struct brcmf_if *ifp;
+ int ifidx;
+
+ ifidx = brcmf_proto_hdr_get_ifidx(pub, skb);
+ ifp = brcmf_get_ifp(pub, ifidx);
+ brcmf_tx_passing_skb(ifp, skb);
err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true,
addr, skb);
- if (err)
+ if (err) {
+ brcmf_tx_regained_skb(ifp, skb);
break;
+ }
}
else
err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, true, addr,
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index bc3d8ab..7cdc1f6 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -247,9 +247,6 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
goto done;
}
- if (eh->h_proto == htons(ETH_P_PAE))
- atomic_inc(&ifp->pend_8021x_cnt);
-
/* determine the priority */
if (skb->priority == 0 || skb->priority > 7)
skb->priority = cfg80211_classify8021d(skb, NULL);
@@ -388,20 +385,41 @@ void brcmf_rx_event(struct device *dev, struct sk_buff *skb)
brcmu_pkt_buf_free_skb(skb);
}
-void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
+/**
+ * brcmf_tx_passing_skb - Let core know skb is being passed to the firmware
+ *
+ * Core code needs to track state of some skbs. This function should be called
+ * every time skb is going to be passed to the firmware for transmitting.
+ */
+void brcmf_tx_passing_skb(struct brcmf_if *ifp, struct sk_buff *skb)
{
- struct ethhdr *eh;
- u16 type;
+ struct ethhdr *eh = (struct ethhdr *)(skb->data);
- eh = (struct ethhdr *)(txp->data);
- type = ntohs(eh->h_proto);
+ if (eh->h_proto == htons(ETH_P_PAE))
+ atomic_inc(&ifp->pend_8021x_cnt);
+}
- if (type == ETH_P_PAE) {
+/**
+ * brcmf_tx_regained_skb - Let core know skb is not being fw processed anymore
+ *
+ * This function should be called every time skb is returned from the firmware
+ * processing for whatever reason. It usually happens after successful
+ * transmission but may be also due to some error.
+ */
+void brcmf_tx_regained_skb(struct brcmf_if *ifp, struct sk_buff *skb)
+{
+ struct ethhdr *eh = (struct ethhdr *)(skb->data);
+
+ if (eh->h_proto == htons(ETH_P_PAE)) {
atomic_dec(&ifp->pend_8021x_cnt);
+
if (waitqueue_active(&ifp->pend_8021x_wait))
wake_up(&ifp->pend_8021x_wait);
}
+}
+void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
+{
if (!success)
ifp->stats.tx_errors++;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index f16cfc9..80478b5 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -215,6 +215,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked);
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
+void brcmf_tx_passing_skb(struct brcmf_if *ifp, struct sk_buff *skb);
+void brcmf_tx_regained_skb(struct brcmf_if *ifp, struct sk_buff *skb);
void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index 2b9a2bc..2a25eea 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -701,17 +701,22 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
count = BRCMF_MSGBUF_TX_FLUSH_CNT2 - BRCMF_MSGBUF_TX_FLUSH_CNT1;
while (brcmf_flowring_qlen(flow, flowid)) {
+ u8 ifidx = brcmf_flowring_ifidx_get(flow, flowid);
+ struct brcmf_if *ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
+
skb = brcmf_flowring_dequeue(flow, flowid);
if (skb == NULL) {
brcmf_err("No SKB, but qlen %d\n",
brcmf_flowring_qlen(flow, flowid));
break;
}
+ brcmf_tx_passing_skb(ifp, skb);
skb_orphan(skb);
if (brcmf_msgbuf_alloc_pktid(msgbuf->drvr->bus_if->dev,
msgbuf->tx_pktids, skb, ETH_HLEN,
&physaddr, &pktid)) {
brcmf_flowring_reinsert(flow, flowid, skb);
+ brcmf_tx_regained_skb(ifp, skb);
brcmf_err("No PKTID available !!\n");
break;
}
@@ -720,6 +725,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
msgbuf->tx_pktids, pktid);
brcmf_flowring_reinsert(flow, flowid, skb);
+ brcmf_tx_regained_skb(ifp, skb);
break;
}
count++;
@@ -728,7 +734,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
tx_msghdr->msg.msgtype = MSGBUF_TYPE_TX_POST;
tx_msghdr->msg.request_id = cpu_to_le32(pktid);
- tx_msghdr->msg.ifidx = brcmf_flowring_ifidx_get(flow, flowid);
+ tx_msghdr->msg.ifidx = ifidx;
tx_msghdr->flags = BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3;
tx_msghdr->flags |= (skb->priority & 0x07) <<
BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT;
@@ -857,6 +863,7 @@ brcmf_msgbuf_process_ioctl_complete(struct brcmf_msgbuf *msgbuf, void *buf)
static void
brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
{
+ struct brcmf_if *ifp;
struct brcmf_commonring *commonring;
struct msgbuf_tx_status *tx_status;
u32 idx;
@@ -876,8 +883,9 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
commonring = msgbuf->flowrings[flowid];
atomic_dec(&commonring->outstanding_tx);
- brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx),
- skb, true);
+ ifp = brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx);
+ brcmf_tx_regained_skb(ifp, skb);
+ brcmf_txfinalize(ifp, skb, true);
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
index 57531f4..453cc5a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
@@ -16,6 +16,7 @@
#ifndef BRCMFMAC_PROTO_H
#define BRCMFMAC_PROTO_H
+#include "core.h"
enum proto_addr_mode {
ADDR_INDIRECT = 0,
@@ -29,6 +30,7 @@ struct brcmf_skb_reorder_data {
struct brcmf_proto {
int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
struct sk_buff *skb, struct brcmf_if **ifp);
+ int (*hdr_get_ifidx)(struct brcmf_pub *drvr, struct sk_buff *skb);
int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
void *buf, uint len);
int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
@@ -64,6 +66,15 @@ static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
ifp = &tmp;
return drvr->proto->hdrpull(drvr, do_fws, skb, ifp);
}
+
+static inline int brcmf_proto_hdr_get_ifidx(struct brcmf_pub *drvr,
+ struct sk_buff *skb)
+{
+ if (!drvr->proto->hdr_get_ifidx)
+ return -ENOTSUPP;
+ return drvr->proto->hdr_get_ifidx(drvr, skb);
+}
+
static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx,
uint cmd, void *buf, uint len)
{
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index b892dac..4dc96bd 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -42,6 +42,7 @@
#include "sdio.h"
#include "chip.h"
#include "firmware.h"
+#include "proto.h"
#include "core.h"
#include "common.h"
@@ -2240,6 +2241,7 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq)
static int brcmf_sdio_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
uint chan)
{
+ struct brcmf_pub *pub = bus->sdiodev->bus_if->drvr;
int ret;
struct sk_buff *pkt_next, *tmp;
@@ -2263,7 +2265,13 @@ done:
if (ret == 0)
bus->tx_seq = (bus->tx_seq + pktq->qlen) % SDPCM_SEQ_WRAP;
skb_queue_walk_safe(pktq, pkt_next, tmp) {
+ struct brcmf_if *ifp;
+ int ifidx;
+
__skb_unlink(pkt_next, pktq);
+ ifidx = brcmf_proto_hdr_get_ifidx(pub, pkt_next);
+ ifp = brcmf_get_ifp(pub, ifidx);
+ brcmf_tx_regained_skb(ifp, pkt_next);
brcmf_txcomplete(bus->sdiodev->dev, pkt_next, ret == 0);
}
return ret;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
index 2f978a3..d2f81c7 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -26,6 +26,7 @@
#include "bus.h"
#include "debug.h"
#include "firmware.h"
+#include "proto.h"
#include "usb.h"
#include "core.h"
#include "common.h"
@@ -476,12 +477,16 @@ static void brcmf_usb_tx_complete(struct urb *urb)
{
struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
struct brcmf_usbdev_info *devinfo = req->devinfo;
+ struct brcmf_pub *pub = devinfo->bus_pub.bus->drvr;
+ struct brcmf_if *ifp;
unsigned long flags;
brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status,
req->skb);
brcmf_usb_del_fromq(devinfo, req);
+ ifp = brcmf_get_ifp(pub, brcmf_proto_hdr_get_ifidx(pub, req->skb));
+ brcmf_tx_regained_skb(ifp, req->skb);
brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0);
req->skb = NULL;
brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount);
@@ -598,7 +603,9 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
{
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+ struct brcmf_pub *pub = devinfo->bus_pub.bus->drvr;
struct brcmf_usbreq *req;
+ struct brcmf_if *ifp;
int ret;
unsigned long flags;
@@ -622,6 +629,8 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
skb->data, skb->len, brcmf_usb_tx_complete, req);
req->urb->transfer_flags |= URB_ZERO_PACKET;
brcmf_usb_enq(devinfo, &devinfo->tx_postq, req, NULL);
+ ifp = brcmf_get_ifp(pub, brcmf_proto_hdr_get_ifidx(pub, skb));
+ brcmf_tx_passing_skb(ifp, skb);
ret = usb_submit_urb(req->urb, GFP_ATOMIC);
if (ret) {
brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n");
@@ -629,6 +638,7 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
req->skb = NULL;
brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req,
&devinfo->tx_freecount);
+ brcmf_tx_regained_skb(ifp, skb);
goto fail;
}
--
2.9.3
^ permalink raw reply related
* RE: [PATCH] realtek: Add switch variable to 'switch case not processed' messages
From: David Laight @ 2016-09-26 9:33 UTC (permalink / raw)
To: 'Joe Perches', Jean Delvare
Cc: Larry Finger, Chaoming Li, Kalle Valo,
linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <1474733754.23838.3.camel@perches.com>
> If you want to create enum->#ENUM structs and
> "const char *" lookup functions, please be my guest.
>
> otherwise, hex is at least a consistent way to display
> what should be infrequent output.
If I've typed it right:
#define tags(x) x(A) x(B) x(C)
#define x(t) t,
enum {tags(x) tag_count};
#undef x
#define x(t) ##t,
static const char names[] = { tags(x) };
#undef x
David
^ permalink raw reply
* RE: [PATCH 2/2] mwifiex: firmware name correction for usb8997 chipset
From: Amitkumar Karwar @ 2016-09-26 9:01 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless@vger.kernel.org, Ganapathi Bhat
In-Reply-To: <87wphzyr7e.fsf@kamboji.qca.qualcomm.com>
Hi Kalle,
> From: Kalle Valo [mailto:kvalo@codeaurora.org]
> Sent: Monday, September 26, 2016 2:27 PM
> To: Amitkumar Karwar
> Cc: linux-wireless@vger.kernel.org; Ganapathi Bhat
> Subject: Re: [PATCH 2/2] mwifiex: firmware name correction for usb8997
> chipset
>
> Amitkumar Karwar <akarwar@marvell.com> writes:
>
> >> Like discussed earlier, the firmware names are supposed to be stable.
> >> I consider them to be an interface between kernel and user space.
> >> Instead of changing the driver you should actually rename the
> >> firmware file. I'm planning to take this anyway but in the future
> >> please pay extra attention to do this properly.
> >
> > Thanks for accepting the patch. We will stick to the same name for
> > 8997 and ensure v3/v4 etc won't be used for future chipsets/firmwares.
>
> Good, thanks.
>
> >> My recommendation is to keep the firmware name simple as possible and
> >> get rid of any extra cruft, for example in this case a good name
> >> would be "mrvl/usb8997.bin". That extra "usb" and "combo_v4" don't
> >> bring any benefit.
> >>
> >
> > 'combo' here indicates it's a combine firmware image for bluetooth and
> > wifi. Firmware images with bluetooth only OR WiFi only functionality
> > are also possible. Example use case: We support PCIe function level
> > reset feature as a recovery mechanism. With this mechanism, WiFi
> > recovery can happen by re-downloading WiFi only firmware without
> > affecting bluetooth functionality for PCIe-USB8997 chipset.
>
> Ok, makes sense.
>
> > 'usbusb' here indicates this firmware is for a USB-USB8997 chipset
> > where WiFi and bluetooth are over USB bus. There would be a different
> > firmware if chipset is USB-UART8997 where bluetooth is via UART.
>
> So the bluetooth via UART chip would be 'usbuart'? Sounds reasonable
> then.
>
Right. 'usbuart' string would be used in firmware name for USB-UART8997 where bluetooth is via uart.
Regards,
Amitkumar Karwar
^ permalink raw reply
* Re: [PATCH 2/2] mwifiex: firmware name correction for usb8997 chipset
From: Kalle Valo @ 2016-09-26 8:56 UTC (permalink / raw)
To: Amitkumar Karwar; +Cc: linux-wireless@vger.kernel.org, Ganapathi Bhat
In-Reply-To: <3ca1064a85854ba9b7f5e6b5ef127726@SC-EXCH04.marvell.com>
Amitkumar Karwar <akarwar@marvell.com> writes:
>> Like discussed earlier, the firmware names are supposed to be stable. I
>> consider them to be an interface between kernel and user space. Instead
>> of changing the driver you should actually rename the firmware file. I'm
>> planning to take this anyway but in the future please pay extra
>> attention to do this properly.
>
> Thanks for accepting the patch. We will stick to the same name for
> 8997 and ensure v3/v4 etc won't be used for future chipsets/firmwares.
Good, thanks.
>> My recommendation is to keep the firmware name simple as possible and
>> get rid of any extra cruft, for example in this case a good name would
>> be "mrvl/usb8997.bin". That extra "usb" and "combo_v4" don't bring any
>> benefit.
>>
>
> 'combo' here indicates it's a combine firmware image for bluetooth and
> wifi. Firmware images with bluetooth only OR WiFi only functionality
> are also possible. Example use case: We support PCIe function level
> reset feature as a recovery mechanism. With this mechanism, WiFi
> recovery can happen by re-downloading WiFi only firmware without
> affecting bluetooth functionality for PCIe-USB8997 chipset.
Ok, makes sense.
> 'usbusb' here indicates this firmware is for a USB-USB8997 chipset
> where WiFi and bluetooth are over USB bus. There would be a different
> firmware if chipset is USB-UART8997 where bluetooth is via UART.
So the bluetooth via UART chip would be 'usbuart'? Sounds reasonable
then.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH 10/25] iwlwifi: mvm: support packet injection
From: Kalle Valo @ 2016-09-26 8:52 UTC (permalink / raw)
To: Sharon, Sara; +Cc: Luca Coelho, linux-wireless@vger.kernel.org, Coelho, Luciano
In-Reply-To: <84271B8B681983469E84120965EB1B0434D68BCA@HASMSX106.ger.corp.intel.com>
"Sharon, Sara" <sara.sharon@intel.com> writes:
>> The commit log doesn't tell a lot. I started to wonder why use
>> debugfs and not the proper interface through mac80211?
>
> This is RX packet injection, not TX. So the injection goes up - from
> the driver to mac80211. Since we use it to test some mvm data path
> stuff, we don't want to inject at mac80211 level.
>
>> But reading from the code makes me suspect that this isn't really
>> normal packet injection, more like passing full descriptors to the
>> hw. Did I understand correctly?
>
> For injecting at driver level we need the injected packet to contain a
> fake of the HW descriptor for the driver processing. This descriptor
> isn't being passed to the hw, but to the driver since it is RX. The
> code isn't creating the descriptor, but it is validating length and
> other checks to make sure we won't access invalid memory or so.
Ah, makes sense. No need to resend this, but in the future please try to
explain higher level design like this in the commit log. That avoids a
lot of guessing (wrong) for me and others.
--
Kalle Valo
^ permalink raw reply
* RE: [PATCH 10/25] iwlwifi: mvm: support packet injection
From: Sharon, Sara @ 2016-09-26 8:10 UTC (permalink / raw)
To: 'Kalle Valo', Luca Coelho
Cc: linux-wireless@vger.kernel.org, Coelho, Luciano
In-Reply-To: <87oa3d1r5h.fsf@kamboji.qca.qualcomm.com>
> The commit log doesn't tell a lot. I started to wonder why use debugfs and not the proper interface through mac80211?
This is RX packet injection, not TX. So the injection goes up - from the driver to mac80211.
Since we use it to test some mvm data path stuff, we don't want to inject at mac80211 level.
> But reading from the code makes me suspect that this isn't really normal packet injection, more like passing full descriptors to the hw. Did I understand correctly?
For injecting at driver level we need the injected packet to contain a fake of the HW descriptor for the driver processing.
This descriptor isn't being passed to the hw, but to the driver since it is RX.
The code isn't creating the descriptor, but it is validating length and other checks to make sure we won't access invalid memory or so.
Sara
---------------------------------------------------------------------
A member of the Intel Corporation group of companies
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply
* Re: wifi test automation?
From: Kalle Valo @ 2016-09-26 8:01 UTC (permalink / raw)
To: Oleksij Rempel; +Cc: linux-wireless
In-Reply-To: <ea8a3e16-53d9-4637-fdcb-e68829a82f06@gmx.net>
Oleksij Rempel <fishor@gmx.net> writes:
> What kind of WiFi testomation are you using?
>
> Right now i found some links, do some of this used by WiFi devs?
> http://avocado-framework.github.io/
> https://autotest.github.io/
> https://github.com/Wi-FiTestSuite
> https://wireless.wiki.kernel.org/en/developers/testing/wifi-test
If I had some free time I would like to try out hostap's test framework
with remote hosts. I find it very promising:
http://w1.fi/cgit/hostap/commit/?id=5865186e311b626ad155123f40f837b562ea14ef
--
Kalle Valo
^ permalink raw reply
* Re: staging: wilc1000: kernel Oops while opening the device
From: Aditya.Shankar @ 2016-09-26 5:17 UTC (permalink / raw)
To: gregkh; +Cc: Ganesh.Krishna, nicolas.ferre, linux-wireless, luisbg
In-Reply-To: <20160923150734.GB13933@kroah.com>
On Friday 23 September 2016 08:37 PM, Greg KH wrote:
> On Fri, Sep 23, 2016 at 01:17:08PM +0000, Aditya.Shankar@microchip.com wrote:
>> On Thursday 22 September 2016 06:04 PM, Ganesh Krishna - I00112 wrote:
>>>> -----Original Message-----
>>>> From: Greg Kroah-Hartman [mailto:gregkh@linuxfoundation.org]
>>>> Sent: Monday, September 19, 2016 7:12 PM
>>>> To: Nicolas Ferre
>>>> Cc: linux-wireless@vger.kernel.org; Aditya Shankar - I16078; Ganesh Krishna - I00112; luisbg@osg.samsung.com
>>>> Subject: Re: staging: wilc1000: kernel Oops while opening the device
>>>>
>>>> On Mon, Sep 19, 2016 at 02:06:02PM +0200, Nicolas Ferre wrote:
>>>>> Hi all,
>>>>>
>>>>> While using the wilc1000 driver with latest 4.8-rc7, I have
>>>>> difficulties to open the device and actually use it as I have this
>>>>> kernel Oops right after the loading of the firmware (wilc1003_firmware.bin).
>>>>>
>>>>> If I revert back the driver to its
>>>>> b9811891a9f60ca9c314dcab3244c65930c4cf37 state, it works okay. I did
>>>>> this because I tend to think that it might be related to the latest move on this driver to "completion" or "work queues".
>>>>> It seems to be a regression from 4.7.
>>>>
>>>> Ick, not good at all.
>>>>
>>>> Any chance you can run 'git bisect' to see if you can find the offending patch?
>>>>
>>>> I thought the maintainers were testing this driver over time :(
>>>
>>>> thanks,
>>>>
>>>> greg k-h
>>>
>>> Ick indeed. Maintainers are on it full time. Thank you very much for the flag. While I am only reporting activity, hope to have results soon.
>>> Regards,
>>> ganesh k
>>>
>> Hi All,
>>
>> bisecting changes on the wilc1000 host driver, I find that this problem seems to occur after the below change.
>> As of now, I only know the where and not the why. So I will continue to figure out why this happens.
>>
>> commit 2518ac59eb27ed003c5a97e8f9588adafdfe4a8a
>> Author: Binoy Jayan <binoy.jayan@linaro.org>
>> Date: Thu Jun 23 11:11:51 2016 +0530
>>
>> staging: wilc1000: Replace kthread with workqueue for host interface
>>
>> Deconstruct the kthread / message_queue logic, replacing it with
>> create_singlethread_workqueue() / queue_work() setup, by adding a
>> 'struct work_struct' to 'struct host_if_msg'. The current kthread
>> hostIFthread() is converted to a work queue helper with the name
>> 'host_if_work'.
>
> So if you revert this, it works?
>
> If so, let us know and I will gladly revert it, as breaking things is
> not ok.
>
> thanks,
>
> greg k-h
>
Unfortunately no. We will have to revert this commit and the one submitted after this.
The commit a5c84b2 after 2518ac5 is heavily reliant on its parent 2518ac5.
Note that reverting 2518ac5 throws up a couple of minor merge conflicts which can be
resolved by dropping changes in HEAD and retaining the parent commit of 2518ac5.
With this, the crash is not seen anymore.
Thanks!
Aditya
^ permalink raw reply
* RTL8192CU: about trivial change of removing some 8192c declaration from header file
From: Xuebing Wang @ 2016-09-26 1:55 UTC (permalink / raw)
To: Larry Finger, Chaoming Li; +Cc: linux-wireless
Hi Larry and Chaoming:
I am trying to do User Mode driver for RTL8192CU (device is Alfa
AWUS036NHR which is 802.11 b/g/n), and I am reading RTL8192CU / RTL8192C
/ RTLWIFI driver source code.
There is a very trivial error that below declarations (in
rtl8192cu/hw.h) are already in file
drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h
---
int rtl92c_download_fw(struct ieee80211_hw *hw);
void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
u8 element_id, u32 cmd_len, u8 *p_cmdbuffer);
---
Does it make sense for me to submit a trivial patch to remove these
declarations from rtl8192cu/hw.h?
Thanks.
xuebing
^ permalink raw reply
* Re: ath10k mesh + ap + encryption?
From: Simon Wunderlich @ 2016-09-25 20:16 UTC (permalink / raw)
To: Pedersen, Thomas
Cc: ath10k@lists.infradead.org, Valo, Kalle, Martin Blumenstingl,
openwrt-devel@lists.openwrt.org, linux-wireless@vger.kernel.org
In-Reply-To: <1474669037.16013.9.camel@qca.qualcomm.com>
[-- Attachment #1: Type: text/plain, Size: 1609 bytes --]
On Friday, September 23, 2016 10:18:49 PM CEST Pedersen, Thomas wrote:
> On Mon, 2016-09-19 at 08:43 +0200, Simon Wunderlich wrote:
>
> > On Tuesday, September 13, 2016 5:54:38 PM CEST Pedersen, Thomas wrote:
> >
> > > On Tue, 2016-09-13 at 14:30 +0200, Simon Wunderlich wrote:
> > >
> > >
> > > > [...]
> > > >
> > > >
> > > >
> > > > Thanks for the clarification. We will then stick to the 70's branch
> > > > then.
> > > >
> > > > Does anyone have pointers for the other questions? :) I would believe
> > > > hat many
> > > > people would be interested in running AP + Mesh encrypted at the same
> > > > time (at
> > > > least in the open source community ...).
> > >
> > >
> > >
> > > We're testing encrypted AP + Mesh quite successfully right now with
> > > this firmware: https://github.com/kvalo/ath10k-firmware/commit/307cb46b
> > > 06661ebd3186723b5002de769c7add83, of course that is for a QCA4019 chip.
> > > Which chip are you using? I can poke the firmware guys for possibility
> > > of getting a 10.4.3.2 firmware build for it.
> >
> >
> > Hi Thomas,
> >
> > thanks for the hint! We are using an older QCA9882. I assume your firmware
> > will
not work for this one? If you can poke the firmware guys, that
> > would be great.>
> > :)
>
>
> Hi Simon,
>
> According to firmware guys the latest code can actually compile down to
> any chipset, so it should simply be a matter of getting builds released.
Hi Thomas,
thats great news, thanks for the heads up!
How are we going to get those builds released? Who can I ask, or do you want
to take care of that?
Thanks,
Simon
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* [PATCH 1/3] mac80211: filter multicast data packets on AP / AP_VLAN
From: Michael Braun @ 2016-09-25 16:39 UTC (permalink / raw)
To: johannes; +Cc: Michael Braun, linux-wireless
In-Reply-To: <1474821596-12155-1-git-send-email-michael-dev@fami-braun.de>
This patch adds filtering for multicast data packets on AP_VLAN interfaces that
have no authorized station connected and changes filtering on AP interfaces to
not count stations assigned to AP_VLAN interfaces.
This saves airtime and avoids waking up other stations currently authorized in
this BSS. When using WPA, the packets dropped could not be decrypted by any
station.
The behaviour when there are no AP_VLAN interfaces is left unchanged.
When there are AP_VLAN interfaces, this patch
1. adds filtering multicast data packets sent on AP_VLAN interfaces that
have no authorized station connected.
No filtering happens on 4addr AP_VLAN interfaces.
2. makes filtering of multicast data packets sent on AP interfaces depend on
the number of authorized stations in this bss not assigned to an AP_VLAN
interface.
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.
The new counters are exposed in debugfs.
Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
--
v2:
- use separate function to inc/dec mcast_sta counters
- do not filter in 4addr mode
- change description
- change filtering on AP interface (do not count AP_VLAN sta)
- use new counters regardless of 4addr or not
- simplify cfg.c:change_station
- remove no-op change in __cleanup_single_sta
---
net/mac80211/cfg.c | 20 +++++-----------
net/mac80211/debugfs_netdev.c | 11 +++++++++
net/mac80211/ieee80211_i.h | 54 +++++++++++++++++++++++++++++++++++++++++++
net/mac80211/rx.c | 5 ++--
net/mac80211/sta_info.c | 10 ++------
net/mac80211/tx.c | 5 ++--
6 files changed, 78 insertions(+), 27 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 543b1d4..078e837 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1357,9 +1357,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,
goto out_err;
if (params->vlan && params->vlan != sta->sdata->dev) {
- bool prev_4addr = false;
- bool new_4addr = false;
-
vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
if (params->vlan->ieee80211_ptr->use_4addr) {
@@ -1369,26 +1366,21 @@ static int ieee80211_change_station(struct wiphy *wiphy,
}
rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
- new_4addr = true;
__ieee80211_check_fast_rx_iface(vlansdata);
}
if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- sta->sdata->u.vlan.sta) {
+ sta->sdata->u.vlan.sta)
RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL);
- prev_4addr = true;
- }
+
+ if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+ ieee80211_vif_dec_num_mcast(sta->sdata);
sta->sdata = vlansdata;
ieee80211_check_fast_xmit(sta);
- if (sta->sta_state == IEEE80211_STA_AUTHORIZED &&
- prev_4addr != new_4addr) {
- if (new_4addr)
- atomic_dec(&sta->sdata->bss->num_mcast_sta);
- else
- atomic_inc(&sta->sdata->bss->num_mcast_sta);
- }
+ if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+ ieee80211_vif_inc_num_mcast(sta->sdata);
ieee80211_send_layer2_update(sta);
}
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index a5ba739..d97756d 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -477,6 +477,8 @@ IEEE80211_IF_FILE_RW(tdls_wider_bw);
IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC);
IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC);
IEEE80211_IF_FILE(dtim_count, u.ap.ps.dtim_count, DEC);
+IEEE80211_IF_FILE(num_mcast_sta_vlan_if, u.vlan.num_mcast_sta_if, ATOMIC);
+IEEE80211_IF_FILE(num_mcast_sta_novlan_if, u.ap.num_mcast_sta_if, ATOMIC);
static ssize_t ieee80211_if_fmt_num_buffered_multicast(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
@@ -636,6 +638,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
static void add_ap_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(num_mcast_sta);
+ DEBUGFS_ADD(num_mcast_sta_novlan_if);
DEBUGFS_ADD_MODE(smps, 0600);
DEBUGFS_ADD(num_sta_ps);
DEBUGFS_ADD(dtim_count);
@@ -643,6 +646,11 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
}
+static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_ADD(num_mcast_sta_vlan_if);
+}
+
static void add_ibss_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD_MODE(tsf, 0600);
@@ -746,6 +754,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
case NL80211_IFTYPE_AP:
add_ap_files(sdata);
break;
+ case NL80211_IFTYPE_AP_VLAN:
+ add_vlan_files(sdata);
+ break;
case NL80211_IFTYPE_WDS:
add_wds_files(sdata);
break;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f56d342..b10e8be 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -289,6 +289,7 @@ struct ieee80211_if_ap {
struct ps_data ps;
atomic_t num_mcast_sta; /* number of stations receiving multicast */
+ atomic_t num_mcast_sta_if; /* num_mcast_sta w/o sta in AP_VLAN */
enum ieee80211_smps_mode req_smps, /* requested smps mode */
driver_smps_mode; /* smps mode request */
@@ -305,6 +306,7 @@ struct ieee80211_if_vlan {
/* used for all tx if the VLAN is configured to 4-addr mode */
struct sta_info __rcu *sta;
+ atomic_t num_mcast_sta_if; /* number of stations receiving multicast */
};
struct mesh_stats {
@@ -1496,6 +1498,58 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status)
return false;
}
+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;
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
+ atomic_inc(&sdata->u.ap.num_mcast_sta_if);
+ else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ atomic_inc(&sdata->u.vlan.num_mcast_sta_if);
+
+ if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN ||
+ !sdata->u.vlan.sta) /* except 4addr mode */
+ atomic_inc(&sdata->bss->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_if);
+ else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ atomic_dec(&sdata->u.vlan.num_mcast_sta_if);
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+ sdata->u.vlan.sta)
+ return; /* 4addr mode */
+
+ atomic_dec(&sdata->bss->num_mcast_sta);
+}
+
+/**
+ * @returns number of multicast stations connected
+ * -1 if unsupported (no-AP, 4addr mode)
+ */
+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_if);
+ else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+ !sdata->u.vlan.sta)
+ return atomic_read(&sdata->u.vlan.num_mcast_sta_if);
+ else
+ return -1;
+}
+
u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
struct ieee80211_rx_status *status,
unsigned int mpdu_len,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9dce3b1..4c6adc9 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2160,7 +2160,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
- if (is_multicast_ether_addr(ehdr->h_dest)) {
+ if (is_multicast_ether_addr(ehdr->h_dest) &&
+ ieee80211_vif_get_num_mcast_if(sdata) != 0) {
/*
* send multicast frames both to higher layers in
* local net stack and back to the wireless medium
@@ -2169,7 +2170,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
if (!xmit_skb)
net_info_ratelimited("%s: failed to clone multicast frame\n",
dev->name);
- } else {
+ } else if (!is_multicast_ether_addr(ehdr->h_dest)) {
dsta = sta_info_get(sdata, skb->data);
if (dsta) {
/*
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 76b737d..216ef65 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1882,10 +1882,7 @@ int sta_info_move_state(struct sta_info *sta,
if (!sta->sta.support_p2p_ps)
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
} else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
- if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
- (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- !sta->sdata->u.vlan.sta))
- atomic_dec(&sta->sdata->bss->num_mcast_sta);
+ ieee80211_vif_dec_num_mcast(sta->sdata);
clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
ieee80211_clear_fast_xmit(sta);
ieee80211_clear_fast_rx(sta);
@@ -1893,10 +1890,7 @@ int sta_info_move_state(struct sta_info *sta,
break;
case IEEE80211_STA_AUTHORIZED:
if (sta->sta_state == IEEE80211_STA_ASSOC) {
- if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
- (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- !sta->sdata->u.vlan.sta))
- atomic_inc(&sta->sdata->bss->num_mcast_sta);
+ ieee80211_vif_inc_num_mcast(sta->sdata);
set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
ieee80211_check_fast_xmit(sta);
ieee80211_check_fast_rx(sta);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5023966..7130862 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -331,9 +331,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
return TX_DROP;
}
- } 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) != -1 &&
+ ieee80211_is_data(hdr->frame_control))) {
/*
* No associated STAs - no need to send multicast
* frames.
--
2.1.4
^ permalink raw reply related
* [PATCH 3/3] mac80211: cache the only AP_VLAN station
From: Michael Braun @ 2016-09-25 16:39 UTC (permalink / raw)
To: johannes; +Cc: Michael Braun, linux-wireless
In-Reply-To: <1474821596-12155-1-git-send-email-michael-dev@fami-braun.de>
If an AP_VLAN is only used with one station, cache a pointer to this station to
avoid lookup. This should speed up station lookup when there is only one
station assigned to the AP_VLAN interface, e.g. when using hostapd with
per_sta_vif.
Assigning only one station per AP_VLAN interfaces enables bridge IGMP snooping
to track multicast subscriptions by station to selectively forward to only
those stations that subscribed.
Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
---
net/mac80211/cfg.c | 10 ++++++++--
net/mac80211/ieee80211_i.h | 14 ++++++++++----
net/mac80211/sta_info.c | 33 +++++++++++++++++++++++++++++++--
net/mac80211/tx.c | 5 +++++
4 files changed, 54 insertions(+), 8 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 078e837..a69e6f2 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -67,6 +67,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
if (type == NL80211_IFTYPE_AP_VLAN &&
params && params->use_4addr == 0) {
RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
+ RCU_INIT_POINTER(sdata->u.vlan.sta0, NULL);
ieee80211_check_fast_rx_iface(sdata);
} else if (type == NL80211_IFTYPE_STATION &&
params && params->use_4addr >= 0) {
@@ -1379,8 +1380,13 @@ static int ieee80211_change_station(struct wiphy *wiphy,
sta->sdata = vlansdata;
ieee80211_check_fast_xmit(sta);
- if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
- ieee80211_vif_inc_num_mcast(sta->sdata);
+ if (test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
+ ieee80211_vif_inc_num_mcast(sta->sdata) == 1 &&
+ sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ rcu_assign_pointer(vlansdata->u.vlan.sta0, sta);
+ else if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+ test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+ RCU_INIT_POINTER(vlansdata->u.vlan.sta0, NULL);
ieee80211_send_layer2_update(sta);
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 7b3de28..48a141f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -307,6 +307,8 @@ struct ieee80211_if_vlan {
/* used for all tx if the VLAN is configured to 4-addr mode */
struct sta_info __rcu *sta;
+ /* the one and only authenticated station in non 4-addr mode if set */
+ struct sta_info __rcu *sta0;
atomic_t num_mcast_sta_if; /* number of stations receiving multicast */
};
@@ -1499,21 +1501,25 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status)
return false;
}
-static inline void
+static inline int
ieee80211_vif_inc_num_mcast(struct ieee80211_sub_if_data *sdata)
{
+ int ret;
+
if (sdata->vif.type != NL80211_IFTYPE_AP &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
- return;
+ return -1;
if (sdata->vif.type == NL80211_IFTYPE_AP)
- atomic_inc(&sdata->u.ap.num_mcast_sta_if);
+ ret = atomic_inc_return(&sdata->u.ap.num_mcast_sta_if);
else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- atomic_inc(&sdata->u.vlan.num_mcast_sta_if);
+ ret = atomic_inc_return(&sdata->u.vlan.num_mcast_sta_if);
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN ||
!sdata->u.vlan.sta) /* except 4addr mode */
atomic_inc(&sdata->bss->num_mcast_sta);
+
+ return ret;
}
static inline void
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 216ef65..d1c5d96 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -162,11 +162,28 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
const u8 *addr)
{
struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
+ struct sta_info *sta = NULL;
struct rhash_head *tmp;
const struct bucket_table *tbl;
rcu_read_lock();
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+ !sdata->u.vlan.sta)
+ sta = rcu_dereference(sdata->u.vlan.sta0);
+
+ WARN_ONCE((sta && sta->sdata != sdata),
+ "sdata->u.vlan.sta0->sdata != sdata");
+
+ if (sta && sta->sdata == sdata &&
+ ether_addr_equal(sta->sta.addr, addr)) {
+ rcu_read_unlock();
+ /* this is safe as the caller must already hold
+ * another rcu read section or the mutex
+ */
+ return sta;
+ }
+
tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
for_each_sta_info(local, tbl, addr, sta, tmp) {
@@ -920,6 +937,10 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta)
rcu_access_pointer(sdata->u.vlan.sta) == sta)
RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+ rcu_access_pointer(sdata->u.vlan.sta0) == sta)
+ RCU_INIT_POINTER(sdata->u.vlan.sta0, NULL);
+
return 0;
}
@@ -1883,6 +1904,9 @@ int sta_info_move_state(struct sta_info *sta,
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
} else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
ieee80211_vif_dec_num_mcast(sta->sdata);
+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+ rcu_access_pointer(sta->sdata->u.vlan.sta0) == sta)
+ RCU_INIT_POINTER(sta->sdata->u.vlan.sta0, NULL);
clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
ieee80211_clear_fast_xmit(sta);
ieee80211_clear_fast_rx(sta);
@@ -1890,7 +1914,12 @@ int sta_info_move_state(struct sta_info *sta,
break;
case IEEE80211_STA_AUTHORIZED:
if (sta->sta_state == IEEE80211_STA_ASSOC) {
- ieee80211_vif_inc_num_mcast(sta->sdata);
+ if (ieee80211_vif_inc_num_mcast(sta->sdata) == 1 &&
+ sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ rcu_assign_pointer(sta->sdata->u.vlan.sta0,
+ sta);
+ else if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ RCU_INIT_POINTER(sta->sdata->u.vlan.sta0, NULL);
set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
ieee80211_check_fast_xmit(sta);
ieee80211_check_fast_rx(sta);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 9c82fd8..c06d5f9 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1808,6 +1808,7 @@ ieee80211_tx_multicast_to_unicast(struct ieee80211_sub_if_data *sdata,
sta = rcu_dereference(sdata->u.vlan.sta);
if (sta) /* 4addr */
return 0;
+ prev = rcu_dereference(sdata->u.vlan.sta0);
case NL80211_IFTYPE_AP:
break;
default:
@@ -1839,6 +1840,9 @@ ieee80211_tx_multicast_to_unicast(struct ieee80211_sub_if_data *sdata,
return 0;
}
+ if (prev)
+ goto skip_lookup;
+
/* clone packets and update destination mac */
list_for_each_entry_rcu(sta, &local->sta_list, list) {
if (sdata != sta->sdata)
@@ -1862,6 +1866,7 @@ ieee80211_tx_multicast_to_unicast(struct ieee80211_sub_if_data *sdata,
prev = sta;
}
+skip_lookup:
if (likely(prev)) {
ieee80211_tx_dnat(skb, prev);
return 0;
--
2.1.4
^ 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