Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH v3 2/3] mt76usb: use synchronous msg for mcu command responses
From: Lorenzo Bianconi @ 2019-02-22 12:00 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: Felix Fietkau, linux-wireless
In-Reply-To: <20190222115446.GA5720@redhat.com>

> On Fri, Feb 22, 2019 at 10:53:19AM +0100, Lorenzo Bianconi wrote:
> > > Use usb_bulk_msg for reading MCU command responses. This simplify code
> > > a lot.
> > > 
> > > Together with 97a3005759c ("mt76usb: allow mt76u_bulk_msg be used
> > > for reads") it also fix possible problems with rx data buffers
> > > not being aligned and contained within single page. After doing
> > > page_frag_alloc(1024) consecutive page_frag_alloc(PAGE_SIZE) will
> > > alloc PAGE_SIZE buffer at PAGE_SIZE - 1024 offset.
> > > 
> > > Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> > > ---
> > >  drivers/net/wireless/mediatek/mt76/mt76.h          |  3 +-
> > >  drivers/net/wireless/mediatek/mt76/mt76x0/usb.c    | 11 --------
> > >  .../net/wireless/mediatek/mt76/mt76x02_usb_mcu.c   | 32 +++++++---------------
> > >  drivers/net/wireless/mediatek/mt76/mt76x2/usb.c    | 11 --------
> > >  drivers/net/wireless/mediatek/mt76/usb.c           |  1 -
> > >  drivers/net/wireless/mediatek/mt76/usb_mcu.c       | 31 +++------------------
> > >  6 files changed, 15 insertions(+), 74 deletions(-)
> > > 
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> > > index 6092646014c4..c9b5eb9b0582 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> > > @@ -384,8 +384,7 @@ struct mt76_usb {
> > >  
> > >  	struct mt76u_mcu {
> > >  		struct mutex mutex;
> > > -		struct completion cmpl;
> > 
> > Hi Stanislaw,
> > 
> > I was reviewing this approach and I guess it is a little bit racey since now we
> > are not sure that when the device is removed or suspended the pending mcu commands
> > are terminated and we do not have any api to stop usb transactions.
> > Are we sure when we access mt76x02_dev/mt76_dev structure it has not been
> > already removed?
> > Maybe we need to maintain the completion in mt76u_mcu and use it to wait the mcu
> > commands are terminated.
> 
> I don't think so. On suspend we do mt76xxu_mac_stop() which access registers
> using mcu commands, all should be synchronized by mcu->mutex . All other
> process that could use mcu command should be already stopped. Actually suspend
> can be simplified.

ack, I missed mcu->mutex. Thx.

Regards,
Lorenzo

> 
> Device remove should be properly handled by -ENODEV error returned by
> usb_bulk_msg.
> 
> Stanislaw

^ permalink raw reply

* Re: [PATCH v3 2/3] mt76usb: use synchronous msg for mcu command responses
From: Stanislaw Gruszka @ 2019-02-22 11:54 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: Felix Fietkau, linux-wireless
In-Reply-To: <20190222095318.GA14269@localhost.localdomain>

On Fri, Feb 22, 2019 at 10:53:19AM +0100, Lorenzo Bianconi wrote:
> > Use usb_bulk_msg for reading MCU command responses. This simplify code
> > a lot.
> > 
> > Together with 97a3005759c ("mt76usb: allow mt76u_bulk_msg be used
> > for reads") it also fix possible problems with rx data buffers
> > not being aligned and contained within single page. After doing
> > page_frag_alloc(1024) consecutive page_frag_alloc(PAGE_SIZE) will
> > alloc PAGE_SIZE buffer at PAGE_SIZE - 1024 offset.
> > 
> > Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> > ---
> >  drivers/net/wireless/mediatek/mt76/mt76.h          |  3 +-
> >  drivers/net/wireless/mediatek/mt76/mt76x0/usb.c    | 11 --------
> >  .../net/wireless/mediatek/mt76/mt76x02_usb_mcu.c   | 32 +++++++---------------
> >  drivers/net/wireless/mediatek/mt76/mt76x2/usb.c    | 11 --------
> >  drivers/net/wireless/mediatek/mt76/usb.c           |  1 -
> >  drivers/net/wireless/mediatek/mt76/usb_mcu.c       | 31 +++------------------
> >  6 files changed, 15 insertions(+), 74 deletions(-)
> > 
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> > index 6092646014c4..c9b5eb9b0582 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> > @@ -384,8 +384,7 @@ struct mt76_usb {
> >  
> >  	struct mt76u_mcu {
> >  		struct mutex mutex;
> > -		struct completion cmpl;
> 
> Hi Stanislaw,
> 
> I was reviewing this approach and I guess it is a little bit racey since now we
> are not sure that when the device is removed or suspended the pending mcu commands
> are terminated and we do not have any api to stop usb transactions.
> Are we sure when we access mt76x02_dev/mt76_dev structure it has not been
> already removed?
> Maybe we need to maintain the completion in mt76u_mcu and use it to wait the mcu
> commands are terminated.

I don't think so. On suspend we do mt76xxu_mac_stop() which access registers
using mcu commands, all should be synchronized by mcu->mutex . All other
process that could use mcu command should be already stopped. Actually suspend
can be simplified.

Device remove should be properly handled by -ENODEV error returned by
usb_bulk_msg.

Stanislaw

^ permalink raw reply

* Re: [PATCH] iw: allow to set wmm parameters from iw
From: Johannes Berg @ 2019-02-22 11:03 UTC (permalink / raw)
  To: Andrea Greco; +Cc: johannes.berg, linux-wireless, Andrea Greco
In-Reply-To: <20190221231807.6969-1-andrea.greco.gapmilano@gmail.com>

Andrea Greco <a.greco@4sigma.it> wrote:

> From: Andrea Greco <a.greco@4sigma.it>

please review the contributing file and resend your patch with signed-
off-by. also, i think the printf shouldn't be there.

Patch set to Changes Requested.

-- 
https://patchwork.kernel.org/patch/10824843/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


^ permalink raw reply

* Re: [PATCH 1/5] net: dsa: fix a leaked reference by adding a missing of_node_put
From: Linus Walleij @ 2019-02-22 10:38 UTC (permalink / raw)
  To: Wen Yang
  Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, David S. Miller,
	netdev, linux-kernel@vger.kernel.org, Alexandre Belloni,
	UNGLinuxDriver, Felix Fietkau, Lorenzo Bianconi, Kalle Valo,
	Matthias Brugger, linux-wireless, Linux ARM,
	moderated list:ARM/Mediatek SoC support, anirudh, John Linn,
	Michal Simek, wang.yi59
In-Reply-To: <1550819742-32155-1-git-send-email-wen.yang99@zte.com.cn>

On Fri, Feb 22, 2019 at 8:15 AM Wen Yang <wen.yang99@zte.com.cn> wrote:

> The call to of_get_child_by_name returns a node pointer with refcount
> incremented thus it must be explicitly decremented after the last
> usage.
>
> Detected by coccinelle with the following warnings:
> ./drivers/net/dsa/rtl8366rb.c:510:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.
> ./drivers/net/dsa/rtl8366rb.c:518:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.
> ./drivers/net/dsa/rtl8366rb.c:540:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.
> ./drivers/net/dsa/rtl8366rb.c:548:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.
> ./drivers/net/dsa/rtl8366rb.c:556:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.
> ./drivers/net/dsa/rtl8366rb.c:561:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.
>
> Signed-off-by: Wen Yang <wen.yang99@zte.com.cn>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Vivien Didelot <vivien.didelot@gmail.com>
> Cc: Florian Fainelli <f.fainelli@gmail.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: netdev@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org

Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCH v3 2/3] mt76usb: use synchronous msg for mcu command responses
From: Lorenzo Bianconi @ 2019-02-22  9:53 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: Felix Fietkau, linux-wireless
In-Reply-To: <1550679320-14343-2-git-send-email-sgruszka@redhat.com>

> Use usb_bulk_msg for reading MCU command responses. This simplify code
> a lot.
> 
> Together with 97a3005759c ("mt76usb: allow mt76u_bulk_msg be used
> for reads") it also fix possible problems with rx data buffers
> not being aligned and contained within single page. After doing
> page_frag_alloc(1024) consecutive page_frag_alloc(PAGE_SIZE) will
> alloc PAGE_SIZE buffer at PAGE_SIZE - 1024 offset.
> 
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> ---
>  drivers/net/wireless/mediatek/mt76/mt76.h          |  3 +-
>  drivers/net/wireless/mediatek/mt76/mt76x0/usb.c    | 11 --------
>  .../net/wireless/mediatek/mt76/mt76x02_usb_mcu.c   | 32 +++++++---------------
>  drivers/net/wireless/mediatek/mt76/mt76x2/usb.c    | 11 --------
>  drivers/net/wireless/mediatek/mt76/usb.c           |  1 -
>  drivers/net/wireless/mediatek/mt76/usb_mcu.c       | 31 +++------------------
>  6 files changed, 15 insertions(+), 74 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 6092646014c4..c9b5eb9b0582 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -384,8 +384,7 @@ struct mt76_usb {
>  
>  	struct mt76u_mcu {
>  		struct mutex mutex;
> -		struct completion cmpl;

Hi Stanislaw,

I was reviewing this approach and I guess it is a little bit racey since now we
are not sure that when the device is removed or suspended the pending mcu commands
are terminated and we do not have any api to stop usb transactions.
Are we sure when we access mt76x02_dev/mt76_dev structure it has not been
already removed?
Maybe we need to maintain the completion in mt76u_mcu and use it to wait the mcu
commands are terminated.

Regards,
Lorenzo

> -		struct mt76u_buf res;
> +		u8 *data;
>  		u32 msg_seq;
>  
>  		/* multiple reads */
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
> index da9d05f6074d..f0c33890f1a5 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
> @@ -311,13 +311,11 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf,
>  					 pm_message_t state)
>  {
>  	struct mt76x02_dev *dev = usb_get_intfdata(usb_intf);
> -	struct mt76_usb *usb = &dev->mt76.usb;
>  
>  	mt76u_stop_queues(&dev->mt76);
>  	mt76x0u_mac_stop(dev);
>  	clear_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
>  	mt76x0_chip_onoff(dev, false, false);
> -	usb_kill_urb(usb->mcu.res.urb);
>  
>  	return 0;
>  }
> @@ -328,15 +326,6 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
>  	struct mt76_usb *usb = &dev->mt76.usb;
>  	int ret;
>  
> -	reinit_completion(&usb->mcu.cmpl);
> -	ret = mt76u_submit_buf(&dev->mt76, USB_DIR_IN,
> -			       MT_EP_IN_CMD_RESP,
> -			       &usb->mcu.res, GFP_KERNEL,
> -			       mt76u_mcu_complete_urb,
> -			       &usb->mcu.cmpl);
> -	if (ret < 0)
> -		goto err;
> -
>  	ret = mt76u_submit_rx_buffers(&dev->mt76);
>  	if (ret < 0)
>  		goto err;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
> index f497c8e4332a..0cb8751321a1 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
> @@ -61,33 +61,21 @@ mt76x02u_multiple_mcu_reads(struct mt76_dev *dev, u8 *data, int len)
>  static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq)
>  {
>  	struct mt76_usb *usb = &dev->usb;
> -	struct mt76u_buf *buf = &usb->mcu.res;
> -	struct urb *urb = buf->urb;
> -	u8 *data = buf->buf;
> -	int i, ret;
> +	u8 *data = usb->mcu.data;
> +	int i, len, ret;
>  	u32 rxfce;
>  
>  	for (i = 0; i < 5; i++) {
> -		if (!wait_for_completion_timeout(&usb->mcu.cmpl,
> -						 msecs_to_jiffies(300)))
> +		ret = mt76u_bulk_msg(dev, data, MCU_RESP_URB_SIZE, &len, 300);
> +		if (ret == -ETIMEDOUT)
>  			continue;
> -
> -		if (urb->status)
> -			return -EIO;
> +		if (ret)
> +			goto out;
>  
>  		if (usb->mcu.rp)
> -			mt76x02u_multiple_mcu_reads(dev, data + 4,
> -						    urb->actual_length - 8);
> +			mt76x02u_multiple_mcu_reads(dev, data + 4, len - 8);
>  
>  		rxfce = get_unaligned_le32(data);
> -		ret = mt76u_submit_buf(dev, USB_DIR_IN,
> -				       MT_EP_IN_CMD_RESP,
> -				       buf, GFP_KERNEL,
> -				       mt76u_mcu_complete_urb,
> -				       &usb->mcu.cmpl);
> -		if (ret)
> -			return ret;
> -
>  		if (seq == FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, rxfce) &&
>  		    FIELD_GET(MT_RX_FCE_INFO_EVT_TYPE, rxfce) == EVT_CMD_DONE)
>  			return 0;
> @@ -96,9 +84,9 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq)
>  			FIELD_GET(MT_RX_FCE_INFO_EVT_TYPE, rxfce),
>  			seq, FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, rxfce));
>  	}
> -
> -	dev_err(dev->dev, "error: %s timed out\n", __func__);
> -	return -ETIMEDOUT;
> +out:
> +	dev_err(dev->dev, "error: %s failed with %d\n", __func__, ret);
> +	return ret;
>  }
>  
>  static int
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
> index f81a85e96922..ddb6b2c48e01 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
> @@ -100,11 +100,9 @@ static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf,
>  					  pm_message_t state)
>  {
>  	struct mt76x02_dev *dev = usb_get_intfdata(intf);
> -	struct mt76_usb *usb = &dev->mt76.usb;
>  
>  	mt76u_stop_queues(&dev->mt76);
>  	mt76x2u_stop_hw(dev);
> -	usb_kill_urb(usb->mcu.res.urb);
>  
>  	return 0;
>  }
> @@ -115,15 +113,6 @@ static int __maybe_unused mt76x2u_resume(struct usb_interface *intf)
>  	struct mt76_usb *usb = &dev->mt76.usb;
>  	int err;
>  
> -	reinit_completion(&usb->mcu.cmpl);
> -	err = mt76u_submit_buf(&dev->mt76, USB_DIR_IN,
> -			       MT_EP_IN_CMD_RESP,
> -			       &usb->mcu.res, GFP_KERNEL,
> -			       mt76u_mcu_complete_urb,
> -			       &usb->mcu.cmpl);
> -	if (err < 0)
> -		goto err;
> -
>  	err = mt76u_submit_rx_buffers(&dev->mt76);
>  	if (err < 0)
>  		goto err;
> diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
> index 78191968b4fa..5c3b7f735aae 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> @@ -933,7 +933,6 @@ int mt76u_init(struct mt76_dev *dev,
>  	INIT_DELAYED_WORK(&usb->stat_work, mt76u_tx_status_data);
>  	skb_queue_head_init(&dev->rx_skb[MT_RXQ_MAIN]);
>  
> -	init_completion(&usb->mcu.cmpl);
>  	mutex_init(&usb->mcu.mutex);
>  
>  	mutex_init(&usb->usb_ctrl_mtx);
> diff --git a/drivers/net/wireless/mediatek/mt76/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/usb_mcu.c
> index 72c8607da4b4..747231edc57d 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb_mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb_mcu.c
> @@ -16,42 +16,19 @@
>  
>  #include "mt76.h"
>  
> -void mt76u_mcu_complete_urb(struct urb *urb)
> -{
> -	struct completion *cmpl = urb->context;
> -
> -	complete(cmpl);
> -}
> -EXPORT_SYMBOL_GPL(mt76u_mcu_complete_urb);
> -
>  int mt76u_mcu_init_rx(struct mt76_dev *dev)
>  {
>  	struct mt76_usb *usb = &dev->usb;
> -	int err;
>  
> -	err = mt76u_buf_alloc(dev, &usb->mcu.res, MCU_RESP_URB_SIZE,
> -			      MCU_RESP_URB_SIZE, GFP_KERNEL);
> -	if (err < 0)
> -		return err;
> -
> -	err = mt76u_submit_buf(dev, USB_DIR_IN, MT_EP_IN_CMD_RESP,
> -			       &usb->mcu.res, GFP_KERNEL,
> -			       mt76u_mcu_complete_urb,
> -			       &usb->mcu.cmpl);
> -	if (err < 0)
> -		mt76u_buf_free(&usb->mcu.res);
> -
> -	return err;
> +	usb->mcu.data = kmalloc(MCU_RESP_URB_SIZE, GFP_KERNEL);
> +	return usb->mcu.data ? 0 : -ENOMEM;
>  }
>  EXPORT_SYMBOL_GPL(mt76u_mcu_init_rx);
>  
>  void mt76u_mcu_deinit(struct mt76_dev *dev)
>  {
> -	struct mt76u_buf *buf = &dev->usb.mcu.res;
> +	struct mt76_usb *usb = &dev->usb;
>  
> -	if (buf->urb) {
> -		usb_kill_urb(buf->urb);
> -		mt76u_buf_free(buf);
> -	}
> +	kfree(usb->mcu.data);
>  }
>  EXPORT_SYMBOL_GPL(mt76u_mcu_deinit);
> -- 
> 2.7.5
> 

^ permalink raw reply

* [PATCH] cfg80211: reg: Fix use-after-free in call_crda
From: Yue Haibing @ 2019-02-22  9:42 UTC (permalink / raw)
  To: johannes, davem; +Cc: linux-kernel, netdev, linux-wireless, YueHaibing

From: YueHaibing <yuehaibing@huawei.com>

KASAN report this:

BUG: KASAN: use-after-free in kobject_uevent_env+0xedb/0xf20 lib/kobject_uevent.c:474
Read of size 8 at addr ffff8881e52d5dc0 by task kworker/0:2/1066

CPU: 0 PID: 1066 Comm: kworker/0:2 Not tainted 5.0.0-rc7+ #45
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
Workqueue: events reg_todo [cfg80211]
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0xfa/0x1ce lib/dump_stack.c:113
 print_address_description+0x65/0x270 mm/kasan/report.c:187
 kasan_report+0x149/0x18d mm/kasan/report.c:317
 kobject_uevent_env+0xedb/0xf20 lib/kobject_uevent.c:474
 reg_query_database+0x23e/0x390 [cfg80211]
 reg_process_hint+0x34a/0xc00 [cfg80211]
 reg_todo+0x3f0/0xa80 [cfg80211]
 process_one_work+0xc4d/0x1b40 kernel/workqueue.c:2173
 worker_thread+0x171/0x1130 kernel/workqueue.c:2319
 kthread+0x302/0x3c0 kernel/kthread.c:246
 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352

Allocated by task 3500:
 set_track mm/kasan/common.c:85 [inline]
 __kasan_kmalloc.constprop.3+0xa0/0xd0 mm/kasan/common.c:496
 kmalloc include/linux/slab.h:550 [inline]
 kzalloc include/linux/slab.h:740 [inline]
 platform_device_alloc+0x2a/0xf0 drivers/base/platform.c:268
 platform_device_register_full+0x6d/0x4d0 drivers/base/platform.c:509
 regulatory_init+0x13c/0x5e0 [cfg80211]
 cfg80211_init+0x7a/0x10f [cfg80211]
 do_one_initcall+0xfa/0x5ca init/main.c:887
 do_init_module+0x204/0x5f6 kernel/module.c:3460
 load_module+0x66b2/0x8570 kernel/module.c:3808
 __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902
 do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290
 entry_SYSCALL_64_after_hwframe+0x49/0xbe

Freed by task 2957:
 set_track mm/kasan/common.c:85 [inline]
 __kasan_slab_free+0x130/0x180 mm/kasan/common.c:458
 slab_free_hook mm/slub.c:1409 [inline]
 slab_free_freelist_hook mm/slub.c:1436 [inline]
 slab_free mm/slub.c:2986 [inline]
 kfree+0xe1/0x270 mm/slub.c:3938
 device_release+0x78/0x200 drivers/base/core.c:919
 kobject_cleanup lib/kobject.c:662 [inline]
 kobject_release lib/kobject.c:691 [inline]
 kref_put include/linux/kref.h:67 [inline]
 kobject_put+0x146/0x240 lib/kobject.c:708
 put_device+0x1c/0x30 drivers/base/core.c:2060
 request_firmware_work_func+0x16d/0x290 drivers/base/firmware_loader/main.c:786
 process_one_work+0xc4d/0x1b40 kernel/workqueue.c:2173
 worker_thread+0x171/0x1130 kernel/workqueue.c:2319
 kthread+0x302/0x3c0 kernel/kthread.c:246
 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352

The buggy address belongs to the object at ffff8881e52d5d80
 which belongs to the cache kmalloc-2k of size 2048
The buggy address is located 64 bytes inside of
 2048-byte region [ffff8881e52d5d80, ffff8881e52d6580)
The buggy address belongs to the page:
page:ffffea000794b400 count:1 mapcount:0 mapping:ffff8881f6c02800 index:0xffff8881e52d3300 compound_mapcount: 0
flags: 0x2fffc0000010200(slab|head)
raw: 02fffc0000010200 ffffea00079d5200 0000000400000004 ffff8881f6c02800
raw: ffff8881e52d3300 00000000800f000e 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff8881e52d5c80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ffff8881e52d5d00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff8881e52d5d80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                                           ^
 ffff8881e52d5e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff8881e52d5e80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb

In function reg_query_database, query_regdb_file call
request_firmware_nowait to do request_firmware asynchronously,
which need the caller hold the reference of dev, otherwise it will
do put_device freeing '&reg_pdev->dev'. After that, call_crda access
the dev will trigger use-after-free bug.
This patch fix this by holding a reference of dev in regulatory_init
after platform_device_register_simple registered successly, which
releasing in platform_device_unregister.

Reported-by: Hulk Robot <hulkci@huawei.com>
Fixes: 007f6c5e6eb4 ("cfg80211: support loading regulatory database as firmware file")
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
 net/wireless/reg.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index adfa58f..3de568f 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -3884,6 +3884,8 @@ int __init regulatory_init(void)
 	if (IS_ERR(reg_pdev))
 		return PTR_ERR(reg_pdev);
 
+	get_device(&reg_pdev->dev);
+
 	spin_lock_init(&reg_requests_lock);
 	spin_lock_init(&reg_pending_beacons_lock);
 	spin_lock_init(&reg_indoor_lock);
-- 
2.7.4



^ permalink raw reply related

* Re: [RFC PATCH v3 04/12] mac80211: Compatibility Extended Key ID support
From: Johannes Berg @ 2019-02-22  8:53 UTC (permalink / raw)
  To: Alexander Wetzel; +Cc: linux-wireless
In-Reply-To: <bad49ffb-5334-03f5-62e0-4f06d7c36242@wetzel-home.de>

On Thu, 2019-02-21 at 21:07 +0100, Alexander Wetzel wrote:
> > 
> > > +	if (!ext_native && key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
> > > +		key->flags |= KEY_FLAG_RX_SW_CRYPTO;
> > > +		/* Activate Rx crypto offload after max 10s when idle */
> > > +		ieee80211_queue_delayed_work(&local->hw, &sta->ext_key_compat_wk,
> > > +					     round_jiffies_relative(HZ * 10));
> > > +	}
> > 
> > Is there much point in this?
> > 
> > > +		if (unlikely(rx->key->flags & KEY_FLAG_RX_SW_CRYPTO)) {
> > > +			rx->key->flags &= ~KEY_FLAG_RX_SW_CRYPTO;
> > > +			cancel_delayed_work(&rx->sta->ext_key_compat_wk);
> > > +			ieee80211_queue_delayed_work(&rx->local->hw,
> > > +						     &rx->sta->ext_key_compat_wk, 0);
> > > +		}
> > 
> > We'll almost certainly do it from here, so never exercise the other
> > path?
> 
> This is mostly to have a definite time we know the new key is used also 
> for RX. In probably 99.9% of all cases it will be triggered from the Rx 
> path.
> Some special purpose devices may not send any packets for a long time 
> and trigger the fallback, as (wrong) firewall rules. (I've e.g. tested 
> it by dropping all outgoing packets on the remote sta.)
> 
> The idea was to be sure that a rekey intervall >10s prevents activating 
> Rx crypt when rekeying the next key. Which now sounds kind of thin...

Not sure I even understand this?

You meant "Rx crypto offload"? I'm not really sure we _care_ that much?

Then again, an issue may be that some firmware may want (need) the keys
for RX so it can look at certain frames (action frames?) itself. So if
we never install the RX key and then only get an action frame that the
firmware should handle, we lose. Such firmware could not support COMPAT
mode then I guess, which may mean a bunch of iwlwifi devices shouldn't
use COMPAT mode.

johannes


^ permalink raw reply

* Re: [PATCH v2] iwlwifi: mvm: Use div_s64 instead of do_div in iwl_mvm_debug_range_resp
From: Arnd Bergmann @ 2019-02-22  8:52 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Nathan Chancellor, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Kalle Valo, linux-wireless, Networking,
	LKML
In-Reply-To: <CAKwvOdmCeHxiGPkXXzjwnTtgzEDDjYRE1QBdu7BHeuzCE4YtRA@mail.gmail.com>

On Fri, Feb 22, 2019 at 1:14 AM Nick Desaulniers
<ndesaulniers@google.com> wrote:
> On Thu, Feb 21, 2019 at 12:08 AM Nathan Chancellor <natechancellor@gmail.com> wrote:

> One thing I'm curious about, is "why does do_div exist?" When should I
> use do_div vs div_u64 (not div_s64 as is used in this patch)?

I think do_div() is mostly historic, we've had it since the early days
when C compilers were not as good with inline functions. The various
other versions are regular functions, and I tend to prefer them for new
code, but do_div() is widely known and documented, so I have little
hope of it going away any time soon.

       Arnd

^ permalink raw reply

* Re: [RFC PATCH v3 05/12] mac80211: Mark A-MPDU keyid borders for drivers
From: Johannes Berg @ 2019-02-22  8:51 UTC (permalink / raw)
  To: Alexander Wetzel; +Cc: linux-wireless
In-Reply-To: <a4cf7a7a-104d-b685-8fd4-a9dfac97ecb9@wetzel-home.de>

On Thu, 2019-02-21 at 22:20 +0100, Alexander Wetzel wrote:

> > I think it may make sense - reprogramming the hardware engines may take
> > some time, and doing that in the middle of the A-MPDU may not be
> > feasible? You don't just have to load the key (that you need to do
> > anyway) but also extract the status? I dunno, I'm more handwaving, but
> > it doesn't make sense to add such a requirement when only one key index
> > can be used to start with.
> > 
> 
> I'm pretty new to all that and I know I have still huge gaps everywhere.

And I'm just handwaving ;-)

But I know that for example we have A-MPDU spacing rules, ie. sometimes
padding must be inserted by the transmitter to give the receiver's HW or
FW enough time to program crypto engines. It thus stands to reason that
in order to minimise the spacing you'd want to keep the key material at
hand in the engine while processing the whole A-MPDU.

> But the card must be able to process MPDUs using both KeyIDs at that 
> moment already. When receiving a A-MPDU it should not be very hard to 
> check each MPDU and process it accordingly. (TX should even be simpler: 
> The driver simply can decide if he want's to have a key border in the 
> A-MPDU or not and switch to key when it wants.)

I tend to agree, but you never know in what surprising ways hardware
engines work :-)

> > > The code is assuming that the driver is not aggregating MPDUs more than
> > > 5s apart. We probably don't have wait nearly so long but I'm not sure
> > > what is the minimum time.
> > 
> > OTOH, if you have a lot of BE/VI/VO traffic BK might be starved even
> > longer than that, technically indefinitely.
> > 
> 
> Hm, there is nothing preventing us to drop this "idle" switch as long as 
> we also drop the 10s Rx accel offload when idle fallback in the COMPAT 
> patch. (We have to drop the RX idle accel patch or get a small risk of 
> dropping packets in unlikely but possible scenarios. If that are eapol 
> packets things will become hairy, probably disconnecting the sta.)
> 
> It just feels strange to potentially still use the old key for one 
> packet more without time limit. It could be, that the first EAPOL packet 
> we send for the next rekey would still use the previous key, the second 
> eapol packet the current.

Not sure I understand this. If we have no TX going on at all, then
surely we can switch with the next packet, before we encrypt it?

And if we have a packet sitting on hardware queues forever, then we
can't do anything about it anyway?

> > > +	if (sta->ptk_idx_next == sta->ptk_idx) {
> > > +		/* First packet using new key with A-MPDU active*/
> > > +		sta->ptk_idx_next = INVALID_PTK_KEYIDX;
> > > +		ieee80211_check_fast_xmit(tx->sta);
> > 
> > I'm not convinced you can call this from this context? It looks safe
> > though, but it's really strange in a way.
> > 
> 
> Well, it's seems to work fine, no warnings or problems so far:-)
> 
> But I also had doubts and only after finding out that 
> ieee80211_check_fast_xmit() is already being called from the same 
> context I dared to use it, see ieee80211_tx_prepare().

OK :-)
I guess I misremembered then.

> > > +	info->flags &= ~IEEE80211_TX_CTL_AMPDU;
> > 
> > Like you say above, I don't think this really makes a lot of sense. If
> > we don't have any free bits I guess we should try to find some ...
> 
> Well, all I can think of is quite invasive, so I hoped you would have a 
> better idea:

I think we have free bits in enum mac80211_tx_control_flags, so that
should be workable? They won't be preserved until TX status, but that's
OK for this purpose, no?

johannes


^ permalink raw reply

* Re: [RFC PATCH v3 03/12] mac80211: IEEE 802.11 Extended Key ID support
From: Johannes Berg @ 2019-02-22  8:41 UTC (permalink / raw)
  To: Alexander Wetzel; +Cc: linux-wireless
In-Reply-To: <171d2db4-7639-4738-2a6d-c899f0247aee@wetzel-home.de>

On Thu, 2019-02-21 at 20:47 +0100, Alexander Wetzel wrote:
> > > > 
> > > >   - Enforce cipher does not change when replacing a key.
> > > 
> > > is that actually required somehow?
> > 
> > The code is silently assuming a rekey is using the same cipher. Someone 
> > e.g. switching from WEP to CCMP with a rekey would pass all sanity 
> > checks and allow to use the code in a way never intended or tested.
> > With the current handling the userspace e.g. should be able to install a 
> > WEB key using keyid 3 and then rekey it with a CCMP key, claiming keyid 
> > 0 bit mac80211 will copy the keyid from the old and use keyid 3. 
> > Something not possible otherwise.
> > 
> > That said I do not see how this could be exploited, I simply try to 
> > enforce all assumptions to be on the safe side. (I did not dig deeper 
> > into potential exploits after finding out how keyids are used during 
> > rekey.)

Ok. That's fair, but it'd be good to add that reasoning to the commit
log or even a comment where the validation happens.


> > Second, I spend quite some time finding good names for the calls and one 
> > of the last tweaks to this patch was replacing SET_KEY_RX_ONLY to 
> > EXT_SET_KEY...

:)

> > So here the reasoning for why I named them as they are and why I  prefer 
> > the names used in the patch.
> > First, many drivers will handle SET_KEY and SET_KEY_RX_ONLY with the 
> > same code and not differentiate between those at all. Using EXT_as a 
> > prefix for the "normal" command is therefore a nice way to imply the 
> > command can only be used with Extended Key ID and still link it to the 
> > original command.
> > But more important for me was the clash between what the command spells 
> > and what it does in the COMPAT mode: SET_KEY_RX_ONLY would then be used 
> > to install a TX only key which never can be used by the card for Rx.
> > So I decided to rename it to EXT_SET_KEY, just indicating that this 
> > command adds a new key to the card for Extended Key ID and drop the 
> > confusing reference to Rx.

Wait, what? In compat mode SET_KEY_RX_ONLY installs a TX-only key? Ah,
you mean before you changed this.

Why don't we split out compat mode then?

But I see where you're coming from with the EXT_ now. I need to think of
it less as an "extension" now, but as "extended key ID". I'm not really
entirely sure that makes sense - even what we think of as "extended key
ID" now might be the new normal soon? But then again the spec does the
same thing.

> > Long story short: Using SET_KEY_RXONLY and SET_KEY_TX is not wrong, but 
> > I would rate them more confusing.

Fair enough.

> > > > +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;
> > > 
> > > You set this, wouldn't it make more sense to check EXT_KEY_ID_NATIVE?
> > > 
> > > Or maybe this is because of the next patch?

> Exactly. With COMPAT we would have to check for EXT_KEY_ID_NATIVE and 
> EXT_KEY_ID_COMPAT. Since we have already done that and set 
> NL80211_EXT_FEATURE_EXT_KEY_ID I check that here.
> Assuming we merge NATIVE and drop COMPAT it may make sense to keep the 
> check here and drop EXT_KEY_ID_NATIVE altogether.
> The drivers than can set NL80211_EXT_FEATURE_EXT_KEY_ID directly.

Yes, I think I get it. I don't think we need to drop compat, it seems
somewhat useful for some drivers - I think I mostly just got confused
here because compat support only comes later, and I wasn't really
thinking about it yet in the context of this patch.

> > I have to look at that again. It will change some assumptions for sure 
> > but still could work out with some slight differences. I'll have to look 
> > deeper into that since I remember two moments where I was sure needing 
> > the flag. That may well be outdated, but at a first glance it would at 
> > least open the door to first install two key in legacy mode and then 
> > switch between them. (Which should be no problem, of course)
> > I'll follow up on that separately, but that may take some time. When it 
> > works you'll get a new RFC.

No worries :-)
I don't really mind the flag, but much of the use I've seen now here
seemed equivalent, and then it doesn't seem necessary.

> > > > +    key->flags &= ~KEY_FLAG_RX_ONLY;
[snip]
> > > > +    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;
> > > 
> > > You've already cleared the RX_ONLY flag, which gets you inconsistent
> > > data now.
> > > 
> > 
> > I don't think so, it looks ok for me. But the delay_tailroom logic took 
> > a surprisingly large chunk of time and I should explain how the updated 
> > logic is intended to work. Maybe I've messed it up somehow and just do 
> > not see it:

My comment wasn't related to tailroom accounting at all. I've snipped
more code above to hopefully make it clearer.

If you fail to activate the key in the driver, then the key is not
actually enabled for TX, and thus you should not have cleared the
KEY_FLAG_RX_ONLY? You'll be returning this error all the way to
userspace, I assume.

(Maybe, btw, the driver should be allowed to return something like
"oops, I now want to use TX software crypto" like it can do for other
operations?)

> > > >   #define NUM_DEFAULT_KEYS 4
> > > >   #define NUM_DEFAULT_MGMT_KEYS 2
> > > > +#define INVALID_PTK_KEYIDX 2 /* Existing key slot never used by PTK 
> > > > keys */
> > > 
> > > We could also use something obviously wrong like 0xff?
> > 
> > No, not without some undesired modifications. We actually fetch the 
> > referenced key and the key slot must exist and be NULL. We (mostly) 
> > discussed that in the previous RFC, I just decided to use a define 
> > instead the numeric value. (Mostly due the fact that A-MPDU also needs 
> > an "invalid" ID and using the same looks like a good idea.

Hm, yeah, I vaguely remember. OK.

> > That's only right for the push path but can send out wrong packets when 
> > the driver is using the pull path:
> > 
> > 1) ieee80211_xmit_fast() will use fast_tx structure to fill in the 
> > "cached" keyid and queue the packet. (let's say 0)
> > 
> > 2) ieee80211_check_fast_xmit is called due to a rekey (and keyid change 
> > from 0 -> 1)
> > 
> > 3) ieee80211_tx_dequeue() will then dequeue the prepared skb from 1), 
> > refresh the key information but keep keyid 0 in the skb and instruct the 
> > driver to encrypt it for keyid 1 -> WRONG
> > 
> > 4) The remote sta tries to decrypt the packet using the key 0, as 
> > referenced by the keyid. Which will of course not work.
> > 
> > With Extended Key ID (and some debugging) I added a simple rule: When 
> > you assign the pn you also set the matching keyid.

OK.

johannes


^ permalink raw reply

* Re: [RFC PATCH v3 02/12] nl80211/cfg80211: Extended Key ID support
From: Johannes Berg @ 2019-02-22  8:30 UTC (permalink / raw)
  To: Alexander Wetzel; +Cc: linux-wireless
In-Reply-To: <a0e99ac4-4c10-55e6-3ded-5bb5a3ddfb78@wetzel-home.de>

On Sun, 2019-02-17 at 20:19 +0100, Alexander Wetzel wrote:

> I don't see the problem but I may simply be to set on my way to see 
> it... So I'll just give an outline what's required of the API and how 
> this implementation meets those. Hoping that answers your question or 
> allowing you to pinpoint our differences in understanding. (I've added a 
>   more than really required, it may be useful for other discussions to 
> have that outlined in one piece, too.)

:-)

> Extended Key ID has only two requirements for the kernel API:
> 1) Allow a key to be used for decryption first and switch it to a 
> "normal" Rx/Tx key with a second call
> 
> 2) Allow pairwise keys to use keyids 0 and 1 instead only 0.

Right.

> "Legacy" key installs are using NL80211_CMD_NEW_KEY to install a new key 
> and are allow to mark a key for WEP or management  default usages via 
> NL80211_CMD_SET_KEY later.

Right.

> With Extended Key ID we stick to a similar approach: NL80211_CMD_NEW_KEY 
> is called to install the new key and nl80211_key_install_mode allows to 
> select between a "legacy" or "extended" key install: NL80211_KEY_RX_TX 
> for "legacy" or NL80211_KEY_RX_ONLY for "extended".

Ah. That's where the "EXT" came from in the mac80211 names :-) FWIW, I'm
not sure that makes sense. Yes, we think of it as an "extension" or
being "extended" now while we work on it, but ultimately it'll be a
simple part of the API. But I digress.

> NL80211_KEY_SWITCH_TX is only allowed with NL80211_CMD_SET_KEY and is 
> the only Extended Key ID action allowed for that function.

Yes, but what does it *do*? Your documentation said:

	Switch Tx to a Rx only, referenced by sta mac and idx.

but that seems backwards to me based on the above requirement:
	Allow a key to be used for decryption first and switch it to a
	"normal" Rx/Tx key with a second call.

IOW, you said we need to have the ability to first install RX-only, and
then switch the key to RX & TX. I'd have called this "ENABLE_TX" or
something like that. Or perhaps SWITCH_(ON_)TX if you're so inclined,
but the documentation should then say

	Switch key from RX-only to TX/RX, referenced by ...

no? That's what I meant by "the other way around".

> Any non-pairwise keys can only use NL80211_KEY_RX_TX which is of course 
> always the default and also allowed for "legacy" pairwise keys.

Right.

> A Extended Key Install will:
> 1) call NL80211_CMD_NEW_KEY with all the usual parameters of a new key 
> install plus the flag NL80211_KEY_RX_ONLY set.

So far makes sense.

> 2) Once ready will call NL80211_CMD_SET_KEY with flag 
> NL80211_KEY_SWITCH_TX to activate a specific key.

Also makes sense, but the documentation doesn't.

I think we should rename these perhaps

	NL80211_KEY_RX_TX - install key and enable RX/TX (default)
	NL80211_KEY_RX_ONLY - install unicast key for RX only
	NL80211_KEY_ENABLE_TX - enable TX for a previously installed 
				RX_ONLY key

I think?

About the ENABLE_TX vs. SWITCH_TX - we don't allow to switch TX *off*
again, only *on*, so I think "enable" makes more sense than "switch".

Anyway, my whole comment was only about the documentation text which
seemed backward or at least unclear to me.

> ok, I'll remove all the drive-by comment "cleanups".
> It (often) looks kind of untidy and not really worth separate patches 
> and I'm kind of responsible for (most) of them.. I see why you don't 
> want to see those fixed drive-by...
> 
> My understanding is now that we prefer to not change those and I'll 
> leave them alone.

I have no objection to even the most trivial cleanup patches going in
separately, and if you like multiple in a bigger "clean up this area"
patch, but here I think it detracts from the patch.

> Yes. Extended Key ID only allows to use Key ID 1 on top of the 
> established ID 0. See "IEEE 802.11 - 2016 9.4.2.25.4 RSN capabilities":
> 
> Bit 13: Extended Key ID for Individually Addressed Frames. This subfield 
> is set to 1 to indicate that the STA supports Key ID values in the range 
> 0 to 1 for a PTKSA and STKSA when the cipher suite is CCMP or GCMP. A 
> value of 0 indicates that the STA only supports Key ID 0 for a PTKSA and
> STKSA.

OK :)

johannes


^ permalink raw reply

* Re: [PATCH v2] iwlwifi: mvm: Use div_s64 instead of do_div in iwl_mvm_debug_range_resp
From: Luciano Coelho @ 2019-02-22  7:45 UTC (permalink / raw)
  To: Nick Desaulniers, Nathan Chancellor
  Cc: Johannes Berg, Emmanuel Grumbach, Intel Linux Wireless,
	Kalle Valo, linux-wireless, netdev, LKML, Arnd Bergmann
In-Reply-To: <CAKwvOdmCeHxiGPkXXzjwnTtgzEDDjYRE1QBdu7BHeuzCE4YtRA@mail.gmail.com>

On Thu, 2019-02-21 at 16:13 -0800, Nick Desaulniers wrote:
> On Thu, Feb 21, 2019 at 12:08 AM Nathan Chancellor
> <natechancellor@gmail.com> wrote:
> > Clang warns:
> > 
> > drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c:465:2:
> > warning:
> > comparison of distinct pointer types ('typeof ((rtt_avg)) *' (aka
> > 'long
> > long *') and 'uint64_t *' (aka 'unsigned long long *'))
> > [-Wcompare-distinct-pointer-types]
> >         do_div(rtt_avg, 6666);
> >         ^~~~~~~~~~~~~~~~~~~~~
> > include/asm-generic/div64.h:222:28: note: expanded from macro
> > 'do_div'
> >         (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
> >                ~~~~~~~~~~~~~~~~~~ ^  ~~~~~~~~~~~~~~~
> > 1 warning generated.
> > 
> > do_div expects an unsigned dividend. Use div_s64, which expects a
> > signed
> > dividend.
> > 
> > Fixes: 937b10c0de68 ("iwlwifi: mvm: add debug prints for FTM")
> > Link: https://github.com/ClangBuiltLinux/linux/issues/372
> > Suggested-by: Arnd Bergmann <arnd@arndb.de>
> > Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
> > ---
> > 
> > v1 -> v2:
> > 
> > * Fix logic (as the return value of div{,64}_s64 must be used),
> > thanks
> >   to Arnd for the review.
> 
> oh boy, sorry I missed that in the initial code review, thanks Arnd
> for the sharp eye!
> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>

Thanks, guys, I really didn't pay much attention when I applied the
previous versions either.

I have applied this in our internal tree and will send it out instead
of the previous one as part of our upstreaming process.

--
Cheers,
Luca.


^ permalink raw reply

* [PATCH] net: nfc: Fix NULL dereference on nfc_llcp_build_tlv fails
From: Yue Haibing @ 2019-02-22  7:37 UTC (permalink / raw)
  To: sameo, davem; +Cc: linux-kernel, netdev, linux-wireless, YueHaibing

From: YueHaibing <yuehaibing@huawei.com>

KASAN report this:

BUG: KASAN: null-ptr-deref in nfc_llcp_build_gb+0x37f/0x540 [nfc]
Read of size 3 at addr 0000000000000000 by task syz-executor.0/5401

CPU: 0 PID: 5401 Comm: syz-executor.0 Not tainted 5.0.0-rc7+ #45
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0xfa/0x1ce lib/dump_stack.c:113
 kasan_report+0x171/0x18d mm/kasan/report.c:321
 memcpy+0x1f/0x50 mm/kasan/common.c:130
 nfc_llcp_build_gb+0x37f/0x540 [nfc]
 nfc_llcp_register_device+0x6eb/0xb50 [nfc]
 nfc_register_device+0x50/0x1d0 [nfc]
 nfcsim_device_new+0x394/0x67d [nfcsim]
 ? 0xffffffffc1080000
 nfcsim_init+0x6b/0x1000 [nfcsim]
 do_one_initcall+0xfa/0x5ca init/main.c:887
 do_init_module+0x204/0x5f6 kernel/module.c:3460
 load_module+0x66b2/0x8570 kernel/module.c:3808
 __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902
 do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290
 entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x462e99
Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f9cb79dcc58 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000000000073bf00 RCX: 0000000000462e99
RDX: 0000000000000000 RSI: 0000000020000280 RDI: 0000000000000003
RBP: 00007f9cb79dcc70 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f9cb79dd6bc
R13: 00000000004bcefb R14: 00000000006f7030 R15: 0000000000000004

nfc_llcp_build_tlv will return NULL on fails, caller should check it,
otherwise will trigger a NULL dereference.

Reported-by: Hulk Robot <hulkci@huawei.com>
Fixes: eda21f16a5ed ("NFC: Set MIU and RW values from CONNECT and CC LLCP frames")
Fixes: d646960f7986 ("NFC: Initial LLCP support")
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
 net/nfc/llcp_commands.c | 20 ++++++++++++++++++++
 net/nfc/llcp_core.c     | 24 ++++++++++++++++++++----
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c
index 6a196e4..d1fc019e 100644
--- a/net/nfc/llcp_commands.c
+++ b/net/nfc/llcp_commands.c
@@ -419,6 +419,10 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
 						      sock->service_name,
 						      sock->service_name_len,
 						      &service_name_tlv_length);
+		if (!service_name_tlv) {
+			err = -ENOMEM;
+			goto error_tlv;
+		}
 		size += service_name_tlv_length;
 	}
 
@@ -429,9 +433,17 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
 
 	miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
 				      &miux_tlv_length);
+	if (!miux_tlv) {
+		err = -ENOMEM;
+		goto error_tlv;
+	}
 	size += miux_tlv_length;
 
 	rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
+	if (!rw_tlv) {
+		err = -ENOMEM;
+		goto error_tlv;
+	}
 	size += rw_tlv_length;
 
 	pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len);
@@ -484,9 +496,17 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
 
 	miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
 				      &miux_tlv_length);
+	if (!miux_tlv) {
+		err = -ENOMEM;
+		goto error_tlv;
+	}
 	size += miux_tlv_length;
 
 	rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
+	if (!rw_tlv) {
+		err = -ENOMEM;
+		goto error_tlv;
+	}
 	size += rw_tlv_length;
 
 	skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size);
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
index ef4026a..4fa0152 100644
--- a/net/nfc/llcp_core.c
+++ b/net/nfc/llcp_core.c
@@ -532,10 +532,10 @@ static u8 nfc_llcp_reserve_sdp_ssap(struct nfc_llcp_local *local)
 
 static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
 {
-	u8 *gb_cur, *version_tlv, version, version_length;
-	u8 *lto_tlv, lto_length;
-	u8 *wks_tlv, wks_length;
-	u8 *miux_tlv, miux_length;
+	u8 *gb_cur, version, version_length;
+	u8 lto_length, wks_length, miux_length;
+	u8 *version_tlv = NULL, *lto_tlv = NULL,
+	   *wks_tlv = NULL, *miux_tlv = NULL;
 	__be16 wks = cpu_to_be16(local->local_wks);
 	u8 gb_len = 0;
 	int ret = 0;
@@ -543,17 +543,33 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
 	version = LLCP_VERSION_11;
 	version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version,
 					 1, &version_length);
+	if (!version_tlv) {
+		ret = -ENOMEM;
+		goto out;
+	}
 	gb_len += version_length;
 
 	lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_LTO, &local->lto, 1, &lto_length);
+	if (!lto_tlv) {
+		ret = -ENOMEM;
+		goto out;
+	}
 	gb_len += lto_length;
 
 	pr_debug("Local wks 0x%lx\n", local->local_wks);
 	wks_tlv = nfc_llcp_build_tlv(LLCP_TLV_WKS, (u8 *)&wks, 2, &wks_length);
+	if (!wks_tlv) {
+		ret = -ENOMEM;
+		goto out;
+	}
 	gb_len += wks_length;
 
 	miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
 				      &miux_length);
+	if (!miux_tlv) {
+		ret = -ENOMEM;
+		goto out;
+	}
 	gb_len += miux_length;
 
 	gb_len += ARRAY_SIZE(llcp_magic);
-- 
2.7.4



^ permalink raw reply related

* [PATCH 4/4] ath10k: Fix the wrong calculation ht_idx and idx of rate table for tx_stats
From: Surabhi Vishnoi @ 2019-02-22  7:20 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Surabhi Vishnoi
In-Reply-To: <1550820034-18603-1-git-send-email-svishnoi@codeaurora.org>

ht_idx (ht rate index) and idx (rate table index) are calculated based on
mcs index. This mcs index used in the above calculation should be 0-9 for
getting the correct ht_idx and idx.

Currently the mcs index used for the above calculations is mcs index which
can be 0-31 (in case of HT), leading to incorrect rate index and ht index
values.

Fix the issue by obtaining mcs value from the ratecode reported by firmware
and use it for calculating ht_idx and idx (rate-table index).

Tested HW: WCN3990
Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1

Fixes: e88975ca37d1 ("ath10k: dump tx stats in rate table format")
Signed-off-by: Surabhi Vishnoi <svishnoi@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 5b1dd58..b504c4f 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2931,11 +2931,11 @@ static inline s8 ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate)
 
 	tx_stats = arsta->tx_stats;
 	gi = test_bit(ATH10K_RATE_INFO_FLAGS_SGI_BIT, &flags);
-	ht_idx = txrate->mcs + txrate->nss * 8;
-	mcs = txrate->mcs;
+	mcs = ATH10K_HW_MCS_RATE(pstats->ratecode);
 	bw = txrate->bw;
 	nss = txrate->nss;
-	idx = mcs * 8 + 8 * 10 * nss;
+	ht_idx = mcs + (nss - 1) * 8;
+	idx = mcs * 8 + 8 * 10 * (nss - 1);
 	idx += bw * 2 + gi;
 
 #define STATS_OP_FMT(name) tx_stats->stats[ATH10K_STATS_TYPE_##name]
-- 
1.9.1


^ permalink raw reply related

* [PATCH 3/4] ath10k: Fix the wrong updation of SGI in tx_stats debugfs
From: Surabhi Vishnoi @ 2019-02-22  7:20 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Surabhi Vishnoi
In-Reply-To: <1550820034-18603-1-git-send-email-svishnoi@codeaurora.org>

The SGI is updated wrongly in tx stats table in debugfs per sta
entry. To know whether the packets/bytes are sent with SHORT GI,
test whether the SGI bit(ATH10K_RATE_INFO_FLAGS_SGI_BIT) is set or
not in the txrate flags.

Tested HW: WCN3990
Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1

Fixes: a904417fc876 ("ath10k: add extended per sta tx statistics support")
Signed-off-by: Surabhi Vishnoi <svishnoi@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c | 3 ++-
 drivers/net/wireless/ath/ath10k/wmi.h    | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 3a02a76..5b1dd58 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2924,12 +2924,13 @@ static inline s8 ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate)
 	struct rate_info *txrate = &arsta->txrate;
 	struct ath10k_htt_tx_stats *tx_stats;
 	int idx, ht_idx, gi, mcs, bw, nss;
+	unsigned long flags;
 
 	if (!arsta->tx_stats)
 		return;
 
 	tx_stats = arsta->tx_stats;
-	gi = (arsta->txrate.flags & RATE_INFO_FLAGS_SHORT_GI);
+	gi = test_bit(ATH10K_RATE_INFO_FLAGS_SGI_BIT, &flags);
 	ht_idx = txrate->mcs + txrate->nss * 8;
 	mcs = txrate->mcs;
 	bw = txrate->bw;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 7053db4..b727232 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -5062,6 +5062,7 @@ enum wmi_rate_preamble {
 #define ATH10K_GI_NUM		2
 #define ATH10K_HT_MCS_NUM	32
 #define ATH10K_RATE_TABLE_NUM	320
+#define ATH10K_RATE_INFO_FLAGS_SGI_BIT	2
 
 /* Value to disable fixed rate setting */
 #define WMI_FIXED_RATE_NONE    (0xff)
-- 
1.9.1


^ permalink raw reply related

* [PATCH 2/4] ath10k: Fix the wrong updation of BW in tx_stats debugfs entry
From: Surabhi Vishnoi @ 2019-02-22  7:20 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Surabhi Vishnoi
In-Reply-To: <1550820034-18603-1-git-send-email-svishnoi@codeaurora.org>

Currently, the bandwidth is updated wrongly in BW table in tx_stats
debugfs per sta as there is difference in number of bandwidth type
in mac80211 and driver stats table. This leads to bandwidth getting
updated at wrong index in bandwidth table in tx_stats.

Fix this index mismatch between mac80211 and driver stats table (BW table)
by making the number of bandwidth type in driver compatible with mac80211.

Tested HW: WCN3990
Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1

Fixes: a904417fc876 ("ath10k: add extended per sta tx statistics support")
Signed-off-by: Surabhi Vishnoi <svishnoi@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/debugfs_sta.c | 8 +++++---
 drivers/net/wireless/ath/ath10k/wmi.h         | 2 +-
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
index 4778a45..645ba9c 100644
--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
@@ -696,11 +696,13 @@ static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file,
 						 "  %llu ", stats->ht[j][i]);
 			len += scnprintf(buf + len, size - len, "\n");
 			len += scnprintf(buf + len, size - len,
-					" BW %s (20,40,80,160 MHz)\n", str[j]);
+					" BW %s (20,5,10,40,80,160 MHz)\n",
+					str[j]);
 			len += scnprintf(buf + len, size - len,
-					 "  %llu %llu %llu %llu\n",
+					 "  %llu %llu %llu %llu %llu %llu\n",
 					 stats->bw[j][0], stats->bw[j][1],
-					 stats->bw[j][2], stats->bw[j][3]);
+					 stats->bw[j][2], stats->bw[j][3],
+					 stats->bw[j][4], stats->bw[j][5]);
 			len += scnprintf(buf + len, size - len,
 					 " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
 			len += scnprintf(buf + len, size - len,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 0e27878..7053db4 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -5056,7 +5056,7 @@ enum wmi_rate_preamble {
 #define ATH10K_FW_SKIPPED_RATE_CTRL(flags)	(((flags) >> 6) & 0x1)
 
 #define ATH10K_VHT_MCS_NUM	10
-#define ATH10K_BW_NUM		4
+#define ATH10K_BW_NUM		6
 #define ATH10K_NSS_NUM		4
 #define ATH10K_LEGACY_NUM	12
 #define ATH10K_GI_NUM		2
-- 
1.9.1


^ permalink raw reply related

* [PATCH 1/4] ath10k: Fix the incorrect updation of NSS data in tx stats
From: Surabhi Vishnoi @ 2019-02-22  7:20 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Surabhi Vishnoi
In-Reply-To: <1550820034-18603-1-git-send-email-svishnoi@codeaurora.org>

The NSS data is updated incorrectly in the tx stats as the array
indexing starts from zero.

Fix the incorrect updation of NSS data in tx_stats by taking into
consideration the array index starting from zero.

Tested HW: WCN3990
Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1

Fixes: a904417fc876 ("ath10k: add extended per sta tx statistics support")
Signed-off-by: Surabhi Vishnoi <svishnoi@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index d5c666c..3a02a76 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2980,7 +2980,7 @@ static inline s8 ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate)
 		}
 		STATS_OP_FMT(AMPDU).bw[0][bw] +=
 			pstats->succ_bytes + pstats->retry_bytes;
-		STATS_OP_FMT(AMPDU).nss[0][nss] +=
+		STATS_OP_FMT(AMPDU).nss[0][nss - 1] +=
 			pstats->succ_bytes + pstats->retry_bytes;
 		STATS_OP_FMT(AMPDU).gi[0][gi] +=
 			pstats->succ_bytes + pstats->retry_bytes;
@@ -2988,7 +2988,7 @@ static inline s8 ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate)
 			pstats->succ_bytes + pstats->retry_bytes;
 		STATS_OP_FMT(AMPDU).bw[1][bw] +=
 			pstats->succ_pkts + pstats->retry_pkts;
-		STATS_OP_FMT(AMPDU).nss[1][nss] +=
+		STATS_OP_FMT(AMPDU).nss[1][nss - 1] +=
 			pstats->succ_pkts + pstats->retry_pkts;
 		STATS_OP_FMT(AMPDU).gi[1][gi] +=
 			pstats->succ_pkts + pstats->retry_pkts;
@@ -3000,27 +3000,27 @@ static inline s8 ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate)
 	}
 
 	STATS_OP_FMT(SUCC).bw[0][bw] += pstats->succ_bytes;
-	STATS_OP_FMT(SUCC).nss[0][nss] += pstats->succ_bytes;
+	STATS_OP_FMT(SUCC).nss[0][nss - 1] += pstats->succ_bytes;
 	STATS_OP_FMT(SUCC).gi[0][gi] += pstats->succ_bytes;
 
 	STATS_OP_FMT(SUCC).bw[1][bw] += pstats->succ_pkts;
-	STATS_OP_FMT(SUCC).nss[1][nss] += pstats->succ_pkts;
+	STATS_OP_FMT(SUCC).nss[1][nss - 1] += pstats->succ_pkts;
 	STATS_OP_FMT(SUCC).gi[1][gi] += pstats->succ_pkts;
 
 	STATS_OP_FMT(FAIL).bw[0][bw] += pstats->failed_bytes;
-	STATS_OP_FMT(FAIL).nss[0][nss] += pstats->failed_bytes;
+	STATS_OP_FMT(FAIL).nss[0][nss - 1] += pstats->failed_bytes;
 	STATS_OP_FMT(FAIL).gi[0][gi] += pstats->failed_bytes;
 
 	STATS_OP_FMT(FAIL).bw[1][bw] += pstats->failed_pkts;
-	STATS_OP_FMT(FAIL).nss[1][nss] += pstats->failed_pkts;
+	STATS_OP_FMT(FAIL).nss[1][nss - 1] += pstats->failed_pkts;
 	STATS_OP_FMT(FAIL).gi[1][gi] += pstats->failed_pkts;
 
 	STATS_OP_FMT(RETRY).bw[0][bw] += pstats->retry_bytes;
-	STATS_OP_FMT(RETRY).nss[0][nss] += pstats->retry_bytes;
+	STATS_OP_FMT(RETRY).nss[0][nss - 1] += pstats->retry_bytes;
 	STATS_OP_FMT(RETRY).gi[0][gi] += pstats->retry_bytes;
 
 	STATS_OP_FMT(RETRY).bw[1][bw] += pstats->retry_pkts;
-	STATS_OP_FMT(RETRY).nss[1][nss] += pstats->retry_pkts;
+	STATS_OP_FMT(RETRY).nss[1][nss - 1] += pstats->retry_pkts;
 	STATS_OP_FMT(RETRY).gi[1][gi] += pstats->retry_pkts;
 
 	if (txrate->flags >= RATE_INFO_FLAGS_MCS) {
-- 
1.9.1


^ permalink raw reply related

* [PATCH 0/4] Fix inconsistencies observed in population of tx_stats in debugfs
From: Surabhi Vishnoi @ 2019-02-22  7:20 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Surabhi Vishnoi

There are some inconsistencies observed while filling various peer tx stats in tx_stats
debugfs entry per sta.

This patchset fixes the wrong updation of NSS, SGI, Bandwidth and rate_table in tx_stats
debugfs entry per sta.

Surabhi Vishnoi (4):
  ath10k: Fix the incorrect updation of NSS data in tx stats
  ath10k: Fix the wrong updation of BW in tx_stats debugfs entry
  ath10k: Fix the wrong updation of SGI in tx_stats debugfs
  ath10k: Fix the wrong calculation ht_idx and idx of rate table for
    tx_stats

 drivers/net/wireless/ath/ath10k/debugfs_sta.c |  8 +++++---
 drivers/net/wireless/ath/ath10k/htt_rx.c      | 25 +++++++++++++------------
 drivers/net/wireless/ath/ath10k/wmi.h         |  3 ++-
 3 files changed, 20 insertions(+), 16 deletions(-)

-- 
1.9.1


^ permalink raw reply

* [PATCH 1/5] net: dsa: fix a leaked reference by adding a missing of_node_put
From: Wen Yang @ 2019-02-22  7:15 UTC (permalink / raw)
  To: linus.walleij
  Cc: andrew, vivien.didelot, f.fainelli, davem, netdev, linux-kernel,
	alexandre.belloni, UNGLinuxDriver, nbd, lorenzo.bianconi83, kvalo,
	matthias.bgg, linux-wireless, linux-arm-kernel, linux-mediatek,
	anirudh, John.Linn, michal.simek, wang.yi59, Wen Yang

The call to of_get_child_by_name returns a node pointer with refcount
incremented thus it must be explicitly decremented after the last
usage.

Detected by coccinelle with the following warnings:
./drivers/net/dsa/rtl8366rb.c:510:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.
./drivers/net/dsa/rtl8366rb.c:518:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.
./drivers/net/dsa/rtl8366rb.c:540:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.
./drivers/net/dsa/rtl8366rb.c:548:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.
./drivers/net/dsa/rtl8366rb.c:556:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.
./drivers/net/dsa/rtl8366rb.c:561:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 501, but without a corresponding object release within this function.

Signed-off-by: Wen Yang <wen.yang99@zte.com.cn>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Vivien Didelot <vivien.didelot@gmail.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/net/dsa/rtl8366rb.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/net/dsa/rtl8366rb.c b/drivers/net/dsa/rtl8366rb.c
index a4d5049..f4b14b6 100644
--- a/drivers/net/dsa/rtl8366rb.c
+++ b/drivers/net/dsa/rtl8366rb.c
@@ -507,7 +507,8 @@ static int rtl8366rb_setup_cascaded_irq(struct realtek_smi *smi)
 	irq = of_irq_get(intc, 0);
 	if (irq <= 0) {
 		dev_err(smi->dev, "failed to get parent IRQ\n");
-		return irq ? irq : -EINVAL;
+		ret = irq ? irq : -EINVAL;
+		goto out_put_node;
 	}
 
 	/* This clears the IRQ status register */
@@ -515,7 +516,7 @@ static int rtl8366rb_setup_cascaded_irq(struct realtek_smi *smi)
 			  &val);
 	if (ret) {
 		dev_err(smi->dev, "can't read interrupt status\n");
-		return ret;
+		goto out_put_node;
 	}
 
 	/* Fetch IRQ edge information from the descriptor */
@@ -537,7 +538,7 @@ static int rtl8366rb_setup_cascaded_irq(struct realtek_smi *smi)
 				 val);
 	if (ret) {
 		dev_err(smi->dev, "could not configure IRQ polarity\n");
-		return ret;
+		goto out_put_node;
 	}
 
 	ret = devm_request_threaded_irq(smi->dev, irq, NULL,
@@ -545,7 +546,7 @@ static int rtl8366rb_setup_cascaded_irq(struct realtek_smi *smi)
 					"RTL8366RB", smi);
 	if (ret) {
 		dev_err(smi->dev, "unable to request irq: %d\n", ret);
-		return ret;
+		goto out_put_node;
 	}
 	smi->irqdomain = irq_domain_add_linear(intc,
 					       RTL8366RB_NUM_INTERRUPT,
@@ -553,12 +554,15 @@ static int rtl8366rb_setup_cascaded_irq(struct realtek_smi *smi)
 					       smi);
 	if (!smi->irqdomain) {
 		dev_err(smi->dev, "failed to create IRQ domain\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_put_node;
 	}
 	for (i = 0; i < smi->num_ports; i++)
 		irq_set_parent(irq_create_mapping(smi->irqdomain, i), irq);
 
-	return 0;
+out_put_node:
+	of_node_put(intc);
+	return ret;
 }
 
 static int rtl8366rb_set_addr(struct realtek_smi *smi)
-- 
2.9.5


^ permalink raw reply related

* [PATCH 3/5] mt76: fix a leaked reference by adding a missing of_node_put
From: Wen Yang @ 2019-02-22  7:15 UTC (permalink / raw)
  To: linus.walleij
  Cc: andrew, vivien.didelot, f.fainelli, davem, netdev, linux-kernel,
	alexandre.belloni, UNGLinuxDriver, nbd, lorenzo.bianconi83, kvalo,
	matthias.bgg, linux-wireless, linux-arm-kernel, linux-mediatek,
	anirudh, John.Linn, michal.simek, wang.yi59, Wen Yang
In-Reply-To: <1550819742-32155-1-git-send-email-wen.yang99@zte.com.cn>

The call to of_find_node_by_phandle returns a node pointer with refcount
incremented thus it must be explicitly decremented after the last
usage.

Detected by coccinelle with the following warnings:
./drivers/net/wireless/mediatek/mt76/eeprom.c:58:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 48, but without a corresponding object release within this function.
./drivers/net/wireless/mediatek/mt76/eeprom.c:61:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 48, but without a corresponding object release within this function.
./drivers/net/wireless/mediatek/mt76/eeprom.c:67:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 48, but without a corresponding object release within this function.
./drivers/net/wireless/mediatek/mt76/eeprom.c:70:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 48, but without a corresponding object release within this function.
./drivers/net/wireless/mediatek/mt76/eeprom.c:72:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 48, but without a corresponding object release within this function.

Signed-off-by: Wen Yang <wen.yang99@zte.com.cn>
Cc: Felix Fietkau <nbd@nbd.name>
Cc: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-mediatek@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/net/wireless/mediatek/mt76/eeprom.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c
index 530e559..a1529920d 100644
--- a/drivers/net/wireless/mediatek/mt76/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/eeprom.c
@@ -54,22 +54,30 @@ mt76_get_of_eeprom(struct mt76_dev *dev, int len)
 		part = np->name;
 
 	mtd = get_mtd_device_nm(part);
-	if (IS_ERR(mtd))
-		return PTR_ERR(mtd);
+	if (IS_ERR(mtd)) {
+		ret =  PTR_ERR(mtd);
+		goto out_put_node;
+	}
 
-	if (size <= sizeof(*list))
-		return -EINVAL;
+	if (size <= sizeof(*list)) {
+		ret = -EINVAL;
+		goto out_put_node;
+	}
 
 	offset = be32_to_cpup(list);
 	ret = mtd_read(mtd, offset, len, &retlen, dev->eeprom.data);
 	put_mtd_device(mtd);
 	if (ret)
-		return ret;
+		goto out_put_node;
 
-	if (retlen < len)
-		return -EINVAL;
+	if (retlen < len) {
+		ret = -EINVAL;
+		goto out_put_node;
+	}
 
-	return 0;
+out_put_node:
+	of_node_put(np);
+	return ret;
 #else
 	return -ENOENT;
 #endif
-- 
2.9.5


^ permalink raw reply related

* [PATCH 5/5] net: dsa: fix a leaked reference by adding missing of_node_put
From: Wen Yang @ 2019-02-22  7:15 UTC (permalink / raw)
  To: linus.walleij
  Cc: andrew, vivien.didelot, f.fainelli, davem, netdev, linux-kernel,
	alexandre.belloni, UNGLinuxDriver, nbd, lorenzo.bianconi83, kvalo,
	matthias.bgg, linux-wireless, linux-arm-kernel, linux-mediatek,
	anirudh, John.Linn, michal.simek, wang.yi59, Wen Yang
In-Reply-To: <1550819742-32155-1-git-send-email-wen.yang99@zte.com.cn>

The call to of_parse_phandle returns a node pointer with refcount
incremented thus it must be explicitly decremented after the last
usage.

Detected by coccinelle with the following warnings:
./net/dsa/port.c:294:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 284, but without a corresponding object release within this function.
./net/dsa/dsa2.c:627:3-9: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 618, but without a corresponding object release within this function.
./net/dsa/dsa2.c:630:3-9: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 618, but without a corresponding object release within this function.
./net/dsa/dsa2.c:636:3-9: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 618, but without a corresponding object release within this function.
./net/dsa/dsa2.c:639:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 618, but without a corresponding object release within this function.

Signed-off-by: Wen Yang <wen.yang99@zte.com.cn>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Vivien Didelot <vivien.didelot@gmail.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 net/dsa/dsa2.c | 16 ++++++++++------
 net/dsa/port.c |  1 +
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 8c431e0..89823f0 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -613,7 +613,7 @@ static int dsa_switch_parse_ports_of(struct dsa_switch *ds,
 	struct device_node *ports, *port;
 	struct dsa_port *dp;
 	u32 reg;
-	int err;
+	int err = 0;
 
 	ports = of_get_child_by_name(dn, "ports");
 	if (!ports) {
@@ -624,19 +624,23 @@ static int dsa_switch_parse_ports_of(struct dsa_switch *ds,
 	for_each_available_child_of_node(ports, port) {
 		err = of_property_read_u32(port, "reg", &reg);
 		if (err)
-			return err;
+			goto out_put_node;
 
-		if (reg >= ds->num_ports)
-			return -EINVAL;
+		if (reg >= ds->num_ports) {
+			err = -EINVAL;
+			goto out_put_node;
+		}
 
 		dp = &ds->ports[reg];
 
 		err = dsa_port_parse_of(dp, port);
 		if (err)
-			return err;
+			goto out_put_node;
 	}
 
-	return 0;
+out_put_node:
+	of_node_put(ports);
+	return err;
 }
 
 static int dsa_switch_parse_member_of(struct dsa_switch *ds,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 2d7e01b..a6d9a04 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -291,6 +291,7 @@ static struct phy_device *dsa_port_get_phy_device(struct dsa_port *dp)
 		return ERR_PTR(-EPROBE_DEFER);
 	}
 
+	of_node_put(phy_dn);
 	return phydev;
 }
 
-- 
2.9.5


^ permalink raw reply related

* [PATCH 4/5] net: xilinx: fix a leaked reference by adding missing of_node_put
From: Wen Yang @ 2019-02-22  7:15 UTC (permalink / raw)
  To: linus.walleij
  Cc: andrew, vivien.didelot, f.fainelli, davem, netdev, linux-kernel,
	alexandre.belloni, UNGLinuxDriver, nbd, lorenzo.bianconi83, kvalo,
	matthias.bgg, linux-wireless, linux-arm-kernel, linux-mediatek,
	anirudh, John.Linn, michal.simek, wang.yi59, Wen Yang
In-Reply-To: <1550819742-32155-1-git-send-email-wen.yang99@zte.com.cn>

The call to of_parse_phandle returns a node pointer with refcount
incremented thus it must be explicitly decremented after the last
usage.

Detected by coccinelle with the following warning:
./drivers/net/ethernet/xilinx/xilinx_axienet_main.c:1624:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 1569, but without a corresponding object release within this function.

Signed-off-by: Wen Yang <wen.yang99@zte.com.cn>
Cc: Anirudha Sarangi <anirudh@xilinx.com>
Cc: John Linn <John.Linn@xilinx.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Michal Simek <michal.simek@xilinx.com>
Cc: netdev@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 0789d8a..8335390 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1575,11 +1575,13 @@ static int axienet_probe(struct platform_device *pdev)
 	ret = of_address_to_resource(np, 0, &dmares);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to get DMA resource\n");
+		of_node_put(np);
 		goto free_netdev;
 	}
 	lp->dma_regs = devm_ioremap_resource(&pdev->dev, &dmares);
 	if (IS_ERR(lp->dma_regs)) {
 		dev_err(&pdev->dev, "could not map DMA regs\n");
+		of_node_put(np);
 		ret = PTR_ERR(lp->dma_regs);
 		goto free_netdev;
 	}
-- 
2.9.5


^ permalink raw reply related

* [PATCH 2/5] net: mscc: ocelot: fix a leaked reference by adding a missing of_node_put
From: Wen Yang @ 2019-02-22  7:15 UTC (permalink / raw)
  To: linus.walleij
  Cc: andrew, vivien.didelot, f.fainelli, davem, netdev, linux-kernel,
	alexandre.belloni, UNGLinuxDriver, nbd, lorenzo.bianconi83, kvalo,
	matthias.bgg, linux-wireless, linux-arm-kernel, linux-mediatek,
	anirudh, John.Linn, michal.simek, wang.yi59, Wen Yang
In-Reply-To: <1550819742-32155-1-git-send-email-wen.yang99@zte.com.cn>

The call to of_parse_phandle returns a node pointer with refcount
incremented thus it must be explicitly decremented after the last
usage.

Detected by coccinelle with the following warnings:
./drivers/net/ethernet/mscc/ocelot_board.c:293:3-9: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 249, but without a corresponding object release within this function.
./drivers/net/ethernet/mscc/ocelot_board.c:312:3-9: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 249, but without a corresponding object release within this function.
./drivers/net/ethernet/mscc/ocelot_board.c:336:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 249, but without a corresponding object release within this function.
./drivers/net/ethernet/mscc/ocelot_board.c:339:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 249, but without a corresponding object release within this function.

Signed-off-by: Wen Yang <wen.yang99@zte.com.cn>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/net/ethernet/mscc/ocelot_board.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index ca3ea2f..f1485a6 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -290,7 +290,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 
 		err = ocelot_probe_port(ocelot, port, regs, phy);
 		if (err)
-			return err;
+			goto err_probe_ports;
 
 		err = of_get_phy_mode(portnp);
 		if (err < 0)
@@ -309,7 +309,8 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 			dev_err(ocelot->dev,
 				"invalid phy mode for port%d, (Q)SGMII only\n",
 				port);
-			return -EINVAL;
+			err = -EINVAL;
+			goto err_probe_ports;
 		}
 
 		serdes = devm_of_phy_get(ocelot->dev, portnp, NULL);
@@ -328,6 +329,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 		ocelot->ports[port]->serdes = serdes;
 	}
 
+	of_node_put(ports);
 	register_netdevice_notifier(&ocelot_netdevice_nb);
 	register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
 
@@ -336,6 +338,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 	return 0;
 
 err_probe_ports:
+	of_node_put(ports);
 	return err;
 }
 
-- 
2.9.5


^ permalink raw reply related

* [PATCH v3] iw: Add support for controlling tx power for per station
From: Balaji Pothunoori @ 2019-02-22  6:37 UTC (permalink / raw)
  To: johannes, linux-wireless; +Cc: ath10k, Ashok Raj Nagarajan, Balaji Pothunoori

From: Ashok Raj Nagarajan <arnagara@codeaurora.org>

This patch allows userspace to set transmit power,
in dBm units, to a station associated to the AP.

To set a limit tx power of 20 dBm:
iw wlan0 station set <mac-addr> txpwr limit 20

To revert the user defined tx power for a station:
iw wlan0 station set <mac-addr> txpwr auto

Co-developed-by: Balaji Pothunoori <bpothuno@codeaurora.org>
Signed-off-by: Ashok Raj Nagarajan <arnagara@codeaurora.org>
Signed-off-by: Balaji Pothunoori <bpothuno@codeaurora.org>
---
v2: modified user configured units to dBm from mBm
v3: no changes, rebased

 station.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/station.c b/station.c
index e1477ef..8e0e852 100644
--- a/station.c
+++ b/station.c
@@ -651,6 +651,7 @@ COMMAND(station, del, "<MAC address> [subtype <subtype>] [reason-code <code>]",
 static const struct cmd *station_set_plink;
 static const struct cmd *station_set_vlan;
 static const struct cmd *station_set_mesh_power_mode;
+static const struct cmd *station_set_txpwr;
 
 static const struct cmd *select_station_cmd(int argc, char **argv)
 {
@@ -662,6 +663,8 @@ static const struct cmd *select_station_cmd(int argc, char **argv)
 		return station_set_vlan;
 	if (strcmp(argv[1], "mesh_power_mode") == 0)
 		return station_set_mesh_power_mode;
+	if (strcmp(argv[1], "txpwr") == 0)
+		return station_set_txpwr;
 	return NULL;
 }
 
@@ -813,6 +816,74 @@ COMMAND_ALIAS(station, set, "<MAC address> mesh_power_mode "
 	"Set link-specific mesh power mode for this station",
 	select_station_cmd, station_set_mesh_power_mode);
 
+static int handle_station_set_txpwr(struct nl80211_state *state,
+				    struct nl_msg *msg,
+				    int argc, char **argv,
+				    enum id_input id)
+{
+	enum nl80211_tx_power_setting type;
+	unsigned char mac_addr[ETH_ALEN];
+	int sta_txpwr = 0;
+	char *err = NULL;
+
+	if (argc != 3 && argc != 4)
+		return 1;
+
+	if (mac_addr_a2n(mac_addr, argv[0])) {
+		fprintf(stderr, "invalid mac address\n");
+		return 2;
+	}
+
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
+	argc--;
+	argv++;
+
+	if (strcmp("txpwr", argv[0]) != 0)
+		return 1;
+	argc--;
+	argv++;
+
+	if (!strcmp(argv[0], "auto"))
+		type = NL80211_TX_POWER_AUTOMATIC;
+	else if (!strcmp(argv[0], "limit"))
+		type = NL80211_TX_POWER_LIMITED;
+	else {
+		printf("Invalid parameter: %s\n", argv[0]);
+		return 2;
+	}
+
+	NLA_PUT_U8(msg, NL80211_ATTR_STA_TX_POWER_SETTING, type);
+
+	if (type != NL80211_TX_POWER_AUTOMATIC) {
+		if (argc != 2) {
+			printf("Missing TX power level argument.\n");
+			return 2;
+		}
+
+		argc--;
+		argv++;
+
+		sta_txpwr = strtoul(argv[0], &err, 0);
+
+		if (sta_txpwr)
+			NLA_PUT_U16(msg, NL80211_ATTR_STA_TX_POWER, sta_txpwr);
+	}
+
+	argc--;
+	argv++;
+
+	if (argc)
+		return 1;
+
+	return 0;
+ nla_put_failure:
+	return -ENOBUFS;
+}
+COMMAND_ALIAS(station, set, "<MAC address> txpwr <auto|limit> [<tx power dBm>]",
+	NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set_txpwr,
+	"Set Tx power for this station.",
+	select_station_cmd, station_set_txpwr);
+
 static int handle_station_dump(struct nl80211_state *state,
 			       struct nl_msg *msg,
 			       int argc, char **argv,
-- 
2.7.4


^ permalink raw reply related

* [PATCH v3 3/3] ath10k: add support for controlling tx power to a station
From: Balaji Pothunoori @ 2019-02-22  6:35 UTC (permalink / raw)
  To: ath10k, linux-wireless; +Cc: Ashok Raj Nagarajan, Balaji Pothunoori

From: Ashok Raj Nagarajan <arnagara@codeaurora.org>

This patch will add the support to control the transmit power for traffic
to a station associated with the AP.

Underlying firmware will enforce that the maximum tx power will be based
on the regulatory requirements. If the user given transmit power is greater
than the allowed tx power in the given channel, then the firmware will use
the maximum tx power in the same channel.

When 0 is sent to the firmware as tx power, it will revert to the default
tx power for the station.

Tested Hardware : QCA9984
Tested Firmware : 10.4-3.9.0.1-00013

Co-developed-by: Balaji Pothunoori <bpothuno@codeaurora.org>
Signed-off-by: Ashok Raj Nagarajan <arnagara@codeaurora.org>
Signed-off-by: Balaji Pothunoori <bpothuno@codeaurora.org>
---
v2: removed mBm to dBm conversion
v3: rebased wmi.h changes

 drivers/net/wireless/ath/ath10k/debug.h |  3 +++
 drivers/net/wireless/ath/ath10k/mac.c   | 39 +++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/wmi.h   |  6 +++++
 3 files changed, 48 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index db78e85..2e43d8d 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -71,6 +71,9 @@ struct ath10k_pktlog_hdr {
 /* FIXME: How to calculate the buffer size sanely? */
 #define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024)
 
+#define ATH10K_TX_POWER_MAX_VAL 70
+#define ATH10K_TX_POWER_MIN_VAL 0
+
 extern unsigned int ath10k_debug_mask;
 
 __printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b73c23d..d6ed452 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6350,6 +6350,41 @@ static void ath10k_mac_dec_num_stations(struct ath10k_vif *arvif,
 	ar->num_stations--;
 }
 
+static int ath10k_sta_set_txpwr(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_sta *sta)
+{
+	struct ath10k *ar = hw->priv;
+	struct ath10k_vif *arvif = (void *)vif->drv_priv;
+	int ret = 0;
+	s16 txpwr;
+
+	if (sta->txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
+		txpwr = 0;
+	} else {
+		txpwr = sta->txpwr.power;
+		if (!txpwr)
+			return -EINVAL;
+	}
+
+	if (txpwr > ATH10K_TX_POWER_MAX_VAL || txpwr < ATH10K_TX_POWER_MIN_VAL)
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+
+	ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
+					WMI_PEER_USE_FIXED_PWR, txpwr);
+	if (ret) {
+		ath10k_warn(ar, "failed to set tx power for station ret: %d\n",
+			    ret);
+		goto out;
+	}
+
+out:
+	mutex_unlock(&ar->conf_mutex);
+	return ret;
+}
+
 static int ath10k_sta_state(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
 			    struct ieee80211_sta *sta,
@@ -8007,6 +8042,7 @@ static const struct ieee80211_ops ath10k_ops = {
 	.set_key			= ath10k_set_key,
 	.set_default_unicast_key        = ath10k_set_default_unicast_key,
 	.sta_state			= ath10k_sta_state,
+	.sta_set_txpwr			= ath10k_sta_set_txpwr,
 	.conf_tx			= ath10k_conf_tx,
 	.remain_on_channel		= ath10k_remain_on_channel,
 	.cancel_remain_on_channel	= ath10k_cancel_remain_on_channel,
@@ -8695,6 +8731,9 @@ int ath10k_mac_register(struct ath10k *ar)
 		wiphy_ext_feature_set(ar->hw->wiphy,
 				      NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
 
+	if (test_bit(WMI_SERVICE_TX_PWR_PER_PEER, ar->wmi.svc_map))
+		wiphy_ext_feature_set(ar->hw->wiphy,
+				      NL80211_EXT_FEATURE_STA_TX_PWR);
 	/*
 	 * on LL hardware queues are managed entirely by the FW
 	 * so we only advertise to mac we can do the queues thing
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index d9b646f..1557253 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -200,6 +200,7 @@ enum wmi_service {
 	WMI_SERVICE_RTT_RESPONDER_ROLE,
 	WMI_SERVICE_PER_PACKET_SW_ENCRYPT,
 	WMI_SERVICE_REPORT_AIRTIME,
+	WMI_SERVICE_TX_PWR_PER_PEER,
 
 	/* Remember to add the new value to wmi_service_name()! */
 
@@ -367,6 +368,7 @@ enum wmi_10_4_service {
 	WMI_10_4_SERVICE_RTT_RESPONDER_ROLE,
 	WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
 	WMI_10_4_SERVICE_REPORT_AIRTIME,
+	WMI_10_4_SERVICE_TX_PWR_PER_PEER,
 };
 
 static inline char *wmi_service_name(enum wmi_service service_id)
@@ -491,6 +493,7 @@ static inline char *wmi_service_name(enum wmi_service service_id)
 	SVCSTR(WMI_SERVICE_RTT_RESPONDER_ROLE);
 	SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT);
 	SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
+	SVCSTR(WMI_SERVICE_TX_PWR_PER_PEER);
 
 	case WMI_SERVICE_MAX:
 		return NULL;
@@ -818,6 +821,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
 	       WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len);
 	SVCMAP(WMI_10_4_SERVICE_REPORT_AIRTIME,
 	       WMI_SERVICE_REPORT_AIRTIME, len);
+	SVCMAP(WMI_10_4_SERVICE_TX_PWR_PER_PEER,
+	       WMI_SERVICE_TX_PWR_PER_PEER, len);
 }
 
 #undef SVCMAP
@@ -6253,6 +6258,7 @@ enum wmi_peer_param {
 	WMI_PEER_USE_4ADDR  = 0x6,
 	WMI_PEER_DEBUG      = 0xa,
 	WMI_PEER_PHYMODE    = 0xd,
+	WMI_PEER_USE_FIXED_PWR = 0x8,
 	WMI_PEER_DUMMY_VAR  = 0xff, /* dummy parameter for STA PS workaround */
 };
 
-- 
2.7.4


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox