* Re: [PATCH] mt76: change the retun type of mt76_dma_attach()
From: Sergei Shtylyov @ 2019-02-11 8:38 UTC (permalink / raw)
To: Ryder Lee, Lorenzo Bianconi, Felix Fietkau, Kalle Valo
Cc: Roy Luo, linux-wireless, linux-kernel, netdev, linux-mediatek
In-Reply-To: <228fdddb9ca96e8ce861e324eb9039722cf18f49.1549850911.git.ryder.lee@mediatek.com>
Hello!
On 11.02.2019 5:13, Ryder Lee wrote:
> There is no need to retun 0 in mt76_dma_attach(), so switch it to void.
^ r missing :-)
>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
[...]
MBR, Sergei
^ permalink raw reply
* [RFC] mt76x02u: correct pad for fragments
From: Stanislaw Gruszka @ 2019-02-11 8:37 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi
Modifying skb->len & data_len doesn't look correct. Issue is not critical
we just pad 2 times, except first padding is not filled with zeros.
However I'm not sure if we should not add pad to all skb's in frags
list.
Additionally remove unlikely(pad) condition, we always pad for at least
four bytes what is needed by HW.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
.../wireless/mediatek/mt76/mt76x02_usb_core.c | 22 +++++++------------
1 file changed, 8 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index dc2226c722dd..c7ca2d93720a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -49,21 +49,15 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
FIELD_PREP(MT_TXD_INFO_DPORT, port) | flags;
put_unaligned_le32(info, skb_push(skb, sizeof(info)));
- pad = round_up(skb->len, 4) + 4 - skb->len;
- skb_walk_frags(skb, iter) {
+ skb_walk_frags(skb, iter)
last = iter;
- if (!iter->next) {
- skb->data_len += pad;
- skb->len += pad;
- break;
- }
- }
-
- if (unlikely(pad)) {
- if (skb_pad(last, pad))
- return -ENOMEM;
- __skb_put(last, pad);
- }
+
+ /* Add zero pad of 4 - 7 bytes at the end of buffer */
+ pad = round_up(skb->len, 4) + 4 - skb->len;
+ if (skb_pad(last, pad))
+ return -ENOMEM;
+ __skb_put(last, pad);
+
return 0;
}
--
2.19.2
^ permalink raw reply related
* [PATCH] mt76x02u: use usb_bulk_msg to upload firmware
From: Stanislaw Gruszka @ 2019-02-11 8:16 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi
We don't need to send firmware data asynchronously, much simpler is just
use synchronous usb_bulk_msg().
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 13 +++++
.../wireless/mediatek/mt76/mt76x02_usb_mcu.c | 52 ++++++-------------
drivers/net/wireless/mediatek/mt76/usb.c | 1 -
3 files changed, 29 insertions(+), 37 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 2e5bcb3fdff7..94e0f1379e68 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -664,6 +664,19 @@ static inline bool mt76u_check_sg(struct mt76_dev *dev)
udev->speed == USB_SPEED_WIRELESS));
}
+static inline int
+mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int timeout)
+{
+ struct usb_interface *intf = to_usb_interface(dev->dev);
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct mt76_usb *usb = &dev->usb;
+ unsigned int pipe;
+ int sent;
+
+ pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]);
+ return usb_bulk_msg(udev, pipe, data, len, &sent, timeout);
+}
+
int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
u8 req_type, u16 val, u16 offset,
void *buf, size_t len);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
index da299b8a1334..642df4287082 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
@@ -121,11 +121,8 @@ static int
__mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb,
int cmd, bool wait_resp)
{
- struct usb_interface *intf = to_usb_interface(dev->dev);
- struct usb_device *udev = interface_to_usbdev(intf);
struct mt76_usb *usb = &dev->usb;
- unsigned int pipe;
- int ret, sent;
+ int ret;
u8 seq = 0;
u32 info;
@@ -135,7 +132,6 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb,
if (test_bit(MT76_REMOVED, &dev->state))
return 0;
- pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]);
if (wait_resp) {
seq = ++usb->mcu.msg_seq & 0xf;
if (!seq)
@@ -149,7 +145,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb,
if (ret)
return ret;
- ret = usb_bulk_msg(udev, pipe, skb->data, skb->len, &sent, 500);
+ ret = mt76u_bulk_msg(dev, skb->data, skb->len, 500);
if (ret)
return ret;
@@ -263,14 +259,12 @@ void mt76x02u_mcu_fw_reset(struct mt76x02_dev *dev)
EXPORT_SYMBOL_GPL(mt76x02u_mcu_fw_reset);
static int
-__mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf,
+__mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, u8 *data,
const void *fw_data, int len, u32 dst_addr)
{
- u8 *data = sg_virt(&buf->urb->sg[0]);
- DECLARE_COMPLETION_ONSTACK(cmpl);
__le32 info;
u32 val;
- int err;
+ int err, data_len;
info = cpu_to_le32(FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) |
FIELD_PREP(MT_MCU_MSG_LEN, len) |
@@ -286,25 +280,12 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf,
mt76u_single_wr(&dev->mt76, MT_VEND_WRITE_FCE,
MT_FCE_DMA_LEN, len << 16);
- buf->len = MT_CMD_HDR_LEN + len + sizeof(info);
- err = mt76u_submit_buf(&dev->mt76, USB_DIR_OUT,
- MT_EP_OUT_INBAND_CMD,
- buf, GFP_KERNEL,
- mt76u_mcu_complete_urb, &cmpl);
- if (err < 0)
- return err;
-
- if (!wait_for_completion_timeout(&cmpl,
- msecs_to_jiffies(1000))) {
- dev_err(dev->mt76.dev, "firmware upload timed out\n");
- usb_kill_urb(buf->urb);
- return -ETIMEDOUT;
- }
+ data_len = MT_CMD_HDR_LEN + len + sizeof(info);
- if (mt76u_urb_error(buf->urb)) {
- dev_err(dev->mt76.dev, "firmware upload failed: %d\n",
- buf->urb->status);
- return buf->urb->status;
+ err = mt76u_bulk_msg(&dev->mt76, data, data_len, 1000);
+ if (err) {
+ dev_err(dev->mt76.dev, "firmware upload failed: %d\n", err);
+ return err;
}
val = mt76_rr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX);
@@ -317,17 +298,16 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf,
int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data,
int data_len, u32 max_payload, u32 offset)
{
- int err, len, pos = 0, max_len = max_payload - 8;
- struct mt76u_buf buf;
+ int len, err = 0, pos = 0, max_len = max_payload - 8;
+ u8 *buf;
- err = mt76u_buf_alloc(&dev->mt76, &buf, 1, max_payload, max_payload,
- GFP_KERNEL);
- if (err < 0)
- return err;
+ buf = kmalloc(max_payload, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
while (data_len > 0) {
len = min_t(int, data_len, max_len);
- err = __mt76x02u_mcu_fw_send_data(dev, &buf, data + pos,
+ err = __mt76x02u_mcu_fw_send_data(dev, buf, data + pos,
len, offset + pos);
if (err < 0)
break;
@@ -336,7 +316,7 @@ int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data,
pos += len;
usleep_range(5000, 10000);
}
- mt76u_buf_free(&buf);
+ kfree(buf);
return err;
}
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 5f0faf07c346..358a95a2bbcb 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -328,7 +328,6 @@ int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
return mt76u_fill_rx_sg(dev, buf, nsgs, len, sglen);
}
-EXPORT_SYMBOL_GPL(mt76u_buf_alloc);
void mt76u_buf_free(struct mt76u_buf *buf)
{
--
2.19.2
^ permalink raw reply related
* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Stefan Wahren @ 2019-02-11 8:08 UTC (permalink / raw)
To: Stanislaw Gruszka, Lorenzo Bianconi
Cc: Felix Fietkau, Doug Anderson, Minas Harutyunyan, linux-wireless,
linux-usb
In-Reply-To: <20190211075056.GB6292@redhat.com>
Hi,
Am 11.02.19 um 08:50 schrieb Stanislaw Gruszka:
> On Sun, Feb 10, 2019 at 05:52:30PM +0100, Lorenzo Bianconi wrote:
>> Anyway we will need to avoid SG since dwc_otg controller does not support it
this isn't correct. AFAIK the dwc2 host driver doesn't implement it,
which doesn't mean the controller does not support it.
Stefan
> What does it mean the dwc_otg does not support SG ? Please be more specific.
>
> Stanislaw
^ permalink raw reply
* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Stanislaw Gruszka @ 2019-02-11 7:50 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Stefan Wahren, Felix Fietkau, Doug Anderson, Minas Harutyunyan,
linux-wireless, linux-usb
In-Reply-To: <CAJ0CqmXL_PXf0LuFOnshbYZb=j_KEHyfmV5wpHHW5HXcexhDJA@mail.gmail.com>
On Sun, Feb 10, 2019 at 05:52:30PM +0100, Lorenzo Bianconi wrote:
> Anyway we will need to avoid SG since dwc_otg controller does not support it
What does it mean the dwc_otg does not support SG ? Please be more specific.
Stanislaw
^ permalink raw reply
* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Stanislaw Gruszka @ 2019-02-11 7:44 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Stefan Wahren, Felix Fietkau, Doug Anderson, Minas Harutyunyan,
linux-wireless, linux-usb
In-Reply-To: <CAJ0CqmXp2a-zwPMyMFu+UCqTHP7qNRiJFopDSdZWdms7dVef4Q@mail.gmail.com>
On Sun, Feb 10, 2019 at 11:22:25AM +0100, Lorenzo Bianconi wrote:
> > On Sat, Feb 09, 2019 at 09:29:05PM +0100, Stefan Wahren wrote:
> > > > could you please test the following series:
> > > > https://patchwork.kernel.org/cover/10764453/
> > >
> > > yeah this fixed the probing timeout and the driver will probe successful. AFAIK the dwc2 host mode doesn't support scatter-gather yet.
> >
> > So this is either dwc2 scatter-gather problem which should be addressed in
> > this driver or mt76x0u does something wrong when configuring SG.
> >
> > Disabling SG is just workaround, which do not address actual problem.
> >
> > I think I found mt76x0u issue that could cause this USB probe error
> > (and possibly also address AMD IOMMU issue). We seems do not correctly
> > set URB transfer length smaller than sg buffer length. Attached patch
> > should correct that.
>
> Hi Stanislaw,
>
> I think 'sg[0].length' is already set in mt76u_fill_rx_sg().
It is, buf->len and sg[0].length are initialized to the same value for 1
segment. But then buf->len (assigned to urb->buffer_transfer_length) change
to smaller value , but sg[0].length stay the same. What I think can be
problem for usb host driver.
> Moreover applying this patch I got the following crash (rpi-5.0.y):
Ok, so with patch probe fail instantly and trigger yet another bug(s)
on error path. You seems to address that already.
> Moreover for mt76x0u SG is 'already' disabled since we use just one
> buffer so from performance point of view I do not see any difference
> of using a standard usb buffer.
> This patch has been tested in multiple scenarios and seems to fix
> reported issues (for usb2.0).
Ok, so passing buffer via urb->transfer_buffer works. But why urb->sg
does not work for 1 segment ?
> Are you concerned about increasing code complexity?
That's one of my concerns. Another, more important one, is that
changing to urb->transfer_buffer just hide the problems. And they will
pop up when someone will start to use SG (BTW how this can be tested
for more than one fragment, IOW how multiple fragments skb's can
be generated ? ).
And now I think the bugs can be in mt76 driver taking that problems
happened on different platforms (rpi and AMD IOMMU), i.e. we do not
correctly set urb->nub_seg or length or do some other thing wrong.
Stanislaw
^ permalink raw reply
* RE: [PATCH v4 03/13] rtw88: hci files
From: Tony Chuang @ 2019-02-11 6:15 UTC (permalink / raw)
To: Brian Norris
Cc: kvalo@codeaurora.org, johannes@sipsolutions.net,
Larry.Finger@lwfinger.net, Pkshih, Andy Huang,
sgruszka@redhat.com, linux-wireless@vger.kernel.org
In-Reply-To: <20190208222855.GA31454@google.com>
> -----Original Message-----
> From: Brian Norris [mailto:briannorris@chromium.org]
>
> Hi,
>
> One more comment for now, below:
>
> On Wed, Jan 30, 2019 at 12:02:10PM +0800, yhchuang@realtek.com wrote:
> > From: Yan-Hsuan Chuang <yhchuang@realtek.com>
> >
> > hci files for Realtek 802.11ac wireless network chips
> >
> > For now there is only PCI bus supported by rtwlan, in the future it
> > will also have USB/SDIO
> >
> > Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
> > ---
> > drivers/net/wireless/realtek/rtw88/hci.h | 211 ++++++
> > drivers/net/wireless/realtek/rtw88/pci.c | 1210
> ++++++++++++++++++++++++++++++
> > drivers/net/wireless/realtek/rtw88/pci.h | 229 ++++++
> > 3 files changed, 1650 insertions(+)
> > create mode 100644 drivers/net/wireless/realtek/rtw88/hci.h
> > create mode 100644 drivers/net/wireless/realtek/rtw88/pci.c
> > create mode 100644 drivers/net/wireless/realtek/rtw88/pci.h
>
> ...
>
> > diff --git a/drivers/net/wireless/realtek/rtw88/pci.c
> b/drivers/net/wireless/realtek/rtw88/pci.c
> > new file mode 100644
> > index 0000000..ef3c9bb
> > --- /dev/null
> > +++ b/drivers/net/wireless/realtek/rtw88/pci.c
> > @@ -0,0 +1,1210 @@
>
> > +static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
> > + u8 hw_queue)
> > +{
> > + struct rtw_chip_info *chip = rtwdev->chip;
> > + struct rtw_pci_rx_ring *ring;
> > + struct rtw_rx_pkt_stat pkt_stat;
> > + struct ieee80211_rx_status rx_status;
> > + struct sk_buff *skb, *new;
> > + u32 cur_wp, cur_rp, tmp;
> > + u32 count;
> > + u32 pkt_offset;
> > + u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
> > + u32 buf_desc_sz = chip->rx_buf_desc_sz;
> > + u8 *rx_desc;
> > + dma_addr_t dma;
> > +
> > + ring = &rtwpci->rx_rings[RTW_RX_QUEUE_MPDU];
> > +
> > + tmp = rtw_read32(rtwdev, RTK_PCI_RXBD_IDX_MPDUQ);
> > + cur_wp = tmp >> 16;
> > + cur_wp &= 0xfff;
> > + if (cur_wp >= ring->r.wp)
> > + count = cur_wp - ring->r.wp;
> > + else
> > + count = ring->r.len - (ring->r.wp - cur_wp);
> > +
> > + cur_rp = ring->r.rp;
> > + while (count--) {
> > + rtw_pci_dma_check(rtwdev, ring, cur_rp);
> > + skb = ring->buf[cur_rp];
> > + dma = *((dma_addr_t *)skb->cb);
> > + pci_unmap_single(rtwpci->pdev, dma, RTK_PCI_RX_BUF_SIZE,
> > + PCI_DMA_FROMDEVICE);
> > + rx_desc = skb->data;
> > + chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
> > +
> > + /* offset from rx_desc to payload */
> > + pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
> > + pkt_stat.shift;
> > +
> > + if (pkt_stat.is_c2h) {
> > + /* keep rx_desc, halmac needs it */
> > + skb_put(skb, pkt_stat.pkt_len + pkt_offset);
> > +
> > + /* pass offset for further operation */
> > + *((u32 *)skb->cb) = pkt_offset;
> > + skb_queue_tail(&rtwdev->c2h_queue, skb);
> > + ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work);
> > + } else {
> > + /* remove rx_desc, maybe use skb_pull? */
> > + skb_put(skb, pkt_stat.pkt_len);
> > + skb_reserve(skb, pkt_offset);
> > +
> > + /* alloc a smaller skb to mac80211 */
> > + new = dev_alloc_skb(pkt_stat.pkt_len);
> > + if (!new) {
> > + new = skb;
> > + } else {
> > + skb_put_data(new, skb->data, skb->len);
> > + dev_kfree_skb_any(skb);
> > + }
> > + /* TODO: merge into rx.c */
> > + rtw_rx_stats(rtwdev, pkt_stat.vif, skb);
> > + memcpy(new->cb, &rx_status, sizeof(rx_status));
> > + ieee80211_rx_irqsafe(rtwdev->hw, new);
> > + }
> > +
> > + /* skb delivered to mac80211, alloc a new one in rx ring */
> > + new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE);
> > + if (WARN(!new, "rx routine starvation\n"))
> > + return;
> > +
> > + ring->buf[cur_rp] = new;
> > + rtw_pci_reset_rx_desc(rtwdev, new, ring, cur_rp, buf_desc_sz);
>
> You aren't handling failures from this function. It's not quite clear to
> me whether that will just leak the SKB, or if it will end in an
> unbalanced unmap later.
Unfortunately I think it will end up in an unbalanced unmap. But I have no idea
now about how to deal with the dma_map failure. Since the rx dma runs ring-based,
if the dma_map failed, seems the only way is to retry to dma_map again until it has
a mapped dma address. Otherwise the dma engine will dma contents of a packet to
an unknown dma address (previous skb in this case, also will corrupt the memory)
after it ran over a cycle and hit this desc.
Hence I think here we should put an err or WARN here to explicitly know there has
something went wrong. But I do not know how to deal with the dma failure :(
Need to re-construct them in my brain and consider the rx path.
Yan-Hsuan
^ permalink raw reply
* Re: linux-next: Signed-off-by missing for commit in the wireless-drivers-next tree
From: Kalle Valo @ 2019-02-11 6:12 UTC (permalink / raw)
To: Stephen Rothwell
Cc: Wireless, Linux Next Mailing List, Linux Kernel Mailing List,
Govind Singh, ath10k
In-Reply-To: <20190211072814.7428f192@canb.auug.org.au>
+ ath10k
Stephen Rothwell <sfr@canb.auug.org.au> writes:
> Hi all,
>
> Commit
>
> 768ec4c012ac ("ath10k: update HOST capability qmi message")
>
> is missing a Signed-off-by from its author.
Oh, I had missed that. Thanks for reporting.
Unfortunately it would be difficult to rebase wireless-drivers-next so I
can't (easily) fix this. But v1 had s-o-b so at least we have the sign
off publically available:
https://patchwork.kernel.org/patch/10688563/
--
Kalle Valo
^ permalink raw reply
* RE: [PATCH v4 03/13] rtw88: hci files
From: Tony Chuang @ 2019-02-11 5:48 UTC (permalink / raw)
To: Brian Norris
Cc: kvalo@codeaurora.org, johannes@sipsolutions.net,
Larry.Finger@lwfinger.net, Pkshih, Andy Huang,
sgruszka@redhat.com, linux-wireless@vger.kernel.org
In-Reply-To: <20190209021426.GA163159@google.com>
> From: Brian Norris [mailto:briannorris@chromium.org]
>
> FYI, I have some more review comments because I'm trying to see why your
> TX path doesn't work all that well. At least, it's not reporting things
> correctly. (I know there's one ACK reporting bug you fixed in a
> follow-up patch, but then, that patch is buggy too I think.)
>
> > +static int rtw_pci_xmit(struct rtw_dev *rtwdev,
> > + struct rtw_tx_pkt_info *pkt_info,
> > + struct sk_buff *skb, u8 queue)
> > +{
> > + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> > + struct rtw_chip_info *chip = rtwdev->chip;
> > + struct rtw_pci_tx_ring *ring;
> > + struct rtw_pci_tx_data *tx_data;
> > + dma_addr_t dma;
> > + u32 tx_pkt_desc_sz = chip->tx_pkt_desc_sz;
> > + u32 tx_buf_desc_sz = chip->tx_buf_desc_sz;
> > + u32 size;
> > + u32 psb_len;
> > + u8 *pkt_desc;
> > + struct rtw_pci_tx_buffer_desc *buf_desc;
> > + u32 bd_idx;
> > +
> > + ring = &rtwpci->tx_rings[queue];
> > +
> > + size = skb->len;
> > +
> > + if (queue == RTW_TX_QUEUE_BCN)
> > + rtw_pci_release_rsvd_page(rtwpci, ring);
> > + else if (!avail_desc(ring->r.wp, ring->r.rp, ring->r.len))
> > + return -ENOSPC;
> > +
> > + pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
> > + memset(pkt_desc, 0, tx_pkt_desc_sz);
> > + pkt_info->qsel = rtw_pci_get_tx_qsel(skb, queue);
> > + rtw_tx_fill_tx_desc(pkt_info, skb);
> > + dma = pci_map_single(rtwpci->pdev, skb->data, skb->len,
> > + PCI_DMA_TODEVICE);
> > + if (pci_dma_mapping_error(rtwpci->pdev, dma))
> > + return -EBUSY;
> > +
> > + /* after this we got dma mapped, there is no way back */
> > + buf_desc = get_tx_buffer_desc(ring, tx_buf_desc_sz);
> > + memset(buf_desc, 0, tx_buf_desc_sz);
> > + psb_len = (skb->len - 1) / 128 + 1;
> > + if (queue == RTW_TX_QUEUE_BCN)
> > + psb_len |= 1 << RTK_PCI_TXBD_OWN_OFFSET;
> > +
> > + buf_desc[0].psb_len = cpu_to_le16(psb_len);
> > + buf_desc[0].buf_size = cpu_to_le16(tx_pkt_desc_sz);
> > + buf_desc[0].dma = cpu_to_le32(dma);
> > + buf_desc[1].buf_size = cpu_to_le16(size);
> > + buf_desc[1].dma = cpu_to_le32(dma + tx_pkt_desc_sz);
> > +
> > + tx_data = rtw_pci_get_tx_data(skb);
> > + tx_data->dma = dma;
> > + skb_queue_tail(&ring->queue, skb);
>
> IIUC, you have no locking for this queue. That seems like a bad idea. It
> then gets pulled off this queue in your ISR, again without a lock. So
> for example, if the only packet in your queue gets completed while you
> are trying to queue another one, you might corrupt the list.
>
I think skb_queue_tail already has its own spinlock to protect the queue?
Cannot see why the list might be corrupted. Or I misunderstand you.
Yan-Hsuan
^ permalink raw reply
* RE: [PATCH v4 08/13] rtw88: debug files
From: Tony Chuang @ 2019-02-11 5:41 UTC (permalink / raw)
To: Brian Norris
Cc: kvalo@codeaurora.org, johannes@sipsolutions.net,
Larry.Finger@lwfinger.net, Pkshih, Andy Huang,
sgruszka@redhat.com, linux-wireless@vger.kernel.org
In-Reply-To: <20190201194938.GA98048@google.com>
> -----Original Message-----
> From: Brian Norris [mailto:briannorris@chromium.org]
>
> Hi,
>
> On Wed, Jan 30, 2019 at 12:02:15PM +0800, yhchuang@realtek.com wrote:
> > From: Yan-Hsuan Chuang <yhchuang@realtek.com>
> >
> > debug files for Realtek 802.11ac wireless network chips
> >
> > Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
> > ---
> > drivers/net/wireless/realtek/rtw88/debug.c | 631
> +++++++++++++++++++++++++++++
> > drivers/net/wireless/realtek/rtw88/debug.h | 35 ++
> > 2 files changed, 666 insertions(+)
> > create mode 100644 drivers/net/wireless/realtek/rtw88/debug.c
> > create mode 100644 drivers/net/wireless/realtek/rtw88/debug.h
> >
> > diff --git a/drivers/net/wireless/realtek/rtw88/debug.c
> b/drivers/net/wireless/realtek/rtw88/debug.c
> > new file mode 100644
> > index 0000000..d0cb9d3
> > --- /dev/null
> > +++ b/drivers/net/wireless/realtek/rtw88/debug.c
> > @@ -0,0 +1,631 @@
>
> ...
>
> > +#ifdef CONFIG_RTW88_DEBUG
> > +
> > +void __rtw_dbg(struct rtw_dev *rtwdev, const char *fmt, ...)
> > +{
> > + struct va_format vaf = {
> > + .fmt = fmt,
> > + };
> > + va_list args;
> > +
> > + va_start(args, fmt);
> > + vaf.va = &args;
> > +
> > + if (net_ratelimit())
> > + dev_dbg(rtwdev->dev, "%pV", &vaf);
>
> I understand some questions came up about this dbg() interface
> previously, without the most constructive result, but...
>
> ...I do find one particular aspect of this interface a little weird: it
> has its own separate Kconfig flag, and yet it's still implicitly
> dependent on CONFIG_DYNAMIC_DEBUG. Note how dev_dbg() gets completely
> stubbed out if !defined(CONFIG_DYNAMIC_DEBUG) && !defined(DEBUG).
>
> I think some other similar loggers end up just using
> dev_printk(KERN_DEBUG, ...) for this piece of the equation, so that if
> somebody has bothered to enable CONFIG_RTW88_DEBUG, they can be sure
> their log messages are at least compiled in.
>
> But then, other drivers that have used dev_printk() *also* have dynamic
> methods to enable/disable their dbg-level messages (e.g., with a 'mask'
> module parameter, for classifying different types of messages). That
> also gives us the option of compiling in the messages while leaving them
> disabled for printing by default. IOW, they basically implement a
> categorized version of CONFIG_DYNAMIC_DEBUG.
>
> (Also note: my systems generally have DYNAMIC_DEBUG disabled, but we
> *do* like to have a few driver-specific debug options enabled for WiFi,
> so we can debug problems in the field via runtime enable/disable.)
>
> Altogether, I think this means you should either:
>
> (a) alias RTW88_DEBUG with DYNAMIC_DEBUG (e.g., RTW88_DEBUG selects
> or
> depends on DYNAMIC_DEBUG?) or, remove your own special Kconfig
> entirely; or
> (b) implement runtime controls to enable/disable your dbg() messages,
> and do not depend on DYNAMIC_DEBUG
>
> I kinda lean toward (b), since that's how many other WiFi drivers work,
> and it prevents me from having to enable all of DYNAMIC_DEBUG (although,
> it may be time to reevaluate why Chrome OS has it disabled...probably
> just for mild savings on size). It also gives you the option of
> classifying your debug messages even further.
>
So I think I can add a debug_mask and change dev_dbg to dev_printk.
And leave rtw_[err|warn|info] unchanged. This way rtw_dbg will no more
depend on DYNAMIC_DEBUG, also better for a wifi driver to select debug
messages we want. Actually as more components added I think it's time to
do it for developers to debug on various scenarios. :)
It will take days for me to change the debug log and resend the patch set.
But I think it's worth that we don't bother to have another patch to fix it.
And I hope it won't have bad impact for reviewers.
Yan-Hsuan
^ permalink raw reply
* RE: [PATCH 01/24] rtw88: report correct tx status if mac80211 requested one
From: Tony Chuang @ 2019-02-11 4:31 UTC (permalink / raw)
To: Brian Norris
Cc: kvalo@codeaurora.org, Larry.Finger@lwfinger.net, Andy Huang,
sgruszka@redhat.com, linux-wireless@vger.kernel.org
In-Reply-To: <20190209030756.GB163159@google.com>
> -----Original Message-----
> From: Brian Norris [mailto:briannorris@chromium.org]
>
> On Thu, Jan 31, 2019 at 08:21:14PM +0800, yhchuang@realtek.com wrote:
> > From: Yan-Hsuan Chuang <yhchuang@realtek.com>
> >
> > Before this commit, driver always reports IEEE80211_TX_STAT_ACK for
> > every tx packet, but it will confuse the mac80211 stack for connection
> > monitor system. mac80211 stack needs correct ack information about some
> > specific packets such as prop_req, null, auth, assoc, in order to know
> > if AP is alive. And for such packets, mac80211 will pass a tx flag
> > IEEE80211_TX_CTL_REQ_TX_STATUS to driver. Driver then need to request a
> > tx report from hardware.
>
> I think you're misinterpreting the mac80211 semantics here. This flag
> isn't for the driver to determine whether or not it should report ACKs
> -- it's to help ensure that status reports *really* make it back up to
> the upper layers (and don't get dropped).
>
> On the contrary, if you look at __ieee80211_tx_status(), it's expecting
> that everything that has IEEE80211_HW_REPORTS_TX_ACK_STATUS will report
> an appropriate IEEE80211_TX_STAT_ACK status. The logic is basically:
>
> if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
> if (!(info->flags & IEEE80211_TX_STAT_ACK))
> ieee80211_lost_packet(sta, info);
>
> That explains why I see almost every packet get reported as lost in `iw
> wlan0 station dump`.
To fix `iw wlan0 station dump` display, I think I can just restore one line
in pci.c. That is, restore IEEE80211_TX_STAT_ACK flag line:
+ continue;
+ }
ieee80211_tx_info_clear_status(info);
- info->flags |= IEEE80211_TX_STAT_ACK;
ieee80211_tx_status_irqsafe(hw, skb)
And with some modifications, such as IEEE80211_TX_CTL_NO_ACK check.
Then we can better reporting ACK status for data frames without
IEEE80211_TX_CTL_REQ_TX_STATUS. This way we can also ensure the
connection monitor can work. (but it will be no loss)
>
> > The tx report is not passed by hardware with the tx'ed packet, it is
> > passed through C2H. So driver need to queue the packets that require
> > correct tx report and upon the tx report is received, report to mac80211
> > stack, with the frame is acked or not.
> >
> > In case of driver missed the C2H report, setup a 500ms timer to purge
> > the tx report skb queue (500ms is time mac80211 used as probe_time).
> >
> > Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
> > ---
> > drivers/net/wireless/realtek/rtw88/fw.c | 21 ++++++-
> > drivers/net/wireless/realtek/rtw88/fw.h | 8 +++
> > drivers/net/wireless/realtek/rtw88/main.c | 10 ++++
> > drivers/net/wireless/realtek/rtw88/main.h | 13 +++++
> > drivers/net/wireless/realtek/rtw88/pci.c | 8 ++-
> > drivers/net/wireless/realtek/rtw88/pci.h | 1 +
> > drivers/net/wireless/realtek/rtw88/tx.c | 96
> +++++++++++++++++++++++++++++++
> > drivers/net/wireless/realtek/rtw88/tx.h | 8 +++
> > 8 files changed, 163 insertions(+), 2 deletions(-)
>
> ...
>
> > diff --git a/drivers/net/wireless/realtek/rtw88/pci.c
> b/drivers/net/wireless/realtek/rtw88/pci.c
> > index ef3c9bb..7de4638 100644
> > --- a/drivers/net/wireless/realtek/rtw88/pci.c
> > +++ b/drivers/net/wireless/realtek/rtw88/pci.c
> > @@ -585,6 +585,7 @@ static int rtw_pci_xmit(struct rtw_dev *rtwdev,
> >
> > tx_data = rtw_pci_get_tx_data(skb);
> > tx_data->dma = dma;
> > + tx_data->sn = pkt_info->sn;
> > skb_queue_tail(&ring->queue, skb);
> >
> > /* kick off tx queue */
> > @@ -716,8 +717,13 @@ static void rtw_pci_tx_isr(struct rtw_dev *rtwdev,
> struct rtw_pci *rtwpci,
> > skb_pull(skb, rtwdev->chip->tx_pkt_desc_sz);
> >
> > info = IEEE80211_SKB_CB(skb);
> > +
> > + /* enqueue to wait for tx report */
> > + if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
> > + rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn);
>
> This reporting code appears to be very buggy. At least, it's extremely
> easy to hit the WARN() you've inserted ("purge skb(s) not reported by
> firmware"), which means that the TX reporting queue is not getting
> responses for a lot of packets.
It's not buggy I think, if firmware is not reporting status, something must
go wrong. And after some test I know why you feel it's unreliable.
For WOW implementation, we modified a lot in fw.c functions.
And correct some driver-firmware interface behaviors. To make sure the
firmware is running as expected. But the patches are still holding in my hand.
I can attach them in this patch set, and apparently I should. I will separate
them out of WOW patch set and resend again.
>
> So it's not clear if you should be trying to accurately report
> everything (even if your firmware status reports are unreliable), or if
> you should just drop the REPORTS_TX_ACK_STATUS feature.
I think we should keep this feature. Because we actually can report status,
despite not for every packet. The only problem is when we use `iw wlan0
station dump` we could get *no* packet loss (like I've mentioned above,
report TX_STAT_ACK for every other packets not have
IEEE80211_TX_CTL_REQ_TX_STATUS). We cannot accurately report
everything by firmware report, it takes too many tx bandwidth, and
the performance will degrade severely. If we really cannot accept reporting
tx status this way, we need to find another way to solve it. That means I
need some time to investigate and test connect monitor system and get
a better report logic if we drop the REPORTS_TX_ACK_STATUS feature.
Or if you have a point of view, we can discuss about it.
Thanks!
>
> > + continue;
> > + }
> > ieee80211_tx_info_clear_status(info);
> > - info->flags |= IEEE80211_TX_STAT_ACK;
> > ieee80211_tx_status_irqsafe(hw, skb);
>
> One other problem with your code is that it doesn't check for
> IEEE80211_TX_CTL_NO_ACK anywhere. With that flag, you should be
> reporting IEEE80211_TX_STAT_NOACK_TRANSMITTED instead of
> IEEE80211_TX_STAT_ACK.
Should add the check with that restored line I mentioned for pci.c
>
> > }
> >
>
> Brian
>
Yan-Hsuan
^ permalink raw reply
* RE: [PATCH 00/24] rtw88: major fixes for 8822c to have stable functionalities
From: Tony Chuang @ 2019-02-11 2:30 UTC (permalink / raw)
To: Brian Norris
Cc: kvalo@codeaurora.org, Larry.Finger@lwfinger.net, Andy Huang,
sgruszka@redhat.com, linux-wireless@vger.kernel.org
In-Reply-To: <20190201024042.GB125494@google.com>
> From: Brian Norris [mailto:briannorris@chromium.org]
> Subject: Re: [PATCH 00/24] rtw88: major fixes for 8822c to have stable
> functionalities
>
> On Thu, Jan 31, 2019 at 08:21:13PM +0800, yhchuang@realtek.com wrote:
> > From: Yan-Hsuan Chuang <yhchuang@realtek.com>
> >
> > Note this patch set is based on the original patch set "rtw88: mac80211
> > driver for Realtek 802.11ac wireless network chips".
>
> The latest would be here, for reference:
>
> https://patchwork.kernel.org/cover/10787651/
> http://lkml.kernel.org/linux-wireless/1548820940-15237-1-git-send-email-yhch
> uang@realtek.com
>
> > These patches are mean to make sure 8822c chip to operate normal for most
> > of the basic functionalities, such as power on, switch channel, scan,
> > connection establish and connection monitor.
> >
> > As the original patch set was sent 3 months ago, progress has been made
> > by Realtek during the past months. Now we have tested on more chips and
> > released tables and parameters for them. Also the chips are all
> > programed with efuse map released for 8822c.
> >
> > Most of the changes are about BB and RF, both control the tx/rx path.
> > PHY parameters/seq and efuse info make sure the hardware is powered on
> > correctly. And channel setting updates help driver to switch to target
> > channel accurately. Then trx mode setting and DACK will make hardware to
> > have stable performance to tx/rx to connect to AP.
> >
> > Here tx power control is also required to transmit with a precise power.
> > Otherwise if the power is too high or too low, the peer might not be able
> > to receive the signal.
> >
> > Finally, we need to report correct tx status for mac80211's connection
> > monitor system, this requires firmware's C2H of tx status report. After
> > this, users can use 8822c chips for more stable wireless communication.
>
> Besides the comments I added (and needing to fix the out-of-bounds
> reads), this series helpfully adds RFE 1 support, so the 8822C chip I
> have works for some basic functions -- it's not too snappy, and I feel
> like there's still plenty of room for improvement but:
>
> Tested-by: Brian Norris <briannorris@chromium.org>
>
> And except for a handful of patches (should look at patch 1 closer),
> these all look pretty sane and helpful.
>
> Reviewed-by: Brian Norris <briannorris@chromium.org>
>
> I still need to pass back over the original patchset and try a few more
> things out.
>
> Regards,
> Brian
Thanks for your review, helps a lot!
Yan-Hsuan
^ permalink raw reply
* RE: [PATCH 24/24] rtw88: 8822b: turn rtw_write32s_mask into macro
From: Tony Chuang @ 2019-02-11 2:29 UTC (permalink / raw)
To: Brian Norris
Cc: kvalo@codeaurora.org, Larry.Finger@lwfinger.net, Andy Huang,
sgruszka@redhat.com, linux-wireless@vger.kernel.org
In-Reply-To: <20190201012446.GA103846@google.com>
> From: Brian Norris [mailto:briannorris@chromium.org]
>
> Hi,
>
> >
> > +static inline void
> > +_rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32
> data)
> > +{
> > + rtw_write32_mask(rtwdev, addr, mask, data);
> > + rtw_write32_mask(rtwdev, addr + 0x200, mask, data);
> > +}
> > +
> > +/* 0xC00-0xCFF and 0xE00-0xEFF have the same layout */
>
> Feels like this belongs with _rtw_write32s_mask() now, not here?
Yeah.
>
> > +#define rtw_write32s_mask(rtwdev, addr, mask, data) \
> > + do { \
> > + BUILD_BUG_ON(addr < 0xC00 || addr >= 0xD00); \
>
> You probably want parentheses around the 'addr'. You *probably* won't
> run into trouble with this particular macro, but if the caller is doing
> the wrong kinds of comparisons or arithmetic, this might not work they
> way you want.
Should add parentheses to protect in case of some coding mistakes.
Thanks
>
> Brian
>
> > + \
> > + _rtw_write32s_mask(rtwdev, addr, mask, data); \
> > + } while (0)
> > +
> > /* phy status page0 */
> > #define GET_PHY_STAT_P0_PWDB(phy_stat)
> \
> > le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
> > --
Yan-Hsuan
^ permalink raw reply
* [PATCH] mt76: change the retun type of mt76_dma_attach()
From: Ryder Lee @ 2019-02-11 2:13 UTC (permalink / raw)
To: Lorenzo Bianconi, Felix Fietkau, Kalle Valo
Cc: Roy Luo, linux-wireless, linux-kernel, netdev, linux-mediatek,
Ryder Lee
There is no need to retun 0 in mt76_dma_attach(), so switch it to void.
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/dma.c | 3 +--
drivers/net/wireless/mediatek/mt76/dma.h | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index e2ba263..d934d72 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -522,10 +522,9 @@ int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
.kick = mt76_dma_kick_queue,
};
-int mt76_dma_attach(struct mt76_dev *dev)
+void mt76_dma_attach(struct mt76_dev *dev)
{
dev->queue_ops = &mt76_dma_ops;
- return 0;
}
EXPORT_SYMBOL_GPL(mt76_dma_attach);
diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h
index 357cc35..e3292df 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.h
+++ b/drivers/net/wireless/mediatek/mt76/dma.h
@@ -54,7 +54,7 @@ enum mt76_mcu_evt_type {
EVT_EVENT_DFS_DETECT_RSP,
};
-int mt76_dma_attach(struct mt76_dev *dev);
+void mt76_dma_attach(struct mt76_dev *dev);
void mt76_dma_cleanup(struct mt76_dev *dev);
#endif
--
1.9.1
^ permalink raw reply related
* [RFC PATCH v3 12/12] ath9k: EXT_KEY_ID A-MPDU API update
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
When using Extended Key ID mac80211 drops @IEEE80211_TX_CTL_AMPDU for
the last packet which can be added to a A-MPDU in preparation.
Finalize A-MPDU immediately and start a new aggregation.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
This is the (b)leading edge of my current attempt to figure out a
solution to the "must not aggregate keyid 0 and 1 frames together"
problem.
I've not even tested that patch properly, yet..
So it only shows how I think ath9k driver can use the A-MPDU border
signal to send out the A-MPDU frame currently under construction.
May be useful to figure out if we want to implement A-MPDU border signal
in mac80211, through.
drivers/net/wireless/ath/ath9k/xmit.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index a24265018cb2..84bbce6f212f 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -990,10 +990,8 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
* from a previous session or a failed attempt in the queue.
* Send them out as normal data frames
*/
- if (!tid->active)
+ if (!tid->active) {
tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-
- if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
bf->bf_state.bf_type = 0;
return bf;
}
@@ -1017,12 +1015,18 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
break;
}
- if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
+ if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno) ||
+ !(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
struct ath_tx_status ts = {};
struct list_head bf_head;
INIT_LIST_HEAD(&bf_head);
- list_add(&bf->list, &bf_head);
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
+ tid->bar_index <= ATH_BA_INDEX(tid->seq_start, seqno))
+ list_add(&bf->list, &bf_head);
+ else
+ ath_tx_addto_baw(sc, tid, bf);
+
ath_tx_update_baw(sc, tid, bf);
ath_tx_complete_buf(sc, bf, txq, &bf_head, NULL, &ts, 0);
continue;
--
2.20.1
^ permalink raw reply related
* [RFC PATCH v3 00/12] Draft for Extended Key ID support
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
This is my current development version for Extended Key ID support in
linux and mac80211.
I consider the all patches in this series against nl80211/mac80211 ready
for merge and if they still have defects not mentioned in the patch I
need your help to see them.
There are still some questions if we even want/need all those patches,
and so I've added some remarks to behind some commit message to start the
different discussions.
The driver patches are - with the exception of the hwsim patch -
definitely not ready for merge and mostly here to illustrate how the
different APIs can be used and to start some discussions how to handle HW
specific challenges. Of course if someone wants to play with Extended Key
ID they also should be useful... (I can provide updated mostly working
hostapd/wpa_supplicant patches if someone is interested. Don't try to
use the old ones I sent to hostapd mailing list in November.)
That said I'm now using most of the patches or their predecessor in my
private Wlan with devices both supporting and not supporting Extended
Key ID fine.
Compared to the last RFC patch only the nl80211 patch is still close to
what we discussed. It got the API cleanup/changes and the open sanity
checks and not much more.
The mac80211 patch from RFC v2 had serious defects. The most serious one
was probably to not select the key based on the keyid of the MPDU.
I think outlining all the changes will not be useful here, the initial
patch was too broken for anything but SW crypto. (Which also had
issues...)
It started out with more or less all the fixes we discussed but when
trying to get it really correct and feature complete it became three
different patches we better review from the scratch. They are now
touching much more code and make in some cases drastic changes.
Here a short overview of the patches in the series and why they are in
it:
1) mac80211: Optimize tailroom_needed update checks:
This would be a standalone patch, but some other patches depend on it
to apply cleanly.
2) nl80211/cfg80211: Extended Key ID support
Generic support for Extended Key ID.
3) mac80211: IEEE 802.11 Extended Key ID support
Mac80211 Extended Key ID support for drivers when the hardware is able to
handle Extended Key ID (aka two pairwise keys in HW).
4) mac80211: Compatibility Extended Key ID support
Mac80211 Extended Key ID support for most devices not able to handle
two unicast keys in HW.
5) mac80211: Mark A-MPDU keyid borders for drivers
This is one big question, see the patch for why we may want this or
not...
6) mac80211_hwsim: Ext Key ID support (NATIVE)
Just a one-liner to allow Extended Key ID to be used with hwsim.
--- No patch below this line is ready for merge ---
7) iwlwifi: Extended Key ID support (NATIVE)
Hopefully the seed to support Extended Key ID for all iwlwifi cards,
see the patch description for the (big) issue it has.
As it is it's mostly an example how Native Extended Key ID support
will look like working with only some cards.
8) iwlwifi: dvm - EXT_KEY_ID A-MPDU API update
Stops iwldvm drivers to complain when used together with the
experimental "mac80211: Mark A-MPDU keyid boarders for drivers"
patch.
The following patches in the series are only illustrating the COMPAT
Extended Key ID support:
9) ath: Basic Extended Key ID support
Experimental patch for generic Extended Key ID support for all ath
drivers.
10) ath5k: ath_key_config() API compatibility update
Allows to still compile ath5k drivers with the patch above.
Only provided to not break any drivers if someone wants to test
this.
11) ath9k: Extended Key ID support (COMPAT)
The example for Compatibility Key ID support, works together with
"ath: Basic Extended Key ID support".
12) ath9k: EXT_KEY_ID A-MPDU API update
A mostly untested example how drivers may benefit from "mac80211:
Mark A-MPDU keyid boarders for drivers".
Alexander Wetzel (12):
mac80211: Optimize tailroom_needed update checks
nl80211/cfg80211: Extended Key ID support
mac80211: IEEE 802.11 Extended Key ID support
mac80211: Compatibility Extended Key ID support
mac80211: Mark A-MPDU keyid boarders for drivers
mac80211_hwsim: Ext Key ID support (NATIVE)
iwlwifi: Extended Key ID support (NATIVE)
iwlwifi: dvm - EXT_KEY_ID A-MPDU API update
ath: Basic Extended Key ID support (COMPAT+NATIVE)
ath5k: ath_key_config() API compatibility update
ath9k: Extended Key ID support (COMPAT)
ath9k: EXT_KEY_ID A-MPDU API update
drivers/net/wireless/ath/ath.h | 7 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/init.c | 1 +
drivers/net/wireless/ath/ath9k/main.c | 20 +-
drivers/net/wireless/ath/ath9k/xmit.c | 14 +-
drivers/net/wireless/ath/key.c | 35 ++-
.../net/wireless/intel/iwlwifi/dvm/mac80211.c | 5 +
drivers/net/wireless/intel/iwlwifi/dvm/tx.c | 2 +-
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 5 +
drivers/net/wireless/mac80211_hwsim.c | 1 +
include/net/cfg80211.h | 2 +
include/net/mac80211.h | 65 ++++-
include/uapi/linux/nl80211.h | 23 +-
net/mac80211/cfg.c | 38 +++
net/mac80211/debugfs.c | 2 +
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/key.c | 223 +++++++++++++++---
net/mac80211/key.h | 9 +
net/mac80211/main.c | 6 +
net/mac80211/rx.c | 81 ++++---
net/mac80211/sta_info.c | 13 +
net/mac80211/sta_info.h | 6 +-
net/mac80211/tx.c | 77 ++++--
net/wireless/nl80211.c | 32 ++-
net/wireless/rdev-ops.h | 3 +-
net/wireless/trace.h | 31 ++-
net/wireless/util.c | 20 +-
28 files changed, 601 insertions(+), 126 deletions(-)
--
2.20.1
^ permalink raw reply
* [RFC PATCH v3 07/12] iwlwifi: Extended Key ID support (NATIVE)
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
This is not ready for merge and has known issues.
The patch is only for discussions to sort out how to handle it correctly!
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
iwlwifi intel cards had two big surprises:
Assuming I did not make some stupid errors it looks like my old
"Intel Corporation Centrino Ultimate-N 6300 (rev 3e)" using ucode
9.221.4.1 build 25532 is perfectly fine with two keys uploaded to
harware and honoring the keyid in the MPDUs. For a card launched 2011
that's a pleasant surprise:-)
A much shorter test with a modern "Intel Corporation Wireless 8265 /
8175 (rev 78)" using ucode version 36.e91976c0.0 shows what seems to be
MPDUs decoded with the wrong key at each rekey and therefore a candidate
for the COMPAT support only..
So the bad news seems to be, that the modern card dropped the support.
It also seems to force us to add some per-card or per-firmware depending
check to decide which card can use the Native Extended Key ID support
and use the Compat mode for the rest.
Is there any way to find out which cards/firmware can be used with
Extended Key ID?
I also have tested patch for iwldvm using the Compat mode and I think
mvm cards will also work with that.
drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c | 5 +++++
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 5 +++++
2 files changed, 10 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
index 54b759cec8b3..0dd5c19ac412 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
@@ -111,6 +111,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
+ ieee80211_hw_set(hw, EXT_KEY_ID_NATIVE);
if (priv->trans->max_skb_frags)
hw->netdev_features = NETIF_F_HIGHDMA | NETIF_F_SG;
@@ -676,6 +677,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
switch (cmd) {
+ case EXT_SET_KEY:
case SET_KEY:
if (is_default_wep_key) {
ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key);
@@ -701,6 +703,9 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
break;
+ case EXT_KEY_RX_TX:
+ ret = 0;
+ break;
default:
ret = -EINVAL;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index fc251cc47b7f..102367d2572f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -442,6 +442,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ieee80211_hw_set(hw, STA_MMPDU_TXQ);
ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, TX_FRAG_LIST);
+ ieee80211_hw_set(hw, EXT_KEY_ID_NATIVE);
if (iwl_mvm_has_tlc_offload(mvm)) {
ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
@@ -3357,6 +3358,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
switch (cmd) {
+ case EXT_SET_KEY:
case SET_KEY:
if ((vif->type == NL80211_IFTYPE_ADHOC ||
vif->type == NL80211_IFTYPE_AP) && !sta) {
@@ -3464,6 +3466,9 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n");
ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key);
break;
+ case EXT_KEY_RX_TX:
+ ret = 0;
+ break;
default:
ret = -EINVAL;
}
--
2.20.1
^ permalink raw reply related
* [RFC PATCH v3 11/12] ath9k: Extended Key ID support (COMPAT)
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
Implements %EXT_SET_KEY, %EXT_KEY_RX_TX and %EXT_DISABLE_KEY_RX and
enables EXT_KEY_ID_COMPAT.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
Like the generic ath patch to provide Extended Key ID support just the
minimum needed to get it working in AP mode and serve as an reference
how Compatibility Extended Key ID support looks like from a driver
perspective.
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/init.c | 1 +
drivers/net/wireless/ath/ath9k/main.c | 20 ++++++++++++++++---
3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index a82ad739ab80..2708572616f2 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1446,7 +1446,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
switch (cmd) {
case SET_KEY:
- ret = ath_key_config(common, vif, sta, key);
+ ret = ath_key_config(common, vif, sta, key, true);
if (ret >= 0) {
key->hw_key_idx = ret;
/* push IV and Michael MIC generation to stack */
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index c070a9e51ebf..ac1c6d59b954 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -929,6 +929,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
+ ieee80211_hw_set(hw, EXT_KEY_ID_COMPAT);
if (ath9k_ps_enable)
ieee80211_hw_set(hw, SUPPORTS_PS);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index f23cb2f3d296..880687f09157 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1518,7 +1518,7 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
vif->type != NL80211_IFTYPE_AP_VLAN)
return 0;
- key = ath_key_config(common, vif, sta, &ps_key);
+ key = ath_key_config(common, vif, sta, &ps_key, true);
if (key > 0) {
an->ps_key = key;
an->key_idx[0] = key;
@@ -1675,9 +1675,13 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_node *an = NULL;
int ret = 0, i;
+ bool rx_accel = true;
- if (ath9k_modparam_nohwcrypt)
+ if (ath9k_modparam_nohwcrypt) {
+ if (cmd == EXT_DISABLE_KEY_RX || cmd == EXT_KEY_RX_TX)
+ return 0;
return -ENOSPC;
+ }
if ((vif->type == NL80211_IFTYPE_ADHOC ||
vif->type == NL80211_IFTYPE_MESH_POINT) &&
@@ -1701,12 +1705,15 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
an = (struct ath_node *)sta->drv_priv;
switch (cmd) {
+ case EXT_SET_KEY:
+ rx_accel = false;
+ /* Fall trough */
case SET_KEY:
if (sta)
ath9k_del_ps_key(sc, vif, sta);
key->hw_key_idx = 0;
- ret = ath_key_config(common, vif, sta, key);
+ ret = ath_key_config(common, vif, sta, key, rx_accel);
if (ret >= 0) {
key->hw_key_idx = ret;
/* push IV and Michael MIC generation to stack */
@@ -1740,6 +1747,13 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
}
key->hw_key_idx = 0;
break;
+ case EXT_DISABLE_KEY_RX:
+ rx_accel = false;
+ /* fall trough */
+ case EXT_KEY_RX_TX:
+ if (ath_hw_rx_crypt(common, key, sta, rx_accel))
+ ret = 0;
+ break;
default:
ret = -EINVAL;
}
--
2.20.1
^ permalink raw reply related
* [PATCH wireless-drivers 3/3] mt76: usb: do not run mt76u_queues_deinit twice
From: Lorenzo Bianconi @ 2019-02-10 21:49 UTC (permalink / raw)
To: linux-wireless; +Cc: nbd, sgruszka, stefan.wahren
In-Reply-To: <cover.1549832428.git.lorenzo.bianconi@redhat.com>
Do not call mt76u_queues_deinit routine in mt76u_alloc_queues error path
since it will be run in mt76x0u_register_device or
mt76x2u_register_device error path. Current implementation triggers the
following kernel warning:
[ 67.005516] WARNING: CPU: 2 PID: 761 at lib/refcount.c:187 refcount_sub_and_test_checked+0xa4/0xb8
[ 67.019513] refcount_t: underflow; use-after-free.
[ 67.099872] Hardware name: BCM2835
[ 67.106268] Backtrace:
[ 67.111584] [<8010c91c>] (dump_backtrace) from [<8010cc00>] (show_stack+0x20/0x24)
[ 67.124974] r6:60000013 r5:ffffffff r4:00000000 r3:a50bade6
[ 67.132226] [<8010cbe0>] (show_stack) from [<807ca5f4>] (dump_stack+0xc8/0x114)
[ 67.141225] [<807ca52c>] (dump_stack) from [<8011e65c>] (__warn+0xf4/0x120)
[ 67.149849] r9:000000bb r8:804d0138 r7:00000009 r6:8099dc84 r5:00000000 r4:b66c7b58
[ 67.160767] [<8011e568>] (__warn) from [<8011e6d0>] (warn_slowpath_fmt+0x48/0x50)
[ 67.171436] r9:7f65e128 r8:80d1419c r7:80c0bac4 r6:b97b3044 r5:b7368e00 r4:00000000
[ 67.182433] [<8011e68c>] (warn_slowpath_fmt) from [<804d0138>] (refcount_sub_and_test_checked+0xa4/0xb8)
[ 67.195221] r3:80c91c25 r2:8099dc94
[ 67.200370] r4:00000000
[ 67.204397] [<804d0094>] (refcount_sub_and_test_checked) from [<804d0164>] (refcount_dec_and_test_checked+0x18/0x1c)
[ 67.218046] r4:b7368e00 r3:00000001
[ 67.223125] [<804d014c>] (refcount_dec_and_test_checked) from [<805db49c>] (usb_free_urb+0x20/0x4c)
[ 67.235358] [<805db47c>] (usb_free_urb) from [<7f639804>] (mt76u_buf_free+0x98/0xac [mt76_usb])
[ 67.247302] r4:00000001 r3:00000001
[ 67.252468] [<7f63976c>] (mt76u_buf_free [mt76_usb]) from [<7f639ef8>] (mt76u_queues_deinit+0x44/0x100 [mt76_usb])
[ 67.266102] r8:b8fe8600 r7:b5dac480 r6:b5dace20 r5:00000001 r4:00000000 r3:00000080
[ 67.277132] [<7f639eb4>] (mt76u_queues_deinit [mt76_usb]) from [<7f65c040>] (mt76x0u_cleanup+0x40/0x4c [mt76x0u])
[ 67.290737] r7:b5dac480 r6:b8fe8600 r5:ffffffea r4:b5dace20
[ 67.298069] [<7f65c000>] (mt76x0u_cleanup [mt76x0u]) from [<7f65c564>] (mt76x0u_probe+0x1f0/0x354 [mt76x0u])
[ 67.311174] r4:b5dace20 r3:00000000
[ 67.316312] [<7f65c374>] (mt76x0u_probe [mt76x0u]) from [<805e0b6c>] (usb_probe_interface+0x104/0x240)
[ 67.328915] r7:00000000 r6:7f65e034 r5:b6634800 r4:b8fe8620
[ 67.336276] [<805e0a68>] (usb_probe_interface) from [<8056a8bc>] (really_probe+0x224/0x2f8)
[ 67.347965] r10:b65f0a00 r9:00000019 r8:7f65e034 r7:80d3e124 r6:00000000 r5:80d3e120
[ 67.359175] r4:b8fe8620 r3:805e0a68
[ 67.364384] [<8056a698>] (really_probe) from [<8056ab60>] (driver_probe_device+0x6c/0x180)
[ 67.375974] r10:b65f0a00 r9:7f65e2c0 r8:b8fe8620 r7:00000000 r6:7f65e034 r5:7f65e034
[ 67.387170] r4:b8fe8620 r3:00000000
[ 67.392378] [<8056aaf4>] (driver_probe_device) from [<8056ad54>] (__driver_attach+0xe0/0xe4)
[ 67.404097] r9:7f65e2c0 r8:7f65d22c r7:00000000 r6:b8fe8654 r5:7f65e034 r4:b8fe8620
[ 67.415122] [<8056ac74>] (__driver_attach) from [<8056880c>] (bus_for_each_dev+0x68/0xa0)
[ 67.426628] r6:8056ac74 r5:7f65e034 r4:00000000 r3:00000027
[ 67.434017] [<805687a4>] (bus_for_each_dev) from [<8056a1cc>] (driver_attach+0x28/0x30)
[ 67.445394] r6:80c6ddc8 r5:b7368f80 r4:7f65e034
[ 67.451703] [<8056a1a4>] (driver_attach) from [<80569c24>] (bus_add_driver+0x194/0x21c)
[ 67.463081] [<80569a90>] (bus_add_driver) from [<8056b504>] (driver_register+0x8c/0x124)
[ 67.474560] r7:80c6ddc8 r6:7f65e034 r5:00000000 r4:7f65e034
[ 67.481964] [<8056b478>] (driver_register) from [<805df510>] (usb_register_driver+0x74/0x140)
[ 67.493901] r5:00000000 r4:7f65e000
[ 67.499131] [<805df49c>] (usb_register_driver) from [<7f661024>] (mt76x0_driver_init+0x24/0x1000 [mt76x0u])
[ 67.512258] r9:00000001 r8:7f65e308 r7:00000000 r6:80c08d48 r5:7f661000 r4:7f65e2c0
[ 67.523404] [<7f661000>] (mt76x0_driver_init [mt76x0u]) from [<80102f6c>] (do_one_initcall+0x4c/0x210)
[ 67.536142] [<80102f20>] (do_one_initcall) from [<801ae63c>] (do_init_module+0x6c/0x21c)
[ 67.547639] r8:7f65e308 r7:80c08d48 r6:b65f0ac0 r5:7f65e2c0 r4:7f65e2c0
[ 67.556129] [<801ae5d0>] (do_init_module) from [<801ad68c>] (load_module+0x1d10/0x2304)
Fixes: b40b15e1521f ("mt76: add usb support to mt76 layer")
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
drivers/net/wireless/mediatek/mt76/usb.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 31c18ac1c94a..8920add3fdfa 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -844,16 +844,9 @@ int mt76u_alloc_queues(struct mt76_dev *dev)
err = mt76u_alloc_rx(dev);
if (err < 0)
- goto err;
-
- err = mt76u_alloc_tx(dev);
- if (err < 0)
- goto err;
+ return err;
- return 0;
-err:
- mt76u_queues_deinit(dev);
- return err;
+ return mt76u_alloc_tx(dev);
}
EXPORT_SYMBOL_GPL(mt76u_alloc_queues);
--
2.20.1
^ permalink raw reply related
* [PATCH wireless-drivers 2/3] mt76: usb: fix possible memory leak in mt76u_buf_free
From: Lorenzo Bianconi @ 2019-02-10 21:49 UTC (permalink / raw)
To: linux-wireless; +Cc: nbd, sgruszka, stefan.wahren
In-Reply-To: <cover.1549832428.git.lorenzo.bianconi@redhat.com>
Move q->ndesc initialization before the for loop in mt76u_alloc_rx
since otherwise allocated urbs will not be freed in mt76u_buf_free
Double-check scatterlist pointer in mt76u_buf_free
Fixes: b40b15e1521f ("mt76: add usb support to mt76 layer")
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
drivers/net/wireless/mediatek/mt76/usb.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index b061263453d4..31c18ac1c94a 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -331,10 +331,16 @@ EXPORT_SYMBOL_GPL(mt76u_buf_alloc);
void mt76u_buf_free(struct mt76u_buf *buf)
{
struct urb *urb = buf->urb;
+ struct scatterlist *sg;
int i;
- for (i = 0; i < urb->num_sgs; i++)
- skb_free_frag(sg_virt(&urb->sg[i]));
+ for (i = 0; i < urb->num_sgs; i++) {
+ sg = &urb->sg[i];
+ if (!sg)
+ continue;
+
+ skb_free_frag(sg_virt(sg));
+ }
usb_free_urb(buf->urb);
}
EXPORT_SYMBOL_GPL(mt76u_buf_free);
@@ -540,7 +546,8 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
nsgs = 1;
}
- for (i = 0; i < MT_NUM_RX_ENTRIES; i++) {
+ q->ndesc = MT_NUM_RX_ENTRIES;
+ for (i = 0; i < q->ndesc; i++) {
err = mt76u_buf_alloc(dev, &q->entry[i].ubuf,
nsgs, q->buf_size,
SKB_WITH_OVERHEAD(q->buf_size),
@@ -548,7 +555,6 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
if (err < 0)
return err;
}
- q->ndesc = MT_NUM_RX_ENTRIES;
return mt76u_submit_rx_buffers(dev);
}
--
2.20.1
^ permalink raw reply related
* [PATCH wireless-drivers 1/3] mt76: usb: fix possible NULL pointer dereference in mt76u_mcu_deinit
From: Lorenzo Bianconi @ 2019-02-10 21:49 UTC (permalink / raw)
To: linux-wireless; +Cc: nbd, sgruszka, stefan.wahren
In-Reply-To: <cover.1549832428.git.lorenzo.bianconi@redhat.com>
Fix possible NULL pointer dereference in mt76u_mcu_deinit routine that
can occur if initialization path fails before calling mt76u_mcu_init_rx
Fixes: ee676cd5017c ("mt76: add driver code for MT76x2u based devices")
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
drivers/net/wireless/mediatek/mt76/usb_mcu.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/usb_mcu.c
index 036be4163e69..9527e1216f3d 100644
--- a/drivers/net/wireless/mediatek/mt76/usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/usb_mcu.c
@@ -48,9 +48,11 @@ EXPORT_SYMBOL_GPL(mt76u_mcu_init_rx);
void mt76u_mcu_deinit(struct mt76_dev *dev)
{
- struct mt76_usb *usb = &dev->usb;
+ struct mt76u_buf *buf = &dev->usb.mcu.res;
- usb_kill_urb(usb->mcu.res.urb);
- mt76u_buf_free(&usb->mcu.res);
+ if (buf->urb) {
+ usb_kill_urb(buf->urb);
+ mt76u_buf_free(buf);
+ }
}
EXPORT_SYMBOL_GPL(mt76u_mcu_deinit);
--
2.20.1
^ permalink raw reply related
* [PATCH wireless-drivers 0/3] fix multiple issues in mt76u error path
From: Lorenzo Bianconi @ 2019-02-10 21:49 UTC (permalink / raw)
To: linux-wireless; +Cc: nbd, sgruszka, stefan.wahren
Fix following issues in mt76u initialization error path:
- NULL pointer dereference in mt76u_mcu_deinit
- possible memory leak in mt76u_buf_free
- use-after-free warning since mt76u_queues_deinit is run twice
This series has been tested running mt76x0u driver on rpi3+
(dwc_otg controller does not support SG I/O)
Lorenzo Bianconi (3):
mt76: usb: fix possible NULL pointer dereference in mt76u_mcu_deinit
mt76: usb: fix possible memory leak in mt76u_buf_free
mt76: usb: do not run mt76u_queues_deinit twice
drivers/net/wireless/mediatek/mt76/usb.c | 25 ++++++++++----------
drivers/net/wireless/mediatek/mt76/usb_mcu.c | 8 ++++---
2 files changed, 17 insertions(+), 16 deletions(-)
--
2.20.1
^ permalink raw reply
* [RFC PATCH v3 03/12] mac80211: IEEE 802.11 Extended Key ID support
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
Add support for Extended Key ID as defined in IEEE 802.11-2016.
- Implement the nl80211 API for Extended Key ID
- Extend mac80211 API to allow drivers to support Extended Key ID
- Add handling for Rx-only keys (including tailroom_need_count)
- Select the decryption key based on the MPDU keyid
- Enforce cipher does not change when replacing a key.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
include/net/mac80211.h | 19 ++++-
net/mac80211/cfg.c | 38 ++++++++++
net/mac80211/debugfs.c | 1 +
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/key.c | 138 +++++++++++++++++++++++++++++--------
net/mac80211/key.h | 4 ++
net/mac80211/main.c | 5 ++
net/mac80211/rx.c | 74 ++++++++++----------
net/mac80211/sta_info.c | 9 +++
net/mac80211/sta_info.h | 2 +-
net/mac80211/tx.c | 13 +---
11 files changed, 227 insertions(+), 78 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index de866a7253c9..e16bc7623dc0 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1804,13 +1804,22 @@ struct ieee80211_cipher_scheme {
* enum set_key_cmd - key command
*
* Used with the set_key() callback in &struct ieee80211_ops, this
- * indicates whether a key is being removed or added.
+ * indicates which action has to be performed with the key.
*
- * @SET_KEY: a key is set
+ * @SET_KEY: a key is set and valid for Rx and Tx immediately
* @DISABLE_KEY: a key must be disabled
+ *
+ * Additional commands for drivers supporting Extended Key ID:
+ *
+ * @EXT_SET_KEY: a new key must be set but is only valid for decryption
+ * @EXT_KEY_RX_TX: a key installed with @EXT_SET_KEY is becoming the
+ * designated Rx/Tx key for the station
*/
enum set_key_cmd {
- SET_KEY, DISABLE_KEY,
+ SET_KEY,
+ DISABLE_KEY,
+ EXT_SET_KEY,
+ EXT_KEY_RX_TX,
};
/**
@@ -2219,6 +2228,9 @@ struct ieee80211_txq {
* @IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN: Driver does not report accurate A-MPDU
* length in tx status information
*
+ * @IEEE80211_HW_EXT_KEY_ID_NATIVE: Driver and hardware are supporting Extended
+ * Key ID and can handle two unicast keys per station for Rx and Tx.
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -2268,6 +2280,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW,
IEEE80211_HW_STA_MMPDU_TXQ,
IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN,
+ IEEE80211_HW_EXT_KEY_ID_NATIVE,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d65aa019ce85..a032da64eed2 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -351,6 +351,38 @@ static int ieee80211_set_noack_map(struct wiphy *wiphy,
return 0;
}
+static int ieee80211_set_tx_key(struct ieee80211_sub_if_data *sdata,
+ const u8 *mac_addr, u8 key_idx)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_key *key;
+ struct sta_info *sta;
+ int ret;
+
+ if (!wiphy_ext_feature_isset(local->hw.wiphy,
+ NL80211_EXT_FEATURE_EXT_KEY_ID))
+ return -EINVAL;
+
+ sta = sta_info_get_bss(sdata, mac_addr);
+
+ if (!sta)
+ return -EINVAL;
+
+ if (sta->ptk_idx == key_idx)
+ return 0;
+
+ mutex_lock(&local->key_mtx);
+ key = key_mtx_dereference(local, sta->ptk[key_idx]);
+
+ if (key && key->flags & KEY_FLAG_RX_ONLY)
+ ret = ieee80211_key_activate_tx(key);
+ else
+ ret = -EINVAL;
+
+ mutex_unlock(&local->key_mtx);
+ return ret;
+}
+
static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params)
@@ -365,6 +397,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
if (!ieee80211_sdata_running(sdata))
return -ENETDOWN;
+ if (pairwise && params->install_mode == NL80211_KEY_SWITCH_TX)
+ return ieee80211_set_tx_key(sdata, mac_addr, key_idx);
+
/* reject WEP and TKIP keys if WEP failed to initialize */
switch (params->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
@@ -396,6 +431,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
if (pairwise)
key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
+ if (params->install_mode == NL80211_KEY_RX_ONLY)
+ key->flags |= KEY_FLAG_RX_ONLY;
+
mutex_lock(&local->sta_mtx);
if (mac_addr) {
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 343ad0a915e4..334a9883894f 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -219,6 +219,7 @@ static const char *hw_flag_names[] = {
FLAG(SUPPORTS_VHT_EXT_NSS_BW),
FLAG(STA_MMPDU_TXQ),
FLAG(TX_STATUS_NO_AMPDU_LEN),
+ FLAG(EXT_KEY_ID_NATIVE),
#undef FLAG
};
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 056b16bce3b0..cbc35a31adc5 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1263,7 +1263,7 @@ struct ieee80211_local {
/*
* Key mutex, protects sdata's key_list and sta_info's
- * key pointers (write access, they're RCU.)
+ * key pointers and @ptk_idx (write access, they're RCU.)
*/
struct mutex key_mtx;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index b9f2bfc00263..d91503de1e1d 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -127,8 +127,13 @@ static void decrease_tailroom_need_count(struct ieee80211_sub_if_data *sdata,
static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
{
struct ieee80211_sub_if_data *sdata = key->sdata;
+ struct ieee80211_local *local = key->local;
struct sta_info *sta;
+ bool rx_only = key->flags & KEY_FLAG_RX_ONLY;
+ bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
+ bool ext_native = ieee80211_hw_check(&local->hw, EXT_KEY_ID_NATIVE);
int ret = -EOPNOTSUPP;
+ int cmd;
might_sleep();
@@ -150,10 +155,10 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
return -EINVAL;
}
- if (!key->local->ops->set_key)
+ if (!local->ops->set_key)
goto out_unsupported;
- assert_key_lock(key->local);
+ assert_key_lock(local);
sta = key->sta;
@@ -161,8 +166,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
* If this is a per-STA GTK, check if it
* is supported; if not, return.
*/
- if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) &&
- !ieee80211_hw_check(&key->local->hw, SUPPORTS_PER_STA_GTK))
+ if (sta && !pairwise &&
+ !ieee80211_hw_check(&local->hw, SUPPORTS_PER_STA_GTK))
goto out_unsupported;
if (sta && !sta->uploaded)
@@ -173,19 +178,25 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
* The driver doesn't know anything about VLAN interfaces.
* Hence, don't send GTKs for VLAN interfaces to the driver.
*/
- if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+ if (!pairwise) {
ret = 1;
goto out_unsupported;
}
}
- ret = drv_set_key(key->local, SET_KEY, sdata,
+ if (rx_only)
+ cmd = EXT_SET_KEY;
+ else
+ cmd = SET_KEY;
+
+ ret = drv_set_key(local, cmd, sdata,
sta ? &sta->sta : NULL, &key->conf);
if (!ret) {
key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
- if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ if (!(rx_only ||
+ key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
decrease_tailroom_need_count(sdata, 1);
@@ -221,7 +232,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
/* all of these we can do in software - if driver can */
if (ret == 1)
return 0;
- if (ieee80211_hw_check(&key->local->hw, SW_CRYPTO_CONTROL))
+ if (ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL))
return -EINVAL;
return 0;
default:
@@ -248,7 +259,8 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
sta = key->sta;
sdata = key->sdata;
- if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ if (!(key->flags & KEY_FLAG_RX_ONLY ||
+ key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
increment_tailroom_need_count(sdata);
@@ -264,9 +276,55 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
sta ? sta->sta.addr : bcast_addr, ret);
}
+int ieee80211_key_activate_tx(struct ieee80211_key *key)
+{
+ struct ieee80211_sub_if_data *sdata = key->sdata;
+ struct sta_info *sta = key->sta;
+ struct ieee80211_local *local = key->local;
+ struct ieee80211_key *old;
+ int ret;
+
+ assert_key_lock(local);
+
+ key->flags &= ~KEY_FLAG_RX_ONLY;
+
+ if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
+ key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
+ IEEE80211_KEY_FLAG_RESERVE_TAILROOM))
+ increment_tailroom_need_count(sdata);
+
+ if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+ ret = drv_set_key(local, EXT_KEY_RX_TX, sdata,
+ &sta->sta, &key->conf);
+ if (ret) {
+ sdata_err(sdata,
+ "failed to activate key for Tx (%d, %pM)\n",
+ key->conf.keyidx, sta->sta.addr);
+ return ret;
+ }
+ }
+
+ old = key_mtx_dereference(local, sta->ptk[sta->ptk_idx]);
+ sta->ptk_idx = key->conf.keyidx;
+ ieee80211_check_fast_xmit(sta);
+
+ if (old) {
+ old->flags |= KEY_FLAG_RX_ONLY;
+
+ if (!(old->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
+ old->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
+ IEEE80211_KEY_FLAG_RESERVE_TAILROOM))
+ decrease_tailroom_need_count(sdata, 1);
+ }
+
+ return 0;
+}
+
static int ieee80211_hw_key_replace(struct ieee80211_key *old_key,
struct ieee80211_key *new_key,
- bool ptk0rekey)
+ bool pairwise)
{
struct ieee80211_sub_if_data *sdata;
struct ieee80211_local *local;
@@ -283,16 +341,17 @@ static int ieee80211_hw_key_replace(struct ieee80211_key *old_key,
assert_key_lock(old_key->local);
sta = old_key->sta;
- /* PTK only using key ID 0 needs special handling on rekey */
- if (new_key && sta && ptk0rekey) {
+ /* Unicast rekey without Extended Key ID needs special handling */
+ if (new_key && pairwise && sta &&
+ rcu_access_pointer(sta->ptk[sta->ptk_idx]) == old_key) {
local = old_key->local;
sdata = old_key->sdata;
- /* Stop TX till we are on the new key */
+ /* Stop Tx till we are on the new key */
old_key->flags |= KEY_FLAG_TAINTED;
ieee80211_clear_fast_xmit(sta);
- /* Aggregation sessions during rekey are complicated due to the
+ /* Aggregation sessions during rekey are complicated by the
* reorder buffer and retransmits. Side step that by blocking
* aggregation during rekey and tear down running sessions.
*/
@@ -400,10 +459,6 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
if (old) {
idx = old->conf.keyidx;
- /* TODO: proper implement and test "Extended Key ID for
- * Individually Addressed Frames" from IEEE 802.11-2016.
- * Till then always assume only key ID 0 is used for
- * pairwise keys.*/
ret = ieee80211_hw_key_replace(old, new, pairwise);
} else {
/* new must be provided in case old is not */
@@ -420,15 +475,19 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
if (sta) {
if (pairwise) {
rcu_assign_pointer(sta->ptk[idx], new);
- sta->ptk_idx = idx;
- if (new) {
+ if (new && !(new->flags & KEY_FLAG_RX_ONLY)) {
+ sta->ptk_idx = idx;
clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
ieee80211_check_fast_xmit(sta);
}
} else {
rcu_assign_pointer(sta->gtk[idx], new);
}
- if (new)
+ /* Only needed when transition from no key -> key.
+ * Still triggers unnecessary when using Extended Key ID
+ * and installing the second key ID the first time.
+ */
+ if (new && !old)
ieee80211_check_fast_rx(sta);
} else {
defunikey = old &&
@@ -664,6 +723,9 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key,
ieee80211_debugfs_key_remove(key);
+ if (key->flags & KEY_FLAG_RX_ONLY)
+ return;
+
if (delay_tailroom) {
/* see ieee80211_delayed_tailroom_dec */
sdata->crypto_tx_tailroom_pending_dec++;
@@ -744,16 +806,33 @@ int ieee80211_key_link(struct ieee80211_key *key,
* can cause warnings to appear.
*/
bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION;
- int ret;
+ bool rx_only = key->flags & KEY_FLAG_RX_ONLY;
+ int ret = -EOPNOTSUPP;
mutex_lock(&sdata->local->key_mtx);
- if (sta && pairwise)
+ if (sta && pairwise) {
+ struct ieee80211_key *alt_key;
+
old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]);
- else if (sta)
+ alt_key = key_mtx_dereference(sdata->local, sta->ptk[idx ^ 1]);
+
+ /* Don't allow pairwise keys to change cipher on rekey */
+ if (key &&
+ ((alt_key && alt_key->conf.cipher != key->conf.cipher) ||
+ (old_key && old_key->conf.cipher != key->conf.cipher)))
+ goto out;
+ } else if (sta) {
old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
- else
+ } else {
old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
+ }
+
+ /* Don't allow non-pairwise keys to change cipher on rekey */
+ if (!pairwise) {
+ if (key && old_key && old_key->conf.cipher != key->conf.cipher)
+ goto out;
+ }
/*
* Silently accept key re-installation without really installing the
@@ -769,7 +848,8 @@ int ieee80211_key_link(struct ieee80211_key *key,
key->sdata = sdata;
key->sta = sta;
- increment_tailroom_need_count(sdata);
+ if (!rx_only)
+ increment_tailroom_need_count(sdata);
ret = ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
@@ -823,7 +903,8 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
}
list_for_each_entry(key, &sdata->key_list, list) {
- increment_tailroom_need_count(sdata);
+ if (!(key->flags & KEY_FLAG_RX_ONLY))
+ increment_tailroom_need_count(sdata);
ieee80211_key_enable_hw_accel(key);
}
@@ -1193,7 +1274,8 @@ void ieee80211_remove_key(struct ieee80211_key_conf *keyconf)
if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
- if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ if (!(key->flags & KEY_FLAG_RX_ONLY ||
+ key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
increment_tailroom_need_count(key->sdata);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index ebdb80b85dc3..1a3da999e0c4 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -18,6 +18,7 @@
#define NUM_DEFAULT_KEYS 4
#define NUM_DEFAULT_MGMT_KEYS 2
+#define INVALID_PTK_KEYIDX 2 /* Existing key slot never used by PTK keys */
struct ieee80211_local;
struct ieee80211_sub_if_data;
@@ -30,11 +31,13 @@ struct sta_info;
* in the hardware for TX crypto hardware acceleration.
* @KEY_FLAG_TAINTED: Key is tainted and packets should be dropped.
* @KEY_FLAG_CIPHER_SCHEME: This key is for a hardware cipher scheme
+ * @KEY_FLAG_RX_ONLY: Pairwise key only allowed to be used on Rx.
*/
enum ieee80211_internal_key_flags {
KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0),
KEY_FLAG_TAINTED = BIT(1),
KEY_FLAG_CIPHER_SCHEME = BIT(2),
+ KEY_FLAG_RX_ONLY = BIT(3),
};
enum ieee80211_internal_tkip_state {
@@ -146,6 +149,7 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
int ieee80211_key_link(struct ieee80211_key *key,
struct ieee80211_sub_if_data *sdata,
struct sta_info *sta);
+int ieee80211_key_activate_tx(struct ieee80211_key *key);
void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom);
void ieee80211_key_free_unused(struct ieee80211_key *key);
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 71005b6dfcd1..ea34544985f3 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1051,6 +1051,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
}
}
+ /* mac80211 supports Extended Key ID when driver does */
+ if (ieee80211_hw_check(&local->hw, EXT_KEY_ID_NATIVE))
+ wiphy_ext_feature_set(local->hw.wiphy,
+ NL80211_EXT_FEATURE_EXT_KEY_ID);
+
/*
* Calculate scan IE length -- we need this to alloc
* memory and to subtract from the driver limit. It
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index bb4d71efb6fb..ce786311baf4 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -988,23 +988,43 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
return -1;
}
-static int ieee80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs,
- struct sk_buff *skb)
+static int ieee80211_get_keyid(struct sk_buff *skb,
+ const struct ieee80211_cipher_scheme *cs)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc;
int hdrlen;
+ int minlen;
+ u8 key_idx_off;
+ u8 key_idx_shift;
u8 keyid;
fc = hdr->frame_control;
hdrlen = ieee80211_hdrlen(fc);
- if (skb->len < hdrlen + cs->hdr_len)
+ if (cs) {
+ minlen = hdrlen + cs->hdr_len;
+ key_idx_off = hdrlen + cs->key_idx_off;
+ key_idx_shift = cs->key_idx_shift;
+ } else {
+ /* WEP, TKIP, CCMP and GCMP have the key id at the same place */
+ minlen = hdrlen + IEEE80211_WEP_IV_LEN;
+ key_idx_off = hdrlen + 3;
+ key_idx_shift = 6;
+ }
+
+ if (unlikely(skb->len < minlen))
return -EINVAL;
- skb_copy_bits(skb, hdrlen + cs->key_idx_off, &keyid, 1);
- keyid &= cs->key_idx_mask;
- keyid >>= cs->key_idx_shift;
+ skb_copy_bits(skb, key_idx_off, &keyid, 1);
+
+ if (cs)
+ keyid &= cs->key_idx_mask;
+ keyid >>= key_idx_shift;
+
+ /* cs could use more than the usual two bits for the keyid */
+ if (unlikely(keyid > NUM_DEFAULT_KEYS))
+ return -EINVAL;
return keyid;
}
@@ -1835,9 +1855,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
int keyidx;
- int hdrlen;
ieee80211_rx_result result = RX_DROP_UNUSABLE;
struct ieee80211_key *sta_ptk = NULL;
+ struct ieee80211_key *ptk_idx = NULL;
int mmie_keyidx = -1;
__le16 fc;
const struct ieee80211_cipher_scheme *cs = NULL;
@@ -1875,21 +1895,24 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
if (rx->sta) {
int keyid = rx->sta->ptk_idx;
+ sta_ptk = rcu_dereference(rx->sta->ptk[keyid]);
- if (ieee80211_has_protected(fc) && rx->sta->cipher_scheme) {
+ if (ieee80211_has_protected(fc)) {
cs = rx->sta->cipher_scheme;
- keyid = ieee80211_get_cs_keyid(cs, rx->skb);
+ keyid = ieee80211_get_keyid(rx->skb, cs);
+
if (unlikely(keyid < 0))
return RX_DROP_UNUSABLE;
+
+ ptk_idx = rcu_dereference(rx->sta->ptk[keyid]);
}
- sta_ptk = rcu_dereference(rx->sta->ptk[keyid]);
}
if (!ieee80211_has_protected(fc))
mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) {
- rx->key = sta_ptk;
+ rx->key = ptk_idx ? ptk_idx : sta_ptk;
if ((status->flag & RX_FLAG_DECRYPTED) &&
(status->flag & RX_FLAG_IV_STRIPPED))
return RX_CONTINUE;
@@ -1949,8 +1972,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
}
return RX_CONTINUE;
} else {
- u8 keyid;
-
/*
* The device doesn't give us the IV so we won't be
* able to look up the key. That's ok though, we
@@ -1964,23 +1985,10 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
(status->flag & RX_FLAG_IV_STRIPPED))
return RX_CONTINUE;
- hdrlen = ieee80211_hdrlen(fc);
-
- if (cs) {
- keyidx = ieee80211_get_cs_keyid(cs, rx->skb);
+ keyidx = ieee80211_get_keyid(rx->skb, cs);
- if (unlikely(keyidx < 0))
- return RX_DROP_UNUSABLE;
- } else {
- if (rx->skb->len < 8 + hdrlen)
- return RX_DROP_UNUSABLE; /* TODO: count this? */
- /*
- * no need to call ieee80211_wep_get_keyidx,
- * it verifies a bunch of things we've done already
- */
- skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
- keyidx = keyid >> 6;
- }
+ if (unlikely(keyidx < 0))
+ return RX_DROP_UNUSABLE;
/* check per-station GTK first, if multicast packet */
if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
@@ -4020,12 +4028,8 @@ void ieee80211_check_fast_rx(struct sta_info *sta)
case WLAN_CIPHER_SUITE_GCMP_256:
break;
default:
- /* we also don't want to deal with WEP or cipher scheme
- * since those require looking up the key idx in the
- * frame, rather than assuming the PTK is used
- * (we need to revisit this once we implement the real
- * PTK index, which is now valid in the spec, but we
- * haven't implemented that part yet)
+ /* We also don't want to deal with
+ * WEP or cipher scheme.
*/
goto clear_rcu;
}
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 11f058987a54..09c69955c6e3 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -347,6 +347,15 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta->sta.max_rx_aggregation_subframes =
local->hw.max_rx_aggregation_subframes;
+ /* Extended Key ID can install keys for keyid 0 and 1 as Rx only.
+ * Tx starts uses a key as soon as a key is installed in the slot
+ * ptk_idx references to. To avoid using the initial Rx key prematurely
+ * for Tx we initialize ptk_idx to a value never used, making sure the
+ * referenced key is always NULL till ptk_idx is set to a valid value.
+ */
+ BUILD_BUG_ON(ARRAY_SIZE(sta->ptk) <= INVALID_PTK_KEYIDX);
+ sta->ptk_idx = INVALID_PTK_KEYIDX;
+
sta->local = local;
sta->sdata = sdata;
sta->rx_stats.last_rx = jiffies;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 71f7e4973329..304a7ea24757 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -449,7 +449,7 @@ struct ieee80211_sta_rx_stats {
* @local: pointer to the global information
* @sdata: virtual interface this station belongs to
* @ptk: peer keys negotiated with this station, if any
- * @ptk_idx: last installed peer key index
+ * @ptk_idx: peer key index to use for transmissions
* @gtk: group keys negotiated with this station, if any
* @rate_ctrl: rate control algorithm reference
* @rate_ctrl_lock: spinlock used to protect rate control data
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 8a49a74c0a37..111bd6c490a6 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3000,23 +3000,15 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
switch (build.key->conf.cipher) {
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
- /* add fixed key ID */
- if (gen_iv) {
- (build.hdr + build.hdr_len)[3] =
- 0x20 | (build.key->conf.keyidx << 6);
+ if (gen_iv)
build.pn_offs = build.hdr_len;
- }
if (gen_iv || iv_spc)
build.hdr_len += IEEE80211_CCMP_HDR_LEN;
break;
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
- /* add fixed key ID */
- if (gen_iv) {
- (build.hdr + build.hdr_len)[3] =
- 0x20 | (build.key->conf.keyidx << 6);
+ if (gen_iv)
build.pn_offs = build.hdr_len;
- }
if (gen_iv || iv_spc)
build.hdr_len += IEEE80211_GCMP_HDR_LEN;
break;
@@ -3383,6 +3375,7 @@ static void ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata,
pn = atomic64_inc_return(&key->conf.tx_pn);
crypto_hdr[0] = pn;
crypto_hdr[1] = pn >> 8;
+ crypto_hdr[3] = 0x20 | (key->conf.keyidx << 6);
crypto_hdr[4] = pn >> 16;
crypto_hdr[5] = pn >> 24;
crypto_hdr[6] = pn >> 32;
--
2.20.1
^ permalink raw reply related
* [RFC PATCH v3 10/12] ath5k: ath_key_config() API compatibility update
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
Update ath_key_config() call to work with Extended Key ID update for ath.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
This patch is only provided to not break compile for ath5k.
(ath5k is very likely also able to support Extended Key ID is
Compatibility mode.)
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 16e052d02c94..cbabb784decb 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -509,7 +509,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
switch (cmd) {
case SET_KEY:
- ret = ath_key_config(common, vif, sta, key);
+ ret = ath_key_config(common, vif, sta, key, true);
if (ret >= 0) {
key->hw_key_idx = ret;
/* push IV and Michael MIC generation to stack */
--
2.20.1
^ permalink raw reply related
* [RFC PATCH v3 06/12] mac80211_hwsim: Ext Key ID support (NATIVE)
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
Driver is not supporting hardware encryption and therefore fully
compatible with Extended Key ID.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
drivers/net/wireless/mac80211_hwsim.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 87be2b18063a..306583316f5d 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2799,6 +2799,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
ieee80211_hw_set(hw, SIGNAL_DBM);
ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, TDLS_WIDER_BW);
+ ieee80211_hw_set(hw, EXT_KEY_ID_NATIVE);
if (rctbl)
ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
--
2.20.1
^ 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