Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [kbuild-all] drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:58:6: error: redefinition of 'brcmf_debugfs_init'
From: Fengguang Wu @ 2017-02-16 13:08 UTC (permalink / raw)
  To: Arend Van Spriel
  Cc: Kalle Valo, Randy Dunlap, linux-wireless, linux-kernel,
	kbuild-all, Rafał Miłecki, Philip Li
In-Reply-To: <8ff44e41-97c7-4ae5-6850-65ad407fd788@broadcom.com>

Hi all,

Yes sorry, it's a false report related to how we do bisects.

>>>>>> CONFIG_BRCM_TRACING=y
>>>>>> CONFIG_BRCMDBG=y
>>>>>>
>>>>>> but DEBUG is not defined.
>>>>>>
>>>>>> I think it would help if CONFIG_BRCMDBG set DEBUG
>>>>>> or if some of the tests for DEBUG used CONFIG_BRCMDBG instead.
>>>>>
>>>>> Arend or Rafał, would you be able to look at this build problem? Kbuild
>>>>> found the build errors below, apparently a very old issue. It just
>>>>> blames me now because I moved the driver to a new directory :)
>>>
>>> It is a very old issue. The thing is that the issue can not really occur
>>> because we have this:
>>>
>>> # common flags
>>> subdir-ccflags-$(CONFIG_BRCMDBG)        += -DDEBUG
>>>
>>> in drivers/net/wireless/broadcom/brcm80211/Makefile. So no clue what
>>> happens in the "kbuild test robot" scenario.

As an optimization, the robot often does "partial builds" during bisects.
For example, when the error is found in

        drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c

It'll try

        make drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.o

And verify the bisect result with

        make drivers/net/wireless/broadcom/brcm80211/brcmfmac/

However in this case the whole dir is moved, so both logics failed to
give correct results. We'll check how to improve this. Sorry for the
confusions!

>> I actually tried to reproduce this with kbuild bot's instructions and
>> was surprised to see that the build worked ok for me. So the issue is
>> not that simple.
>
>Hi Kalle,
>
>Here is the old email exchange we had about this [1]. In my opinion this
>is a Kbuild issue that needs to be looked into.
>
>Regards,
>Arend
>
>[1] http://www.spinics.net/lists/linux-wireless/msg142122.html

Thanks,
Fengguang

^ permalink raw reply

* Re: drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:58:6: error: redefinition of 'brcmf_debugfs_init'
From: Arend Van Spriel @ 2017-02-16 10:30 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Rafał Miłecki, Randy Dunlap, kbuild test robot,
	kbuild-all, linux-kernel, linux-wireless
In-Reply-To: <87efyymp2q.fsf@kamboji.qca.qualcomm.com>

On 16-2-2017 11:01, Kalle Valo wrote:
> Arend Van Spriel <arend.vanspriel@broadcom.com> writes:
> 
>> On 16-2-2017 10:39, Rafał Miłecki wrote:
>>> On 02/16/2017 10:31 AM, Kalle Valo wrote:
>>>> (Adding linux-wireless)
>>>>
>>>> Randy Dunlap <rdunlap@infradead.org> writes:
>>>>
>>>>> On 02/07/17 02:02, kbuild test robot wrote:
>>>>>> Hi Kalle,
>>>>>>
>>>>>> FYI, the error/warning still remains.
>>>>>>
>>>>>> tree:  
>>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
>>>>>> master
>>>>>> head:   8b1b41ee74f9712c355d66dc105bbea663ae0afd
>>>>>> commit: 05491d2ccf20b20a1375303441fbbfbd12b24a4f brcm80211: move
>>>>>> under broadcom vendor directory
>>>>>> date:   1 year, 3 months ago
>>>>>> config: mips-allyesconfig (attached as .config)
>>>>>> compiler: mips-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>>>>>> reproduce:
>>>>>>         wget
>>>>>> https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross
>>>>>>
>>>>>> -O ~/bin/make.cross
>>>>>>         chmod +x ~/bin/make.cross
>>>>>>         git checkout 05491d2ccf20b20a1375303441fbbfbd12b24a4f
>>>>>>         # save the attached .config to linux build tree
>>>>>>         make.cross ARCH=mips
>>>>>>
>>>>>> All errors (new ones prefixed by >>):
> n>>>>
>>>>> when both:
>>>>>
>>>>> CONFIG_BRCM_TRACING=y
>>>>> CONFIG_BRCMDBG=y
>>>>>
>>>>> but DEBUG is not defined.
>>>>>
>>>>> I think it would help if CONFIG_BRCMDBG set DEBUG
>>>>> or if some of the tests for DEBUG used CONFIG_BRCMDBG instead.
>>>>
>>>> Arend or Rafał, would you be able to look at this build problem? Kbuild
>>>> found the build errors below, apparently a very old issue. It just
>>>> blames me now because I moved the driver to a new directory :)
>>
>> It is a very old issue. The thing is that the issue can not really occur
>> because we have this:
>>
>> # common flags
>> subdir-ccflags-$(CONFIG_BRCMDBG)        += -DDEBUG
>>
>> in drivers/net/wireless/broadcom/brcm80211/Makefile. So no clue what
>> happens in the "kbuild test robot" scenario.
> 
> I actually tried to reproduce this with kbuild bot's instructions and
> was surprised to see that the build worked ok for me. So the issue is
> not that simple.

Hi Kalle,

Here is the old email exchange we had about this [1]. In my opinion this
is a Kbuild issue that needs to be looked into.

Regards,
Arend

[1] http://www.spinics.net/lists/linux-wireless/msg142122.html

^ permalink raw reply

* Re: [PATCH V2 2/2] brcmfmac: don't warn user about NVRAM if fallback to platform one succeeds
From: Rafał Miłecki @ 2017-02-16  9:04 UTC (permalink / raw)
  To: Arend Van Spriel
  Cc: Rafał Miłecki, Ming Lei, Luis R . Rodriguez, Greg KH,
	Linux Kernel Mailing List, Kalle Valo, linux-wireless,
	brcm80211-dev-list.pdl
In-Reply-To: <d2b1cb64-a829-b433-2370-f2c47b9d0a5d@broadcom.com>

On 2017-02-16 09:38, Arend Van Spriel wrote:
> On 16-2-2017 8:26, Rafał Miłecki wrote:
>> From: Rafał Miłecki <rafal@milecki.pl>
>> 
>> Failing to load NVRAM file isn't critical if we manage to get platform
>> one in the fallback path. It means warnings like:
>> [   10.801506] brcmfmac 0000:01:00.0: Direct firmware load for 
>> brcm/brcmfmac43602-pcie.txt failed with error -2
>> are unnecessary & disturbing for people with platform NVRAM. This is
>> very common case for Broadcom home routers.
>> 
>> So instead of printing warning immediately with the firmware subsystem
>> let's first try our fallback code. If that fails as well, then it's a
>> right moment to print an error.
>> 
>> This should reduce amount of false reports from users seeing this
>> warning while having wireless working perfectly fine.
> 
> There are of course people with issues who take this warning as a straw
> to clutch.
> 
>> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
>> ---
>> V2: Update commit message as it wasn't clear enough (thanks Andy) & 
>> add extra
>>     messages to the firmware.c.
>> 
>> Kalle, Arend: this patch is strictly related to the bigger 1/2. Could 
>> you ack
>> this change as I expect this patchset to be picked by Ming, Luis or 
>> Greg?
>> ---
>>  .../net/wireless/broadcom/brcm80211/brcmfmac/firmware.c  | 16 
>> +++++++++++-----
>>  1 file changed, 11 insertions(+), 5 deletions(-)
>> 
>> diff --git 
>> a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c 
>> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>> index c7c1e9906500..510a76d99eee 100644
>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>> @@ -462,8 +462,14 @@ static void brcmf_fw_request_nvram_done(const 
>> struct firmware *fw, void *ctx)
>>  		raw_nvram = false;
>>  	} else {
>>  		data = bcm47xx_nvram_get_contents(&data_len);
>> -		if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
>> -			goto fail;
>> +		if (!data) {
>> +			brcmf_dbg(TRACE, "Failed to get platform NVRAM\n");
>> +			if (!(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) {
>> +				brcmf_err("Loading NVRAM from %s and using platform one both 
>> failed\n",
>> +					  fwctx->nvram_name);
>> +				goto fail;
>> +			}
>> +		}
>>  		raw_nvram = true;
>>  	}
>> 
>> @@ -504,9 +510,9 @@ static void brcmf_fw_request_code_done(const 
>> struct firmware *fw, void *ctx)
>>  		return;
>>  	}
>>  	fwctx->code = fw;
>> -	ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
>> -				      fwctx->dev, GFP_KERNEL, fwctx,
>> -				      brcmf_fw_request_nvram_done);
>> +	ret = request_firmware_async(THIS_MODULE, FW_OPT_NO_WARN,
>> +				     fwctx->nvram_name, fwctx->dev, GFP_KERNEL,
>> +				     fwctx, brcmf_fw_request_nvram_done);
> 
> You changed the behaviour, because of your change in patch 1/2:
> 
> -	fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK |
> -		(uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
> +	fw_work->opt_flags = FW_OPT_NOWAIT | opt_flags;
> 
> So: (FW_OPT_NOWAIT | FW_OPT_UEVENT) vs (FW_OPT_NOWAIT | FW_OPT_NO_WARN)

Sorry, I didn't realize brcmfmac needs FW_OPT_UEVENT. I'll re-add it in 
V3, just
let me wait to see if there will be more comments.

^ permalink raw reply

* Re: [PATCH V2 2/2] brcmfmac: don't warn user about NVRAM if fallback to platform one succeeds
From: Arend Van Spriel @ 2017-02-16 10:17 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: Rafał Miłecki, Ming Lei, Luis R . Rodriguez, Greg KH,
	Linux Kernel Mailing List, Kalle Valo, linux-wireless,
	brcm80211-dev-list.pdl
In-Reply-To: <31df911dc857c59b0d36e586f9542113@milecki.pl>

On 16-2-2017 10:32, Rafał Miłecki wrote:
> On 2017-02-16 10:18, Arend Van Spriel wrote:
>> On 16-2-2017 10:04, Rafał Miłecki wrote:
>>> On 2017-02-16 09:38, Arend Van Spriel wrote:
>>>> On 16-2-2017 8:26, Rafał Miłecki wrote:
>>>>> From: Rafał Miłecki <rafal@milecki.pl>
>>>>>
>>>>> Failing to load NVRAM file isn't critical if we manage to get platform
>>>>> one in the fallback path. It means warnings like:
>>>>> [   10.801506] brcmfmac 0000:01:00.0: Direct firmware load for
>>>>> brcm/brcmfmac43602-pcie.txt failed with error -2
>>>>> are unnecessary & disturbing for people with platform NVRAM. This is
>>>>> very common case for Broadcom home routers.
>>>>>
>>>>> So instead of printing warning immediately with the firmware subsystem
>>>>> let's first try our fallback code. If that fails as well, then it's a
>>>>> right moment to print an error.
>>>>>
>>>>> This should reduce amount of false reports from users seeing this
>>>>> warning while having wireless working perfectly fine.
>>>>
>>>> There are of course people with issues who take this warning as a straw
>>>> to clutch.
>>>>
>>>>> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
>>>>> ---
>>>>> V2: Update commit message as it wasn't clear enough (thanks Andy) &
>>>>> add extra
>>>>>     messages to the firmware.c.
>>>>>
>>>>> Kalle, Arend: this patch is strictly related to the bigger 1/2. Could
>>>>> you ack
>>>>> this change as I expect this patchset to be picked by Ming, Luis or
>>>>> Greg?
>>>>> ---
>>>>>  .../net/wireless/broadcom/brcm80211/brcmfmac/firmware.c  | 16
>>>>> +++++++++++-----
>>>>>  1 file changed, 11 insertions(+), 5 deletions(-)
>>>>>
>>>>> diff --git
>>>>> a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>>>> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>>>> index c7c1e9906500..510a76d99eee 100644
>>>>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>>>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>>>> @@ -462,8 +462,14 @@ static void brcmf_fw_request_nvram_done(const
>>>>> struct firmware *fw, void *ctx)
>>>>>          raw_nvram = false;
>>>>>      } else {
>>>>>          data = bcm47xx_nvram_get_contents(&data_len);
>>>>> -        if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
>>>>> -            goto fail;
>>>>> +        if (!data) {
>>>>> +            brcmf_dbg(TRACE, "Failed to get platform NVRAM\n");
>>>>> +            if (!(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) {
>>>>> +                brcmf_err("Loading NVRAM from %s and using platform
>>>>> one both failed\n",
>>>>> +                      fwctx->nvram_name);
>>>>> +                goto fail;
>>>>> +            }
>>>>> +        }
>>>>>          raw_nvram = true;
>>>>>      }
>>>>>
>>>>> @@ -504,9 +510,9 @@ static void brcmf_fw_request_code_done(const
>>>>> struct firmware *fw, void *ctx)
>>>>>          return;
>>>>>      }
>>>>>      fwctx->code = fw;
>>>>> -    ret = request_firmware_nowait(THIS_MODULE, true,
>>>>> fwctx->nvram_name,
>>>>> -                      fwctx->dev, GFP_KERNEL, fwctx,
>>>>> -                      brcmf_fw_request_nvram_done);
>>>>> +    ret = request_firmware_async(THIS_MODULE, FW_OPT_NO_WARN,
>>>>> +                     fwctx->nvram_name, fwctx->dev, GFP_KERNEL,
>>>>> +                     fwctx, brcmf_fw_request_nvram_done);
>>>>
>>>> You changed the behaviour, because of your change in patch 1/2:
>>>>
>>>> -    fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK |
>>>> -        (uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
>>>> +    fw_work->opt_flags = FW_OPT_NOWAIT | opt_flags;
>>>>
>>>> So: (FW_OPT_NOWAIT | FW_OPT_UEVENT) vs (FW_OPT_NOWAIT | FW_OPT_NO_WARN)
>>>
>>> Sorry, I didn't realize brcmfmac needs FW_OPT_UEVENT. I'll re-add it in
>>> V3, just
>>> let me wait to see if there will be more comments.
>>
>> To be honest whether or not FW_OPT_UEVENT is needed should not be
>> something a driver needs to concern about. It is really a system
>> configuration issue if you ask me. So the only thing we could do is to
>> have it just in case.
> 
> Drivers always got a choice (see bool uevent) so I didn't want to change
> it.

Sure, I know. I just wanted to vent an opinion for the firmware_class
maintainers.

Regards,
Arend

^ permalink raw reply

* Re: drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:58:6: error: redefinition of 'brcmf_debugfs_init'
From: Kalle Valo @ 2017-02-16 10:01 UTC (permalink / raw)
  To: Arend Van Spriel
  Cc: Rafał Miłecki, Randy Dunlap, kbuild test robot,
	kbuild-all, linux-kernel, linux-wireless
In-Reply-To: <59013c13-af43-cf9f-8e3e-14d97e48f0dd@broadcom.com>

Arend Van Spriel <arend.vanspriel@broadcom.com> writes:

> On 16-2-2017 10:39, Rafa=C5=82 Mi=C5=82ecki wrote:
>> On 02/16/2017 10:31 AM, Kalle Valo wrote:
>>> (Adding linux-wireless)
>>>
>>> Randy Dunlap <rdunlap@infradead.org> writes:
>>>
>>>> On 02/07/17 02:02, kbuild test robot wrote:
>>>>> Hi Kalle,
>>>>>
>>>>> FYI, the error/warning still remains.
>>>>>
>>>>> tree:=20=20
>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
>>>>> master
>>>>> head:   8b1b41ee74f9712c355d66dc105bbea663ae0afd
>>>>> commit: 05491d2ccf20b20a1375303441fbbfbd12b24a4f brcm80211: move
>>>>> under broadcom vendor directory
>>>>> date:   1 year, 3 months ago
>>>>> config: mips-allyesconfig (attached as .config)
>>>>> compiler: mips-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>>>>> reproduce:
>>>>>         wget
>>>>> https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/=
sbin/make.cross
>>>>>
>>>>> -O ~/bin/make.cross
>>>>>         chmod +x ~/bin/make.cross
>>>>>         git checkout 05491d2ccf20b20a1375303441fbbfbd12b24a4f
>>>>>         # save the attached .config to linux build tree
>>>>>         make.cross ARCH=3Dmips
>>>>>
>>>>> All errors (new ones prefixed by >>):
n>>>>
>>>> when both:
>>>>
>>>> CONFIG_BRCM_TRACING=3Dy
>>>> CONFIG_BRCMDBG=3Dy
>>>>
>>>> but DEBUG is not defined.
>>>>
>>>> I think it would help if CONFIG_BRCMDBG set DEBUG
>>>> or if some of the tests for DEBUG used CONFIG_BRCMDBG instead.
>>>
>>> Arend or Rafa=C5=82, would you be able to look at this build problem? K=
build
>>> found the build errors below, apparently a very old issue. It just
>>> blames me now because I moved the driver to a new directory :)
>
> It is a very old issue. The thing is that the issue can not really occur
> because we have this:
>
> # common flags
> subdir-ccflags-$(CONFIG_BRCMDBG)        +=3D -DDEBUG
>
> in drivers/net/wireless/broadcom/brcm80211/Makefile. So no clue what
> happens in the "kbuild test robot" scenario.

I actually tried to reproduce this with kbuild bot's instructions and
was surprised to see that the build worked ok for me. So the issue is
not that simple.

--=20
Kalle Valo

^ permalink raw reply

* Re: drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:58:6: error: redefinition of 'brcmf_debugfs_init'
From: Arend Van Spriel @ 2017-02-16  9:53 UTC (permalink / raw)
  To: Rafał Miłecki, Kalle Valo, Randy Dunlap
  Cc: kbuild test robot, kbuild-all, linux-kernel, linux-wireless
In-Reply-To: <e8c43505-1e7a-635c-dc27-45422acb25a6@milecki.pl>

On 16-2-2017 10:39, Rafał Miłecki wrote:
> On 02/16/2017 10:31 AM, Kalle Valo wrote:
>> (Adding linux-wireless)
>>
>> Randy Dunlap <rdunlap@infradead.org> writes:
>>
>>> On 02/07/17 02:02, kbuild test robot wrote:
>>>> Hi Kalle,
>>>>
>>>> FYI, the error/warning still remains.
>>>>
>>>> tree:  
>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
>>>> master
>>>> head:   8b1b41ee74f9712c355d66dc105bbea663ae0afd
>>>> commit: 05491d2ccf20b20a1375303441fbbfbd12b24a4f brcm80211: move
>>>> under broadcom vendor directory
>>>> date:   1 year, 3 months ago
>>>> config: mips-allyesconfig (attached as .config)
>>>> compiler: mips-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>>>> reproduce:
>>>>         wget
>>>> https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross
>>>>
>>>> -O ~/bin/make.cross
>>>>         chmod +x ~/bin/make.cross
>>>>         git checkout 05491d2ccf20b20a1375303441fbbfbd12b24a4f
>>>>         # save the attached .config to linux build tree
>>>>         make.cross ARCH=mips
>>>>
>>>> All errors (new ones prefixed by >>):
>>>
>>> when both:
>>>
>>> CONFIG_BRCM_TRACING=y
>>> CONFIG_BRCMDBG=y
>>>
>>> but DEBUG is not defined.
>>>
>>> I think it would help if CONFIG_BRCMDBG set DEBUG
>>> or if some of the tests for DEBUG used CONFIG_BRCMDBG instead.
>>
>> Arend or Rafał, would you be able to look at this build problem? Kbuild
>> found the build errors below, apparently a very old issue. It just
>> blames me now because I moved the driver to a new directory :)

It is a very old issue. The thing is that the issue can not really occur
because we have this:

# common flags
subdir-ccflags-$(CONFIG_BRCMDBG)        += -DDEBUG

in drivers/net/wireless/broadcom/brcm80211/Makefile. So no clue what
happens in the "kbuild test robot" scenario.

Regards,
Arend

> Something like this maybe? Note I didn't test it with above config.
> 
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
> index 6687812770cc..8c7695fde482 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
> @@ -108,7 +108,7 @@ do {                                    \
>  extern int brcmf_msg_level;
> 
>  struct brcmf_pub;
> -#ifdef DEBUG
> +#ifdef CONFIG_BRCMDBG
>  void brcmf_debugfs_init(void);
>  void brcmf_debugfs_exit(void);
>  int brcmf_debug_attach(struct brcmf_pub *drvr);
> 

^ permalink raw reply

* Re: [PATCH V2 2/2] brcmfmac: don't warn user about NVRAM if fallback to platform one succeeds
From: Rafał Miłecki @ 2017-02-16  9:32 UTC (permalink / raw)
  To: Arend Van Spriel
  Cc: Rafał Miłecki, Ming Lei, Luis R . Rodriguez, Greg KH,
	Linux Kernel Mailing List, Kalle Valo, linux-wireless,
	brcm80211-dev-list.pdl
In-Reply-To: <88182ec9-3344-7468-d3c3-33d9ffa532e2@broadcom.com>

On 2017-02-16 10:18, Arend Van Spriel wrote:
> On 16-2-2017 10:04, Rafał Miłecki wrote:
>> On 2017-02-16 09:38, Arend Van Spriel wrote:
>>> On 16-2-2017 8:26, Rafał Miłecki wrote:
>>>> From: Rafał Miłecki <rafal@milecki.pl>
>>>> 
>>>> Failing to load NVRAM file isn't critical if we manage to get 
>>>> platform
>>>> one in the fallback path. It means warnings like:
>>>> [   10.801506] brcmfmac 0000:01:00.0: Direct firmware load for
>>>> brcm/brcmfmac43602-pcie.txt failed with error -2
>>>> are unnecessary & disturbing for people with platform NVRAM. This is
>>>> very common case for Broadcom home routers.
>>>> 
>>>> So instead of printing warning immediately with the firmware 
>>>> subsystem
>>>> let's first try our fallback code. If that fails as well, then it's 
>>>> a
>>>> right moment to print an error.
>>>> 
>>>> This should reduce amount of false reports from users seeing this
>>>> warning while having wireless working perfectly fine.
>>> 
>>> There are of course people with issues who take this warning as a 
>>> straw
>>> to clutch.
>>> 
>>>> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
>>>> ---
>>>> V2: Update commit message as it wasn't clear enough (thanks Andy) &
>>>> add extra
>>>>     messages to the firmware.c.
>>>> 
>>>> Kalle, Arend: this patch is strictly related to the bigger 1/2. 
>>>> Could
>>>> you ack
>>>> this change as I expect this patchset to be picked by Ming, Luis or
>>>> Greg?
>>>> ---
>>>>  .../net/wireless/broadcom/brcm80211/brcmfmac/firmware.c  | 16
>>>> +++++++++++-----
>>>>  1 file changed, 11 insertions(+), 5 deletions(-)
>>>> 
>>>> diff --git
>>>> a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>>> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>>> index c7c1e9906500..510a76d99eee 100644
>>>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>>> @@ -462,8 +462,14 @@ static void brcmf_fw_request_nvram_done(const
>>>> struct firmware *fw, void *ctx)
>>>>          raw_nvram = false;
>>>>      } else {
>>>>          data = bcm47xx_nvram_get_contents(&data_len);
>>>> -        if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
>>>> -            goto fail;
>>>> +        if (!data) {
>>>> +            brcmf_dbg(TRACE, "Failed to get platform NVRAM\n");
>>>> +            if (!(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) {
>>>> +                brcmf_err("Loading NVRAM from %s and using platform
>>>> one both failed\n",
>>>> +                      fwctx->nvram_name);
>>>> +                goto fail;
>>>> +            }
>>>> +        }
>>>>          raw_nvram = true;
>>>>      }
>>>> 
>>>> @@ -504,9 +510,9 @@ static void brcmf_fw_request_code_done(const
>>>> struct firmware *fw, void *ctx)
>>>>          return;
>>>>      }
>>>>      fwctx->code = fw;
>>>> -    ret = request_firmware_nowait(THIS_MODULE, true, 
>>>> fwctx->nvram_name,
>>>> -                      fwctx->dev, GFP_KERNEL, fwctx,
>>>> -                      brcmf_fw_request_nvram_done);
>>>> +    ret = request_firmware_async(THIS_MODULE, FW_OPT_NO_WARN,
>>>> +                     fwctx->nvram_name, fwctx->dev, GFP_KERNEL,
>>>> +                     fwctx, brcmf_fw_request_nvram_done);
>>> 
>>> You changed the behaviour, because of your change in patch 1/2:
>>> 
>>> -    fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK |
>>> -        (uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
>>> +    fw_work->opt_flags = FW_OPT_NOWAIT | opt_flags;
>>> 
>>> So: (FW_OPT_NOWAIT | FW_OPT_UEVENT) vs (FW_OPT_NOWAIT | 
>>> FW_OPT_NO_WARN)
>> 
>> Sorry, I didn't realize brcmfmac needs FW_OPT_UEVENT. I'll re-add it 
>> in
>> V3, just
>> let me wait to see if there will be more comments.
> 
> To be honest whether or not FW_OPT_UEVENT is needed should not be
> something a driver needs to concern about. It is really a system
> configuration issue if you ask me. So the only thing we could do is to
> have it just in case.

Drivers always got a choice (see bool uevent) so I didn't want to change 
it.

^ permalink raw reply

* Re: drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:58:6: error: redefinition of 'brcmf_debugfs_init'
From: Rafał Miłecki @ 2017-02-16  9:39 UTC (permalink / raw)
  To: Kalle Valo, Randy Dunlap, Arend Van Spriel
  Cc: kbuild test robot, kbuild-all, linux-kernel, linux-wireless
In-Reply-To: <87inoamqh6.fsf@kamboji.qca.qualcomm.com>

On 02/16/2017 10:31 AM, Kalle Valo wrote:
> (Adding linux-wireless)
>
> Randy Dunlap <rdunlap@infradead.org> writes:
>
>> On 02/07/17 02:02, kbuild test robot wrote:
>>> Hi Kalle,
>>>
>>> FYI, the error/warning still remains.
>>>
>>> tree:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
>>> head:   8b1b41ee74f9712c355d66dc105bbea663ae0afd
>>> commit: 05491d2ccf20b20a1375303441fbbfbd12b24a4f brcm80211: move
>>> under broadcom vendor directory
>>> date:   1 year, 3 months ago
>>> config: mips-allyesconfig (attached as .config)
>>> compiler: mips-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>>> reproduce:
>>>         wget
>>> https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross
>>> -O ~/bin/make.cross
>>>         chmod +x ~/bin/make.cross
>>>         git checkout 05491d2ccf20b20a1375303441fbbfbd12b24a4f
>>>         # save the attached .config to linux build tree
>>>         make.cross ARCH=mips
>>>
>>> All errors (new ones prefixed by >>):
>>
>> when both:
>>
>> CONFIG_BRCM_TRACING=y
>> CONFIG_BRCMDBG=y
>>
>> but DEBUG is not defined.
>>
>> I think it would help if CONFIG_BRCMDBG set DEBUG
>> or if some of the tests for DEBUG used CONFIG_BRCMDBG instead.
>
> Arend or Rafał, would you be able to look at this build problem? Kbuild
> found the build errors below, apparently a very old issue. It just
> blames me now because I moved the driver to a new directory :)

Something like this maybe? Note I didn't test it with above config.

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
index 6687812770cc..8c7695fde482 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
@@ -108,7 +108,7 @@ do {									\
  extern int brcmf_msg_level;

  struct brcmf_pub;
-#ifdef DEBUG
+#ifdef CONFIG_BRCMDBG
  void brcmf_debugfs_init(void);
  void brcmf_debugfs_exit(void);
  int brcmf_debug_attach(struct brcmf_pub *drvr);

^ permalink raw reply related

* Re: drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:58:6: error: redefinition of 'brcmf_debugfs_init'
From: Kalle Valo @ 2017-02-16  9:31 UTC (permalink / raw)
  To: Randy Dunlap, Arend Van Spriel, Rafał Miłecki
  Cc: kbuild test robot, kbuild-all, linux-kernel, linux-wireless
In-Reply-To: <ce7467a9-12d5-f64e-8b59-f9581db9f7c8@infradead.org>

(Adding linux-wireless)

Randy Dunlap <rdunlap@infradead.org> writes:

> On 02/07/17 02:02, kbuild test robot wrote:
>> Hi Kalle,
>>=20
>> FYI, the error/warning still remains.
>>=20
>> tree:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.g=
it master
>> head:   8b1b41ee74f9712c355d66dc105bbea663ae0afd
>> commit: 05491d2ccf20b20a1375303441fbbfbd12b24a4f brcm80211: move
>> under broadcom vendor directory
>> date:   1 year, 3 months ago
>> config: mips-allyesconfig (attached as .config)
>> compiler: mips-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>> reproduce:
>>         wget
>> https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbi=
n/make.cross
>> -O ~/bin/make.cross
>>         chmod +x ~/bin/make.cross
>>         git checkout 05491d2ccf20b20a1375303441fbbfbd12b24a4f
>>         # save the attached .config to linux build tree
>>         make.cross ARCH=3Dmips=20
>>=20
>> All errors (new ones prefixed by >>):
>
> when both:
>
> CONFIG_BRCM_TRACING=3Dy
> CONFIG_BRCMDBG=3Dy
>
> but DEBUG is not defined.
>
> I think it would help if CONFIG_BRCMDBG set DEBUG
> or if some of the tests for DEBUG used CONFIG_BRCMDBG instead.

Arend or Rafa=C5=82, would you be able to look at this build problem? Kbuild
found the build errors below, apparently a very old issue. It just
blames me now because I moved the driver to a new directory :)

>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:58:6:
>> error: redefinition of 'brcmf_debugfs_init'
    void brcmf_debugfs_init(void)
         ^~~~~~~~~~~~~~~~~~
   In file included from drivers/net/wireless/broadcom/brcm80211/brcmfmac/b=
us.h:20:0,
                    from drivers/net/wireless/broadcom/brcm80211/brcmfmac/d=
ebug.c:24:
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h:118:20: note: p=
revious definition of 'brcmf_debugfs_init' was here
    static inline void brcmf_debugfs_init(void)
                       ^~~~~~~~~~~~~~~~~~
>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:65:6:
>> error: redefinition of 'brcmf_debugfs_exit'
    void brcmf_debugfs_exit(void)
         ^~~~~~~~~~~~~~~~~~
   In file included from drivers/net/wireless/broadcom/brcm80211/brcmfmac/b=
us.h:20:0,
                    from drivers/net/wireless/broadcom/brcm80211/brcmfmac/d=
ebug.c:24:
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h:121:20: note: p=
revious definition of 'brcmf_debugfs_exit' was here
    static inline void brcmf_debugfs_exit(void)
                       ^~~~~~~~~~~~~~~~~~
>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:74:5:
>> error: redefinition of 'brcmf_debug_attach'
    int brcmf_debug_attach(struct brcmf_pub *drvr)
        ^~~~~~~~~~~~~~~~~~
   In file included from drivers/net/wireless/broadcom/brcm80211/brcmfmac/b=
us.h:20:0,
                    from drivers/net/wireless/broadcom/brcm80211/brcmfmac/d=
ebug.c:24:
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h:124:19: note: p=
revious definition of 'brcmf_debug_attach' was here
    static inline int brcmf_debug_attach(struct brcmf_pub *drvr)
                      ^~~~~~~~~~~~~~~~~~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c: In function 'b=
rcmf_debug_attach':
>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:81:6:
>> error: 'struct brcmf_pub' has no member named 'dbgfs_dir'
     drvr->dbgfs_dir =3D debugfs_create_dir(dev_name(dev), root_folder);
         ^~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:82:17: error: '=
struct brcmf_pub' has no member named 'dbgfs_dir'
     if (IS_ERR(drvr->dbgfs_dir))
                    ^~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:83:22: error: '=
struct brcmf_pub' has no member named 'dbgfs_dir'
      return PTR_ERR(drvr->dbgfs_dir);
                         ^~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c: At top level:
>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:90:6:
>> error: redefinition of 'brcmf_debug_detach'
    void brcmf_debug_detach(struct brcmf_pub *drvr)
         ^~~~~~~~~~~~~~~~~~
   In file included from drivers/net/wireless/broadcom/brcm80211/brcmfmac/b=
us.h:20:0,
                    from drivers/net/wireless/broadcom/brcm80211/brcmfmac/d=
ebug.c:24:
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h:128:20: note: p=
revious definition of 'brcmf_debug_detach' was here
    static inline void brcmf_debug_detach(struct brcmf_pub *drvr)
                       ^~~~~~~~~~~~~~~~~~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c: In function 'b=
rcmf_debug_detach':
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:94:26: error: '=
struct brcmf_pub' has no member named 'dbgfs_dir'
     if (!IS_ERR_OR_NULL(drvr->dbgfs_dir))
                             ^~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:95:32: error: '=
struct brcmf_pub' has no member named 'dbgfs_dir'
      debugfs_remove_recursive(drvr->dbgfs_dir);
                                   ^~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c: In function 'b=
rcmf_debugfs_get_devdir':
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:100:13: error: =
'struct brcmf_pub' has no member named 'dbgfs_dir'
     return drvr->dbgfs_dir;
                ^~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c: At top level:
>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:103:5:
>> error: redefinition of 'brcmf_debugfs_add_entry'
    int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
        ^~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/net/wireless/broadcom/brcm80211/brcmfmac/b=
us.h:20:0,
                    from drivers/net/wireless/broadcom/brcm80211/brcmfmac/d=
ebug.c:24:
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h:132:5: note: pr=
evious definition of 'brcmf_debugfs_add_entry' was here
    int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
        ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c: In function 'b=
rcmf_debugfs_add_entry':
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:109:10: error: =
'struct brcmf_pub' has no member named 'dbgfs_dir'
         drvr->dbgfs_dir, read_fn);
             ^~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c: In function 'b=
rcmf_debugfs_get_devdir':
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c:101:1: warning:=
 control reaches end of non-void function [-Wreturn-type]
    }
    ^


--=20
Kalle Valo

^ permalink raw reply

* Re: [PATCH V2 2/2] brcmfmac: don't warn user about NVRAM if fallback to platform one succeeds
From: Arend Van Spriel @ 2017-02-16  9:18 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: Rafał Miłecki, Ming Lei, Luis R . Rodriguez, Greg KH,
	Linux Kernel Mailing List, Kalle Valo, linux-wireless,
	brcm80211-dev-list.pdl
In-Reply-To: <894daa616fc3bbd875e075b3096dba8e@milecki.pl>

On 16-2-2017 10:04, Rafał Miłecki wrote:
> On 2017-02-16 09:38, Arend Van Spriel wrote:
>> On 16-2-2017 8:26, Rafał Miłecki wrote:
>>> From: Rafał Miłecki <rafal@milecki.pl>
>>>
>>> Failing to load NVRAM file isn't critical if we manage to get platform
>>> one in the fallback path. It means warnings like:
>>> [   10.801506] brcmfmac 0000:01:00.0: Direct firmware load for
>>> brcm/brcmfmac43602-pcie.txt failed with error -2
>>> are unnecessary & disturbing for people with platform NVRAM. This is
>>> very common case for Broadcom home routers.
>>>
>>> So instead of printing warning immediately with the firmware subsystem
>>> let's first try our fallback code. If that fails as well, then it's a
>>> right moment to print an error.
>>>
>>> This should reduce amount of false reports from users seeing this
>>> warning while having wireless working perfectly fine.
>>
>> There are of course people with issues who take this warning as a straw
>> to clutch.
>>
>>> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
>>> ---
>>> V2: Update commit message as it wasn't clear enough (thanks Andy) &
>>> add extra
>>>     messages to the firmware.c.
>>>
>>> Kalle, Arend: this patch is strictly related to the bigger 1/2. Could
>>> you ack
>>> this change as I expect this patchset to be picked by Ming, Luis or
>>> Greg?
>>> ---
>>>  .../net/wireless/broadcom/brcm80211/brcmfmac/firmware.c  | 16
>>> +++++++++++-----
>>>  1 file changed, 11 insertions(+), 5 deletions(-)
>>>
>>> diff --git
>>> a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>> index c7c1e9906500..510a76d99eee 100644
>>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
>>> @@ -462,8 +462,14 @@ static void brcmf_fw_request_nvram_done(const
>>> struct firmware *fw, void *ctx)
>>>          raw_nvram = false;
>>>      } else {
>>>          data = bcm47xx_nvram_get_contents(&data_len);
>>> -        if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
>>> -            goto fail;
>>> +        if (!data) {
>>> +            brcmf_dbg(TRACE, "Failed to get platform NVRAM\n");
>>> +            if (!(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) {
>>> +                brcmf_err("Loading NVRAM from %s and using platform
>>> one both failed\n",
>>> +                      fwctx->nvram_name);
>>> +                goto fail;
>>> +            }
>>> +        }
>>>          raw_nvram = true;
>>>      }
>>>
>>> @@ -504,9 +510,9 @@ static void brcmf_fw_request_code_done(const
>>> struct firmware *fw, void *ctx)
>>>          return;
>>>      }
>>>      fwctx->code = fw;
>>> -    ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
>>> -                      fwctx->dev, GFP_KERNEL, fwctx,
>>> -                      brcmf_fw_request_nvram_done);
>>> +    ret = request_firmware_async(THIS_MODULE, FW_OPT_NO_WARN,
>>> +                     fwctx->nvram_name, fwctx->dev, GFP_KERNEL,
>>> +                     fwctx, brcmf_fw_request_nvram_done);
>>
>> You changed the behaviour, because of your change in patch 1/2:
>>
>> -    fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK |
>> -        (uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
>> +    fw_work->opt_flags = FW_OPT_NOWAIT | opt_flags;
>>
>> So: (FW_OPT_NOWAIT | FW_OPT_UEVENT) vs (FW_OPT_NOWAIT | FW_OPT_NO_WARN)
> 
> Sorry, I didn't realize brcmfmac needs FW_OPT_UEVENT. I'll re-add it in
> V3, just
> let me wait to see if there will be more comments.

To be honest whether or not FW_OPT_UEVENT is needed should not be
something a driver needs to concern about. It is really a system
configuration issue if you ask me. So the only thing we could do is to
have it just in case.

Regards,
Arend

^ permalink raw reply

* Re: [PATCH V2 2/2] brcmfmac: don't warn user about NVRAM if fallback to platform one succeeds
From: Arend Van Spriel @ 2017-02-16  8:38 UTC (permalink / raw)
  To: Rafał Miłecki, Ming Lei, Luis R . Rodriguez, Greg KH,
	Linux Kernel Mailing List
  Cc: Kalle Valo, linux-wireless, brcm80211-dev-list.pdl,
	Rafał Miłecki
In-Reply-To: <20170216072636.7128-2-zajec5@gmail.com>

On 16-2-2017 8:26, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
> 
> Failing to load NVRAM file isn't critical if we manage to get platform
> one in the fallback path. It means warnings like:
> [   10.801506] brcmfmac 0000:01:00.0: Direct firmware load for brcm/brcmfmac43602-pcie.txt failed with error -2
> are unnecessary & disturbing for people with platform NVRAM. This is
> very common case for Broadcom home routers.
> 
> So instead of printing warning immediately with the firmware subsystem
> let's first try our fallback code. If that fails as well, then it's a
> right moment to print an error.
> 
> This should reduce amount of false reports from users seeing this
> warning while having wireless working perfectly fine.

There are of course people with issues who take this warning as a straw
to clutch.

> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
> ---
> V2: Update commit message as it wasn't clear enough (thanks Andy) & add extra
>     messages to the firmware.c.
> 
> Kalle, Arend: this patch is strictly related to the bigger 1/2. Could you ack
> this change as I expect this patchset to be picked by Ming, Luis or Greg?
> ---
>  .../net/wireless/broadcom/brcm80211/brcmfmac/firmware.c  | 16 +++++++++++-----
>  1 file changed, 11 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
> index c7c1e9906500..510a76d99eee 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
> @@ -462,8 +462,14 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
>  		raw_nvram = false;
>  	} else {
>  		data = bcm47xx_nvram_get_contents(&data_len);
> -		if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
> -			goto fail;
> +		if (!data) {
> +			brcmf_dbg(TRACE, "Failed to get platform NVRAM\n");
> +			if (!(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) {
> +				brcmf_err("Loading NVRAM from %s and using platform one both failed\n",
> +					  fwctx->nvram_name);
> +				goto fail;
> +			}
> +		}
>  		raw_nvram = true;
>  	}
>  
> @@ -504,9 +510,9 @@ static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
>  		return;
>  	}
>  	fwctx->code = fw;
> -	ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
> -				      fwctx->dev, GFP_KERNEL, fwctx,
> -				      brcmf_fw_request_nvram_done);
> +	ret = request_firmware_async(THIS_MODULE, FW_OPT_NO_WARN,
> +				     fwctx->nvram_name, fwctx->dev, GFP_KERNEL,
> +				     fwctx, brcmf_fw_request_nvram_done);

You changed the behaviour, because of your change in patch 1/2:

-	fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK |
-		(uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
+	fw_work->opt_flags = FW_OPT_NOWAIT | opt_flags;

So: (FW_OPT_NOWAIT | FW_OPT_UEVENT) vs (FW_OPT_NOWAIT | FW_OPT_NO_WARN)

Regards,
Arend

^ permalink raw reply

* Re: [PATCH 2/2] brcmfmac: don't warn user if loading firmware file with NVRAM fails
From: Rafał Miłecki @ 2017-02-16  7:25 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Rafał Miłecki, Ming Lei, Luis R . Rodriguez, Greg KH,
	Linux Kernel Mailing List, Kalle Valo, Arend van Spriel,
	open list:TI WILINK WIRELES..., brcm80211-dev-list.pdl
In-Reply-To: <CAHp75Vee+f5eH7DFWNcWFPcdoBf_63yQh7L71dLpNSmC5fXDww@mail.gmail.com>

On 2017-02-16 02:19, Andy Shevchenko wrote:
> On Thu, Feb 16, 2017 at 12:29 AM, Rafał Miłecki <zajec5@gmail.com> 
> wrote:
>> From: Rafał Miłecki <rafal@milecki.pl>
>> 
>> This isn't critical as we use platform NVRAM as fallback and it's very
>> common case of all Broadcom home routers. Thanks for the new firmware
>> loading function we can achieve this by simply passing FW_OPT_NO_WARN.
>> 
> 
> What kind of warning you are talking about?
> 
> On Intel Edison brcmfmac isn't backed up by NVRAM (there no such) and
> the platform is not ACPI-based. The warning might be crucial for
> debugging Wi-Fi issues on such platforms.

Sorry, I should have tried better with that commit message. V2 in a 
second.

^ permalink raw reply

* [PATCH V2 2/2] brcmfmac: don't warn user about NVRAM if fallback to platform one succeeds
From: Rafał Miłecki @ 2017-02-16  7:26 UTC (permalink / raw)
  To: Ming Lei, Luis R . Rodriguez, Greg KH, Linux Kernel Mailing List
  Cc: Kalle Valo, Arend van Spriel, linux-wireless,
	brcm80211-dev-list.pdl, Rafał Miłecki
In-Reply-To: <20170216072636.7128-1-zajec5@gmail.com>

From: Rafał Miłecki <rafal@milecki.pl>

Failing to load NVRAM file isn't critical if we manage to get platform
one in the fallback path. It means warnings like:
[   10.801506] brcmfmac 0000:01:00.0: Direct firmware load for brcm/brcmfmac43602-pcie.txt failed with error -2
are unnecessary & disturbing for people with platform NVRAM. This is
very common case for Broadcom home routers.

So instead of printing warning immediately with the firmware subsystem
let's first try our fallback code. If that fails as well, then it's a
right moment to print an error.

This should reduce amount of false reports from users seeing this
warning while having wireless working perfectly fine.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
V2: Update commit message as it wasn't clear enough (thanks Andy) & add extra
    messages to the firmware.c.

Kalle, Arend: this patch is strictly related to the bigger 1/2. Could you ack
this change as I expect this patchset to be picked by Ming, Luis or Greg?
---
 .../net/wireless/broadcom/brcm80211/brcmfmac/firmware.c  | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index c7c1e9906500..510a76d99eee 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -462,8 +462,14 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
 		raw_nvram = false;
 	} else {
 		data = bcm47xx_nvram_get_contents(&data_len);
-		if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
-			goto fail;
+		if (!data) {
+			brcmf_dbg(TRACE, "Failed to get platform NVRAM\n");
+			if (!(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) {
+				brcmf_err("Loading NVRAM from %s and using platform one both failed\n",
+					  fwctx->nvram_name);
+				goto fail;
+			}
+		}
 		raw_nvram = true;
 	}
 
@@ -504,9 +510,9 @@ static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
 		return;
 	}
 	fwctx->code = fw;
-	ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
-				      fwctx->dev, GFP_KERNEL, fwctx,
-				      brcmf_fw_request_nvram_done);
+	ret = request_firmware_async(THIS_MODULE, FW_OPT_NO_WARN,
+				     fwctx->nvram_name, fwctx->dev, GFP_KERNEL,
+				     fwctx, brcmf_fw_request_nvram_done);
 
 	if (!ret)
 		return;
-- 
2.11.0

^ permalink raw reply related

* [PATCH V2 1/2] firmware: add more flexible request_firmware_async function
From: Rafał Miłecki @ 2017-02-16  7:26 UTC (permalink / raw)
  To: Ming Lei, Luis R . Rodriguez, Greg KH, Linux Kernel Mailing List
  Cc: Kalle Valo, Arend van Spriel, linux-wireless,
	brcm80211-dev-list.pdl, Rafał Miłecki
In-Reply-To: <20170215222948.21030-1-zajec5@gmail.com>

From: Rafał Miłecki <rafal@milecki.pl>

So far we got only one function for loading firmware asynchronously:
request_firmware_nowait. It didn't allow much customization of firmware
loading process - there is only one bool uevent argument. Moreover this
bool also controls user helper in an unclear way.

Resolve this problem by adding a one flexible function and making old
request_firmware_nowait a simple inline using new solution. This
implementation:
1) Modifies only single bits on existing code
2) Doesn't require adjusting / rewriting current drivers
3) Adds new function for drivers that need more control over loading a
   firmware. Thanks to using flags more features can be added later.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
This patch is based on top of
[PATCH V2 RESEND] firmware: simplify defining and handling FW_OPT_FALLBACK
applied on top of Linux 4.10-rc8.

Ming/Luis/Greg: assuming this gets a positive review, could someone of you pick
this patchset? Second patch modifies brcmfmac, I'll try to get a proper Ack for
that one.
Unless you want this to go through wireless tree, then let me know please.
---
 drivers/base/firmware_class.c | 25 ++++++-------------------
 include/linux/firmware.h      | 34 +++++++++++++++++++++++++++++-----
 2 files changed, 35 insertions(+), 24 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index d05be1732c8b..7b3f0a018dc3 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -182,18 +182,6 @@ static int __fw_state_check(struct fw_state *fw_st, enum fw_status status)
 
 #endif /* CONFIG_FW_LOADER_USER_HELPER */
 
-/* firmware behavior options */
-#define FW_OPT_UEVENT	(1U << 0)
-#define FW_OPT_NOWAIT	(1U << 1)
-#ifdef CONFIG_FW_LOADER_USER_HELPER
-#define FW_OPT_USERHELPER	(1U << 2)
-#else
-#define FW_OPT_USERHELPER	0
-#endif
-#define FW_OPT_NO_WARN	(1U << 3)
-#define FW_OPT_NOCACHE	(1U << 4)
-#define FW_OPT_FALLBACK	(1U << 5)
-
 struct firmware_cache {
 	/* firmware_buf instance will be added into the below list */
 	spinlock_t lock;
@@ -1356,7 +1344,7 @@ static void request_firmware_work_func(struct work_struct *work)
 	_request_firmware(&fw, fw_work->name, fw_work->device, NULL, 0,
 			  fw_work->opt_flags);
 	fw_work->cont(fw, fw_work->context);
-	put_device(fw_work->device); /* taken in request_firmware_nowait() */
+	put_device(fw_work->device); /* taken in request_firmware_async() */
 
 	module_put(fw_work->module);
 	kfree_const(fw_work->name);
@@ -1364,7 +1352,7 @@ static void request_firmware_work_func(struct work_struct *work)
 }
 
 /**
- * request_firmware_nowait - asynchronous version of request_firmware
+ * request_firmware_async - asynchronous version of request_firmware
  * @module: module requesting the firmware
  * @uevent: sends uevent to copy the firmware image if this flag
  *	is non-zero else the firmware copy must be done manually.
@@ -1387,8 +1375,8 @@ static void request_firmware_work_func(struct work_struct *work)
  *		- can't sleep at all if @gfp is GFP_ATOMIC.
  **/
 int
-request_firmware_nowait(
-	struct module *module, bool uevent,
+request_firmware_async(
+	struct module *module, unsigned int opt_flags,
 	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context))
 {
@@ -1407,8 +1395,7 @@ request_firmware_nowait(
 	fw_work->device = device;
 	fw_work->context = context;
 	fw_work->cont = cont;
-	fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK |
-		(uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
+	fw_work->opt_flags = FW_OPT_NOWAIT | opt_flags;
 
 	if (!try_module_get(module)) {
 		kfree_const(fw_work->name);
@@ -1421,7 +1408,7 @@ request_firmware_nowait(
 	schedule_work(&fw_work->work);
 	return 0;
 }
-EXPORT_SYMBOL(request_firmware_nowait);
+EXPORT_SYMBOL(request_firmware_async);
 
 #ifdef CONFIG_PM_SLEEP
 static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
diff --git a/include/linux/firmware.h b/include/linux/firmware.h
index b1f9f0ccb8ac..1f2bf14aa441 100644
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -8,6 +8,18 @@
 #define FW_ACTION_NOHOTPLUG 0
 #define FW_ACTION_HOTPLUG 1
 
+/* firmware behavior options */
+#define FW_OPT_UEVENT	(1U << 0)
+#define FW_OPT_NOWAIT	(1U << 1)
+#ifdef CONFIG_FW_LOADER_USER_HELPER
+#define FW_OPT_USERHELPER	(1U << 2)
+#else
+#define FW_OPT_USERHELPER	0
+#endif
+#define FW_OPT_NO_WARN	(1U << 3)
+#define FW_OPT_NOCACHE	(1U << 4)
+#define FW_OPT_FALLBACK	(1U << 5)
+
 struct firmware {
 	size_t size;
 	const u8 *data;
@@ -41,8 +53,8 @@ struct builtin_fw {
 #if defined(CONFIG_FW_LOADER) || (defined(CONFIG_FW_LOADER_MODULE) && defined(MODULE))
 int request_firmware(const struct firmware **fw, const char *name,
 		     struct device *device);
-int request_firmware_nowait(
-	struct module *module, bool uevent,
+int request_firmware_async(
+	struct module *module, unsigned int opt_flags,
 	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context));
 int request_firmware_direct(const struct firmware **fw, const char *name,
@@ -58,8 +70,8 @@ static inline int request_firmware(const struct firmware **fw,
 {
 	return -EINVAL;
 }
-static inline int request_firmware_nowait(
-	struct module *module, bool uevent,
+static inline int request_firmware_async(
+	struct module *module, unsigned int opt_flags,
 	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context))
 {
@@ -82,6 +94,18 @@ static inline int request_firmware_into_buf(const struct firmware **firmware_p,
 {
 	return -EINVAL;
 }
-
 #endif
+
+static inline int request_firmware_nowait(
+	struct module *module, bool uevent,
+	const char *name, struct device *device, gfp_t gfp, void *context,
+	void (*cont)(const struct firmware *fw, void *context))
+{
+	unsigned int opt_flags = FW_OPT_FALLBACK |
+		(uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
+
+	return request_firmware_async(module, opt_flags, name, device, gfp,
+				      context, cont);
+}
+
 #endif
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH 2/2] brcmfmac: don't warn user if loading firmware file with NVRAM fails
From: Andy Shevchenko @ 2017-02-16  1:19 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: Ming Lei, Luis R . Rodriguez, Greg KH, Linux Kernel Mailing List,
	Kalle Valo, Arend van Spriel, open list:TI WILINK WIRELES...,
	brcm80211-dev-list.pdl, Rafał Miłecki
In-Reply-To: <20170215222948.21030-2-zajec5@gmail.com>

On Thu, Feb 16, 2017 at 12:29 AM, Rafa=C5=82 Mi=C5=82ecki <zajec5@gmail.com=
> wrote:
> From: Rafa=C5=82 Mi=C5=82ecki <rafal@milecki.pl>
>
> This isn't critical as we use platform NVRAM as fallback and it's very
> common case of all Broadcom home routers. Thanks for the new firmware
> loading function we can achieve this by simply passing FW_OPT_NO_WARN.
>

What kind of warning you are talking about?

On Intel Edison brcmfmac isn't backed up by NVRAM (there no such) and
the platform is not ACPI-based. The warning might be crucial for
debugging Wi-Fi issues on such platforms.

> Signed-off-by: Rafa=C5=82 Mi=C5=82ecki <rafal@milecki.pl>
> ---
> Kalle, Arend: this patch is strictly related to the bigger 1/2. Could you=
 ack
> this change as I expect this patchset to be picked by Ming, Luis or Greg.
> ---
>  drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c =
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
> index c7c1e9906500..26ec445a8d2d 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
> @@ -504,9 +504,9 @@ static void brcmf_fw_request_code_done(const struct f=
irmware *fw, void *ctx)
>                 return;
>         }
>         fwctx->code =3D fw;
> -       ret =3D request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_n=
ame,
> -                                     fwctx->dev, GFP_KERNEL, fwctx,
> -                                     brcmf_fw_request_nvram_done);
> +       ret =3D request_firmware_async(THIS_MODULE, FW_OPT_NO_WARN,
> +                                    fwctx->nvram_name, fwctx->dev, GFP_K=
ERNEL,
> +                                    fwctx, brcmf_fw_request_nvram_done);
>
>         if (!ret)
>                 return;
> --
> 2.11.0
>



--=20
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* [PATCH v2] mac80211:  allow overriding station bandwidth.
From: greearb @ 2017-02-16  1:16 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

This allows one to disable VHT160 (or 80+80) on hardware
that might otherwise try to use it.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
v2: Change description

 include/linux/ieee80211.h |  1 +
 net/mac80211/main.c       |  1 +
 net/mac80211/vht.c        | 23 +++++++++++++++++++++++
 3 files changed, 25 insertions(+)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index a80516f..e5dc3a8 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1542,6 +1542,7 @@ struct ieee80211_vht_operation {
 #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ		0x00000004
 #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ	0x00000008
 #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK			0x0000000C
+#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_SHIFT			2
 #define IEEE80211_VHT_CAP_RXLDPC				0x00000010
 #define IEEE80211_VHT_CAP_SHORT_GI_80				0x00000020
 #define IEEE80211_VHT_CAP_SHORT_GI_160				0x00000040
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ec5587d..1447b47 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -464,6 +464,7 @@ static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = {
 static const struct ieee80211_vht_cap mac80211_vht_capa_mod_mask = {
 	.vht_cap_info =
 		cpu_to_le32(IEEE80211_VHT_CAP_RXLDPC |
+			    IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK |
 			    IEEE80211_VHT_CAP_SHORT_GI_80 |
 			    IEEE80211_VHT_CAP_SHORT_GI_160 |
 			    IEEE80211_VHT_CAP_RXSTBC_1 |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 720c64c..5684e13 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -56,6 +56,29 @@ void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
 	__check_vhtcap_disable(sdata, vht_cap,
 			       IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN);
 
+	/* Allow disabling 160Mhz or 80+80 */
+	if (sdata->u.mgd.vht_capa_mask.vht_cap_info &
+	    cpu_to_le32(IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK)) {
+		u32 cap, n;
+
+		n = le32_to_cpu(sdata->u.mgd.vht_capa.vht_cap_info) &
+			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+		n >>= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_SHIFT;
+		cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+		cap >>= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_SHIFT;
+
+		if (n < cap) {
+			vht_cap->cap &=
+				~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+			vht_cap->cap |=
+				n << IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_SHIFT;
+
+			/* Cannot do short GI 160 if we cannot do 160 or 80+80 */
+			if (n == 0)
+				vht_cap->cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
+		}
+	}
+
 	/* Allow user to decrease AMPDU length exponent */
 	if (sdata->u.mgd.vht_capa_mask.vht_cap_info &
 	    cpu_to_le32(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK)) {
-- 
2.4.11

^ permalink raw reply related

* [PATCH v2 1/2] ath10k: improve the firmware download time for QCA6174
From: ryanhsu @ 2017-02-16  0:33 UTC (permalink / raw)
  To: ath10k, linux-wireless; +Cc: lenb, ryanhsu

From: Ryan Hsu <ryanhsu@qca.qualcomm.com>

Len Brown reported the system resume time is taking more than 2 seconds in
bug - https://bugzilla.kernel.org/show_bug.cgi?id=185621.

The reason of the 2 seconds is due to the firmware download time.

The chip is booted up in the default reference clock speed to handle the
firmware download to chip memory and advanced to the support higher speed
clock to run the firmware after all. The default reference clock in the
hardware is slow so that the firmware download time is taking up to 2
seconds for a 600KB firmware file.

	[76796.349701] ath10k_pci : boot uploading firmware image len 688691
	[76798.334612] ath10k_pci : htt tx max num pending tx 1056

The resolution here is to enable the higher speed clock if the hardware
supported before the firmware download at BMI stage, so that the hardware
can handle the firmare download in a more efficient way. This can help to
improve the firmware download time from 2 seconds to around 500ms for the
same 600KB firmware file.

	[322858.577919] ath10k_pci boot uploading firmware image len 688691
	[322859.093094] ath10k_pci htt tx max num pending tx 1056

The steps to advance to the higher speed clock is very hardware specific,
so adding the hardware ops for the hardware that can support this.

Reported-by: Len Brown <lenb@kernel.org>
Signed-off-by: Ryan Hsu <ryanhsu@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/bmi.c  |  72 +++++++++
 drivers/net/wireless/ath/ath10k/bmi.h  |   2 +
 drivers/net/wireless/ath/ath10k/core.c |   4 +-
 drivers/net/wireless/ath/ath10k/hw.c   | 265 +++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/hw.h   |  69 +++++++++
 5 files changed, 411 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c
index 2872d34..abeee20 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.c
+++ b/drivers/net/wireless/ath/ath10k/bmi.c
@@ -19,12 +19,21 @@
 #include "hif.h"
 #include "debug.h"
 #include "htc.h"
+#include "hw.h"
 
 void ath10k_bmi_start(struct ath10k *ar)
 {
+	int ret;
+
 	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi start\n");
 
 	ar->bmi.done_sent = false;
+
+	/* Enable hardware clock to speed up firmware download */
+	if (ar->hw_params.hw_ops->enable_pll_clk) {
+		ret = ar->hw_params.hw_ops->enable_pll_clk(ar);
+		ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi enable pll ret %d\n", ret);
+	}
 }
 
 int ath10k_bmi_done(struct ath10k *ar)
@@ -129,6 +138,69 @@ int ath10k_bmi_read_memory(struct ath10k *ar,
 	return 0;
 }
 
+int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val)
+{
+	struct bmi_cmd cmd;
+	u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.write_soc_reg);
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_BMI,
+		   "bmi write soc register 0x%08x val 0x%08x\n",
+		   address, reg_val);
+
+	if (ar->bmi.done_sent) {
+		ath10k_warn(ar, "bmi write soc register command in progress\n");
+		return -EBUSY;
+	}
+
+	cmd.id = __cpu_to_le32(BMI_WRITE_SOC_REGISTER);
+	cmd.write_soc_reg.addr = __cpu_to_le32(address);
+	cmd.write_soc_reg.value = __cpu_to_le32(reg_val);
+
+	ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
+	if (ret) {
+		ath10k_warn(ar, "Unable to write soc register to device: %d\n",
+			    ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int ath10k_bmi_read_soc_reg(struct ath10k *ar, u32 address, u32 *reg_val)
+{
+	struct bmi_cmd cmd;
+	union bmi_resp resp;
+	u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.read_soc_reg);
+	u32 resplen = sizeof(resp.read_soc_reg);
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi read soc register 0x%08x\n",
+		   address);
+
+	if (ar->bmi.done_sent) {
+		ath10k_warn(ar, "bmi read soc register command in progress\n");
+		return -EBUSY;
+	}
+
+	cmd.id = __cpu_to_le32(BMI_READ_SOC_REGISTER);
+	cmd.read_soc_reg.addr = __cpu_to_le32(address);
+
+	ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen);
+	if (ret) {
+		ath10k_warn(ar, "Unable to read soc register from device: %d\n",
+			    ret);
+		return ret;
+	}
+
+	*reg_val = __le32_to_cpu(resp.read_soc_reg.value);
+
+	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi read soc register value 0x%08x\n",
+		   *reg_val);
+
+	return 0;
+}
+
 int ath10k_bmi_write_memory(struct ath10k *ar,
 			    u32 address, const void *buffer, u32 length)
 {
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index 7d3231a..a65f262 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -232,4 +232,6 @@ int ath10k_bmi_write_memory(struct ath10k *ar, u32 address,
 int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length);
 int ath10k_bmi_fast_download(struct ath10k *ar, u32 address,
 			     const void *buffer, u32 length);
+int ath10k_bmi_read_soc_reg(struct ath10k *ar, u32 address, u32 *reg_val);
+int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val);
 #endif /* _BMI_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 014a87e..c6de267 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -166,7 +166,9 @@
 			.board_size = QCA6174_BOARD_DATA_SZ,
 			.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
 		},
-		.hw_ops = &qca988x_ops,
+		.hw_ops = &qca6174_ops,
+		.hw_clk = qca6174_clk,
+		.target_cpu_freq = 176000000,
 		.decap_align_bytes = 4,
 	},
 	{
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index 33fb268..85582bd 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -19,6 +19,7 @@
 #include "hw.h"
 #include "hif.h"
 #include "wmi-ops.h"
+#include "bmi.h"
 
 const struct ath10k_hw_regs qca988x_regs = {
 	.rtc_soc_base_address		= 0x00004000,
@@ -72,6 +73,9 @@
 	.pcie_intr_fw_mask			= 0x00000400,
 	.pcie_intr_ce_mask_all			= 0x0007f800,
 	.pcie_intr_clr_address			= 0x00000014,
+	.cpu_pll_init_address			= 0x00404020,
+	.cpu_speed_address			= 0x00404024,
+	.core_clk_div_address			= 0x00404028,
 };
 
 const struct ath10k_hw_regs qca99x0_regs = {
@@ -187,6 +191,73 @@
 	.ce_desc_meta_data_lsb          = 4,
 };
 
+const struct ath10k_hw_clk_params qca6174_clk[ATH10K_HW_REFCLK_COUNT] = {
+	{
+		.refclk = 48000000,
+		.div = 0xe,
+		.rnfrac = 0x2aaa8,
+		.settle_time = 2400,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 19200000,
+		.div = 0x24,
+		.rnfrac = 0x2aaa8,
+		.settle_time = 960,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 24000000,
+		.div = 0x1d,
+		.rnfrac = 0x15551,
+		.settle_time = 1200,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 26000000,
+		.div = 0x1b,
+		.rnfrac = 0x4ec4,
+		.settle_time = 1300,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 37400000,
+		.div = 0x12,
+		.rnfrac = 0x34b49,
+		.settle_time = 1870,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 38400000,
+		.div = 0x12,
+		.rnfrac = 0x15551,
+		.settle_time = 1920,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 40000000,
+		.div = 0x12,
+		.rnfrac = 0x26665,
+		.settle_time = 2000,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 52000000,
+		.div = 0x1b,
+		.rnfrac = 0x4ec4,
+		.settle_time = 2600,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+};
+
 void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
 				u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
 {
@@ -361,6 +432,195 @@ static void ath10k_hw_qca988x_set_coverage_class(struct ath10k *ar,
 	mutex_unlock(&ar->conf_mutex);
 }
 
+/**
+ * ath10k_hw_qca6174_enable_pll_clock() - enable the qca6174 hw pll clock
+ * @ar: the ath10k blob
+ *
+ * This function is very hardware specific, the clock initialization
+ * steps is very sensitive and could lead to unknown crash, so they
+ * should be done in sequence.
+ *
+ * *** Be aware if you planned to refactor them. ***
+ *
+ * Return: 0 if successfully enable the pll, otherwise EINVAL
+ */
+static int ath10k_hw_qca6174_enable_pll_clock(struct ath10k *ar)
+{
+	int ret, wait_limit;
+	u32 clk_div_addr, pll_init_addr, speed_addr;
+	u32 addr, reg_val, mem_val;
+	struct ath10k_hw_params *hw;
+	const struct ath10k_hw_clk_params *hw_clk;
+
+	hw = &ar->hw_params;
+
+	if (ar->regs->core_clk_div_address == 0 ||
+	    ar->regs->cpu_pll_init_address == 0 ||
+	    ar->regs->cpu_speed_address == 0)
+		return -EINVAL;
+
+	clk_div_addr = ar->regs->core_clk_div_address;
+	pll_init_addr = ar->regs->cpu_pll_init_address;
+	speed_addr = ar->regs->cpu_speed_address;
+
+	/* Read efuse register to find out the right hw clock configuration */
+	addr = (RTC_SOC_BASE_ADDRESS | EFUSE_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* sanitize if the hw refclk index is out of the boundary */
+	if (MS(reg_val, EFUSE_XTAL_SEL) > ATH10K_HW_REFCLK_COUNT)
+		return -EINVAL;
+
+	hw_clk = &hw->hw_clk[MS(reg_val, EFUSE_XTAL_SEL)];
+
+	/* Set the rnfrac and outdiv params to bb_pll register */
+	addr = (RTC_SOC_BASE_ADDRESS | BB_PLL_CONFIG_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~(BB_PLL_CONFIG_FRAC_MASK | BB_PLL_CONFIG_OUTDIV_MASK);
+	reg_val |= (SM(hw_clk->rnfrac, BB_PLL_CONFIG_FRAC) |
+		    SM(hw_clk->outdiv, BB_PLL_CONFIG_OUTDIV));
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* Set the correct settle time value to pll_settle register */
+	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_SETTLE_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~WLAN_PLL_SETTLE_TIME_MASK;
+	reg_val |= SM(hw_clk->settle_time, WLAN_PLL_SETTLE_TIME);
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* Set the clock_ctrl div to core_clk_ctrl register */
+	addr = (RTC_SOC_BASE_ADDRESS | SOC_CORE_CLK_CTRL_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~SOC_CORE_CLK_CTRL_DIV_MASK;
+	reg_val |= SM(1, SOC_CORE_CLK_CTRL_DIV);
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* Set the clock_div register */
+	mem_val = 1;
+	ret = ath10k_bmi_write_memory(ar, clk_div_addr, &mem_val,
+				      sizeof(mem_val));
+	if (ret)
+		return -EINVAL;
+
+	/* Configure the pll_control register */
+	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val |= (SM(hw_clk->refdiv, WLAN_PLL_CONTROL_REFDIV) |
+		    SM(hw_clk->div, WLAN_PLL_CONTROL_DIV) |
+		    SM(1, WLAN_PLL_CONTROL_NOPWD));
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* busy wait (max 1s) the rtc_sync status register indicate ready */
+	wait_limit = 100000;
+	addr = (RTC_WMAC_BASE_ADDRESS | RTC_SYNC_STATUS_OFFSET);
+	do {
+		ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+		if (ret)
+			return -EINVAL;
+
+		if (!MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
+			break;
+
+		wait_limit--;
+		udelay(10);
+
+	} while (wait_limit > 0);
+
+	if (MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
+		return -EINVAL;
+
+	/* Unset the pll_bypass in pll_control register */
+	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~WLAN_PLL_CONTROL_BYPASS_MASK;
+	reg_val |= SM(0, WLAN_PLL_CONTROL_BYPASS);
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* busy wait (max 1s) the rtc_sync status register indicate ready */
+	wait_limit = 100000;
+	addr = (RTC_WMAC_BASE_ADDRESS | RTC_SYNC_STATUS_OFFSET);
+	do {
+		ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+		if (ret)
+			return -EINVAL;
+
+		if (!MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
+			break;
+
+		wait_limit--;
+		udelay(10);
+
+	} while (wait_limit > 0);
+
+	if (MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
+		return -EINVAL;
+
+	/* Enable the hardware cpu clock register */
+	addr = (RTC_SOC_BASE_ADDRESS | SOC_CPU_CLOCK_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~SOC_CPU_CLOCK_STANDARD_MASK;
+	reg_val |= SM(1, SOC_CPU_CLOCK_STANDARD);
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* unset the nopwd from pll_control register */
+	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~WLAN_PLL_CONTROL_NOPWD_MASK;
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* enable the pll_init register */
+	mem_val = 1;
+	ret = ath10k_bmi_write_memory(ar, pll_init_addr, &mem_val,
+				      sizeof(mem_val));
+	if (ret)
+		return -EINVAL;
+
+	/* set the target clock frequency to speed register */
+	ret = ath10k_bmi_write_memory(ar, speed_addr, &hw->target_cpu_freq,
+				      sizeof(hw->target_cpu_freq));
+	if (ret)
+		return -EINVAL;
+
+	return 0;
+}
+
 const struct ath10k_hw_ops qca988x_ops = {
 	.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
 };
@@ -374,3 +634,8 @@ static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd)
 const struct ath10k_hw_ops qca99x0_ops = {
 	.rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes,
 };
+
+const struct ath10k_hw_ops qca6174_ops = {
+	.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
+	.enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock,
+};
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 38aa7c9..1ca1278 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -251,6 +251,9 @@ struct ath10k_hw_regs {
 	u32 pcie_intr_fw_mask;
 	u32 pcie_intr_ce_mask_all;
 	u32 pcie_intr_clr_address;
+	u32 cpu_pll_init_address;
+	u32 cpu_speed_address;
+	u32 core_clk_div_address;
 };
 
 extern const struct ath10k_hw_regs qca988x_regs;
@@ -359,6 +362,30 @@ enum ath10k_hw_cc_wraparound_type {
 	ATH10K_HW_CC_WRAP_SHIFTED_EACH = 2,
 };
 
+enum ath10k_hw_refclk_speed {
+	ATH10K_HW_REFCLK_UNKNOWN = -1,
+	ATH10K_HW_REFCLK_48_MHZ = 0,
+	ATH10K_HW_REFCLK_19_2_MHZ = 1,
+	ATH10K_HW_REFCLK_24_MHZ = 2,
+	ATH10K_HW_REFCLK_26_MHZ = 3,
+	ATH10K_HW_REFCLK_37_4_MHZ = 4,
+	ATH10K_HW_REFCLK_38_4_MHZ = 5,
+	ATH10K_HW_REFCLK_40_MHZ = 6,
+	ATH10K_HW_REFCLK_52_MHZ = 7,
+
+	/* must be the last one */
+	ATH10K_HW_REFCLK_COUNT,
+};
+
+struct ath10k_hw_clk_params {
+	u32 refclk;
+	u32 div;
+	u32 rnfrac;
+	u32 settle_time;
+	u32 refdiv;
+	u32 outdiv;
+};
+
 struct ath10k_hw_params {
 	u32 id;
 	u16 dev_id;
@@ -412,6 +439,10 @@ struct ath10k_hw_params {
 
 	/* Number of bytes used for alignment in rx_hdr_status of rx desc. */
 	int decap_align_bytes;
+
+	/* hw specific clock control parameters */
+	const struct ath10k_hw_clk_params *hw_clk;
+	int target_cpu_freq;
 };
 
 struct htt_rx_desc;
@@ -420,10 +451,14 @@ struct ath10k_hw_params {
 struct ath10k_hw_ops {
 	int (*rx_desc_get_l3_pad_bytes)(struct htt_rx_desc *rxd);
 	void (*set_coverage_class)(struct ath10k *ar, s16 value);
+	int (*enable_pll_clk)(struct ath10k *ar);
 };
 
 extern const struct ath10k_hw_ops qca988x_ops;
 extern const struct ath10k_hw_ops qca99x0_ops;
+extern const struct ath10k_hw_ops qca6174_ops;
+
+extern const struct ath10k_hw_clk_params qca6174_clk[];
 
 static inline int
 ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
@@ -843,4 +878,38 @@ struct ath10k_hw_ops {
 #define WAVE1_PHYCLK_USEC_MASK			0x0000007F
 #define WAVE1_PHYCLK_USEC_LSB			0
 
+/* qca6174 PLL offset/mask */
+#define SOC_CORE_CLK_CTRL_OFFSET		0x00000114
+#define SOC_CORE_CLK_CTRL_DIV_LSB		0
+#define SOC_CORE_CLK_CTRL_DIV_MASK		0x00000007
+
+#define EFUSE_OFFSET				0x0000032c
+#define EFUSE_XTAL_SEL_LSB			8
+#define EFUSE_XTAL_SEL_MASK			0x00000700
+
+#define BB_PLL_CONFIG_OFFSET			0x000002f4
+#define BB_PLL_CONFIG_FRAC_LSB			0
+#define BB_PLL_CONFIG_FRAC_MASK			0x0003ffff
+#define BB_PLL_CONFIG_OUTDIV_LSB		18
+#define BB_PLL_CONFIG_OUTDIV_MASK		0x001c0000
+
+#define WLAN_PLL_SETTLE_OFFSET			0x0018
+#define WLAN_PLL_SETTLE_TIME_LSB		0
+#define WLAN_PLL_SETTLE_TIME_MASK		0x000007ff
+
+#define WLAN_PLL_CONTROL_OFFSET			0x0014
+#define WLAN_PLL_CONTROL_DIV_LSB		0
+#define WLAN_PLL_CONTROL_DIV_MASK		0x000003ff
+#define WLAN_PLL_CONTROL_REFDIV_LSB		10
+#define WLAN_PLL_CONTROL_REFDIV_MASK		0x00003c00
+#define WLAN_PLL_CONTROL_BYPASS_LSB		16
+#define WLAN_PLL_CONTROL_BYPASS_MASK		0x00010000
+#define WLAN_PLL_CONTROL_NOPWD_LSB		18
+#define WLAN_PLL_CONTROL_NOPWD_MASK		0x00040000
+
+#define RTC_SYNC_STATUS_OFFSET			0x0244
+#define RTC_SYNC_STATUS_PLL_CHANGING_LSB	5
+#define RTC_SYNC_STATUS_PLL_CHANGING_MASK	0x00000020
+/* qca6174 PLL offset/mask end */
+
 #endif /* _HW_H_ */
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2 2/2] ath10k: improve the firmware download time for QCA9377
From: ryanhsu @ 2017-02-16  0:33 UTC (permalink / raw)
  To: ath10k, linux-wireless; +Cc: lenb, ryanhsu
In-Reply-To: <1487205210-17112-1-git-send-email-ryanhsu@qca.qualcomm.com>

From: Ryan Hsu <ryanhsu@qca.qualcomm.com>

QCA9377 is the family of QCA61x4 which shared the same procedure
to enable the hardware clock that could improve the firmware download time.

Signed-off-by: Ryan Hsu <ryanhsu@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/core.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index c6de267..91e2731 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -282,7 +282,9 @@
 			.board_size = QCA9377_BOARD_DATA_SZ,
 			.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
 		},
-		.hw_ops = &qca988x_ops,
+		.hw_ops = &qca6174_ops,
+		.hw_clk = qca6174_clk,
+		.target_cpu_freq = 176000000,
 		.decap_align_bytes = 4,
 	},
 	{
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH 1/2] ath10k: improve the firmware download time for QCA6174
From: kbuild test robot @ 2017-02-16  0:20 UTC (permalink / raw)
  To: ryanhsu; +Cc: kbuild-all, ath10k, linux-wireless, lenb, ryanhsu
In-Reply-To: <1487202638-13244-1-git-send-email-ryanhsu@qca.qualcomm.com>

[-- Attachment #1: Type: text/plain, Size: 1450 bytes --]

Hi Ryan,

[auto build test ERROR on ath6kl/ath-next]
[also build test ERROR on v4.10-rc8 next-20170215]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/ryanhsu-qca-qualcomm-com/ath10k-improve-the-firmware-download-time-for-QCA6174/20170216-075853
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git ath-next
config: x86_64-randconfig-x006-201707 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/net/wireless/ath/ath10k/bmi.c: In function 'ath10k_bmi_start':
>> drivers/net/wireless/ath/ath10k/bmi.c:35:3: error: expected ';' before 'ath10k_dbg'
      ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi enable pll ret %d\n", ret);
      ^~~~~~~~~~

vim +35 drivers/net/wireless/ath/ath10k/bmi.c

    29	
    30		ar->bmi.done_sent = false;
    31	
    32		/* Enable hardware clock to speed up firmware download */
    33		if (ar->hw_params.hw_ops->enable_pll_clk) {
    34			ret = ar->hw_params.hw_ops->enable_pll_clk(ar)
  > 35			ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi enable pll ret %d\n", ret);
    36		}
    37	}
    38	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 31869 bytes --]

^ permalink raw reply

* [PATCH 1/2] ath10k: improve the firmware download time for QCA6174
From: ryanhsu @ 2017-02-15 23:50 UTC (permalink / raw)
  To: ath10k, linux-wireless; +Cc: lenb, ryanhsu

From: Ryan Hsu <ryanhsu@qca.qualcomm.com>

Len Brown reported the system resume time is taking more than 2 seconds in
bug - https://bugzilla.kernel.org/show_bug.cgi?id=185621.

The reason of the 2 seconds is due to the firmware download time.

The chip is booted up in the default reference clock speed to handle the
firmware download to chip memory and advanced to the support higher speed
clock to run the firmware after all. The default reference clock in the
hardware is slow so that the firmware download time is taking up to 2
seconds for a 600KB firmware file.

	[76796.349701] ath10k_pci : boot uploading firmware image len 688691
	[76798.334612] ath10k_pci : htt tx max num pending tx 1056

The resolution here is to enable the higher speed clock if the hardware
supported before the firmware download at BMI stage, so that the hardware
can handle the firmare download in a more efficient way. This can help to
improve the firmware download time from 2 seconds to around 500ms for the
same 600KB firmware file.

	[322858.577919] ath10k_pci boot uploading firmware image len 688691
	[322859.093094] ath10k_pci htt tx max num pending tx 1056

The steps to advance to the higher speed clock is very hardware specific,
so adding the hardware ops for the hardware that can support this.

Reported-by: Len Brown <lenb@kernel.org>
Signed-off-by: Ryan Hsu <ryanhsu@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/bmi.c  |  72 +++++++++
 drivers/net/wireless/ath/ath10k/bmi.h  |   2 +
 drivers/net/wireless/ath/ath10k/core.c |   4 +-
 drivers/net/wireless/ath/ath10k/hw.c   | 265 +++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/hw.h   |  69 +++++++++
 5 files changed, 411 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c
index 2872d34..073a6f3 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.c
+++ b/drivers/net/wireless/ath/ath10k/bmi.c
@@ -19,12 +19,21 @@
 #include "hif.h"
 #include "debug.h"
 #include "htc.h"
+#include "hw.h"
 
 void ath10k_bmi_start(struct ath10k *ar)
 {
+	int ret;
+
 	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi start\n");
 
 	ar->bmi.done_sent = false;
+
+	/* Enable hardware clock to speed up firmware download */
+	if (ar->hw_params.hw_ops->enable_pll_clk) {
+		ret = ar->hw_params.hw_ops->enable_pll_clk(ar)
+		ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi enable pll ret %d\n", ret);
+	}
 }
 
 int ath10k_bmi_done(struct ath10k *ar)
@@ -129,6 +138,69 @@ int ath10k_bmi_read_memory(struct ath10k *ar,
 	return 0;
 }
 
+int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val)
+{
+	struct bmi_cmd cmd;
+	u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.write_soc_reg);
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_BMI,
+		   "bmi write soc register 0x%08x val 0x%08x\n",
+		   address, reg_val);
+
+	if (ar->bmi.done_sent) {
+		ath10k_warn(ar, "bmi write soc register command in progress\n");
+		return -EBUSY;
+	}
+
+	cmd.id = __cpu_to_le32(BMI_WRITE_SOC_REGISTER);
+	cmd.write_soc_reg.addr = __cpu_to_le32(address);
+	cmd.write_soc_reg.value = __cpu_to_le32(reg_val);
+
+	ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
+	if (ret) {
+		ath10k_warn(ar, "Unable to write soc register to device: %d\n",
+			    ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int ath10k_bmi_read_soc_reg(struct ath10k *ar, u32 address, u32 *reg_val)
+{
+	struct bmi_cmd cmd;
+	union bmi_resp resp;
+	u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.read_soc_reg);
+	u32 resplen = sizeof(resp.read_soc_reg);
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi read soc register 0x%08x\n",
+		   address);
+
+	if (ar->bmi.done_sent) {
+		ath10k_warn(ar, "bmi read soc register command in progress\n");
+		return -EBUSY;
+	}
+
+	cmd.id = __cpu_to_le32(BMI_READ_SOC_REGISTER);
+	cmd.read_soc_reg.addr = __cpu_to_le32(address);
+
+	ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen);
+	if (ret) {
+		ath10k_warn(ar, "Unable to read soc register from device: %d\n",
+			    ret);
+		return ret;
+	}
+
+	*reg_val = __le32_to_cpu(resp.read_soc_reg.value);
+
+	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi read soc register value 0x%08x\n",
+		   *reg_val);
+
+	return 0;
+}
+
 int ath10k_bmi_write_memory(struct ath10k *ar,
 			    u32 address, const void *buffer, u32 length)
 {
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index 7d3231a..a65f262 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -232,4 +232,6 @@ int ath10k_bmi_write_memory(struct ath10k *ar, u32 address,
 int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length);
 int ath10k_bmi_fast_download(struct ath10k *ar, u32 address,
 			     const void *buffer, u32 length);
+int ath10k_bmi_read_soc_reg(struct ath10k *ar, u32 address, u32 *reg_val);
+int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val);
 #endif /* _BMI_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 014a87e..c6de267 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -166,7 +166,9 @@
 			.board_size = QCA6174_BOARD_DATA_SZ,
 			.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
 		},
-		.hw_ops = &qca988x_ops,
+		.hw_ops = &qca6174_ops,
+		.hw_clk = qca6174_clk,
+		.target_cpu_freq = 176000000,
 		.decap_align_bytes = 4,
 	},
 	{
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index 33fb268..85582bd 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -19,6 +19,7 @@
 #include "hw.h"
 #include "hif.h"
 #include "wmi-ops.h"
+#include "bmi.h"
 
 const struct ath10k_hw_regs qca988x_regs = {
 	.rtc_soc_base_address		= 0x00004000,
@@ -72,6 +73,9 @@
 	.pcie_intr_fw_mask			= 0x00000400,
 	.pcie_intr_ce_mask_all			= 0x0007f800,
 	.pcie_intr_clr_address			= 0x00000014,
+	.cpu_pll_init_address			= 0x00404020,
+	.cpu_speed_address			= 0x00404024,
+	.core_clk_div_address			= 0x00404028,
 };
 
 const struct ath10k_hw_regs qca99x0_regs = {
@@ -187,6 +191,73 @@
 	.ce_desc_meta_data_lsb          = 4,
 };
 
+const struct ath10k_hw_clk_params qca6174_clk[ATH10K_HW_REFCLK_COUNT] = {
+	{
+		.refclk = 48000000,
+		.div = 0xe,
+		.rnfrac = 0x2aaa8,
+		.settle_time = 2400,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 19200000,
+		.div = 0x24,
+		.rnfrac = 0x2aaa8,
+		.settle_time = 960,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 24000000,
+		.div = 0x1d,
+		.rnfrac = 0x15551,
+		.settle_time = 1200,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 26000000,
+		.div = 0x1b,
+		.rnfrac = 0x4ec4,
+		.settle_time = 1300,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 37400000,
+		.div = 0x12,
+		.rnfrac = 0x34b49,
+		.settle_time = 1870,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 38400000,
+		.div = 0x12,
+		.rnfrac = 0x15551,
+		.settle_time = 1920,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 40000000,
+		.div = 0x12,
+		.rnfrac = 0x26665,
+		.settle_time = 2000,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+	{
+		.refclk = 52000000,
+		.div = 0x1b,
+		.rnfrac = 0x4ec4,
+		.settle_time = 2600,
+		.refdiv = 0,
+		.outdiv = 1,
+	},
+};
+
 void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
 				u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
 {
@@ -361,6 +432,195 @@ static void ath10k_hw_qca988x_set_coverage_class(struct ath10k *ar,
 	mutex_unlock(&ar->conf_mutex);
 }
 
+/**
+ * ath10k_hw_qca6174_enable_pll_clock() - enable the qca6174 hw pll clock
+ * @ar: the ath10k blob
+ *
+ * This function is very hardware specific, the clock initialization
+ * steps is very sensitive and could lead to unknown crash, so they
+ * should be done in sequence.
+ *
+ * *** Be aware if you planned to refactor them. ***
+ *
+ * Return: 0 if successfully enable the pll, otherwise EINVAL
+ */
+static int ath10k_hw_qca6174_enable_pll_clock(struct ath10k *ar)
+{
+	int ret, wait_limit;
+	u32 clk_div_addr, pll_init_addr, speed_addr;
+	u32 addr, reg_val, mem_val;
+	struct ath10k_hw_params *hw;
+	const struct ath10k_hw_clk_params *hw_clk;
+
+	hw = &ar->hw_params;
+
+	if (ar->regs->core_clk_div_address == 0 ||
+	    ar->regs->cpu_pll_init_address == 0 ||
+	    ar->regs->cpu_speed_address == 0)
+		return -EINVAL;
+
+	clk_div_addr = ar->regs->core_clk_div_address;
+	pll_init_addr = ar->regs->cpu_pll_init_address;
+	speed_addr = ar->regs->cpu_speed_address;
+
+	/* Read efuse register to find out the right hw clock configuration */
+	addr = (RTC_SOC_BASE_ADDRESS | EFUSE_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* sanitize if the hw refclk index is out of the boundary */
+	if (MS(reg_val, EFUSE_XTAL_SEL) > ATH10K_HW_REFCLK_COUNT)
+		return -EINVAL;
+
+	hw_clk = &hw->hw_clk[MS(reg_val, EFUSE_XTAL_SEL)];
+
+	/* Set the rnfrac and outdiv params to bb_pll register */
+	addr = (RTC_SOC_BASE_ADDRESS | BB_PLL_CONFIG_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~(BB_PLL_CONFIG_FRAC_MASK | BB_PLL_CONFIG_OUTDIV_MASK);
+	reg_val |= (SM(hw_clk->rnfrac, BB_PLL_CONFIG_FRAC) |
+		    SM(hw_clk->outdiv, BB_PLL_CONFIG_OUTDIV));
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* Set the correct settle time value to pll_settle register */
+	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_SETTLE_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~WLAN_PLL_SETTLE_TIME_MASK;
+	reg_val |= SM(hw_clk->settle_time, WLAN_PLL_SETTLE_TIME);
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* Set the clock_ctrl div to core_clk_ctrl register */
+	addr = (RTC_SOC_BASE_ADDRESS | SOC_CORE_CLK_CTRL_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~SOC_CORE_CLK_CTRL_DIV_MASK;
+	reg_val |= SM(1, SOC_CORE_CLK_CTRL_DIV);
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* Set the clock_div register */
+	mem_val = 1;
+	ret = ath10k_bmi_write_memory(ar, clk_div_addr, &mem_val,
+				      sizeof(mem_val));
+	if (ret)
+		return -EINVAL;
+
+	/* Configure the pll_control register */
+	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val |= (SM(hw_clk->refdiv, WLAN_PLL_CONTROL_REFDIV) |
+		    SM(hw_clk->div, WLAN_PLL_CONTROL_DIV) |
+		    SM(1, WLAN_PLL_CONTROL_NOPWD));
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* busy wait (max 1s) the rtc_sync status register indicate ready */
+	wait_limit = 100000;
+	addr = (RTC_WMAC_BASE_ADDRESS | RTC_SYNC_STATUS_OFFSET);
+	do {
+		ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+		if (ret)
+			return -EINVAL;
+
+		if (!MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
+			break;
+
+		wait_limit--;
+		udelay(10);
+
+	} while (wait_limit > 0);
+
+	if (MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
+		return -EINVAL;
+
+	/* Unset the pll_bypass in pll_control register */
+	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~WLAN_PLL_CONTROL_BYPASS_MASK;
+	reg_val |= SM(0, WLAN_PLL_CONTROL_BYPASS);
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* busy wait (max 1s) the rtc_sync status register indicate ready */
+	wait_limit = 100000;
+	addr = (RTC_WMAC_BASE_ADDRESS | RTC_SYNC_STATUS_OFFSET);
+	do {
+		ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+		if (ret)
+			return -EINVAL;
+
+		if (!MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
+			break;
+
+		wait_limit--;
+		udelay(10);
+
+	} while (wait_limit > 0);
+
+	if (MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
+		return -EINVAL;
+
+	/* Enable the hardware cpu clock register */
+	addr = (RTC_SOC_BASE_ADDRESS | SOC_CPU_CLOCK_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~SOC_CPU_CLOCK_STANDARD_MASK;
+	reg_val |= SM(1, SOC_CPU_CLOCK_STANDARD);
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* unset the nopwd from pll_control register */
+	addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
+	ret = ath10k_bmi_read_soc_reg(ar, addr, &reg_val);
+	if (ret)
+		return -EINVAL;
+
+	reg_val &= ~WLAN_PLL_CONTROL_NOPWD_MASK;
+	ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
+	if (ret)
+		return -EINVAL;
+
+	/* enable the pll_init register */
+	mem_val = 1;
+	ret = ath10k_bmi_write_memory(ar, pll_init_addr, &mem_val,
+				      sizeof(mem_val));
+	if (ret)
+		return -EINVAL;
+
+	/* set the target clock frequency to speed register */
+	ret = ath10k_bmi_write_memory(ar, speed_addr, &hw->target_cpu_freq,
+				      sizeof(hw->target_cpu_freq));
+	if (ret)
+		return -EINVAL;
+
+	return 0;
+}
+
 const struct ath10k_hw_ops qca988x_ops = {
 	.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
 };
@@ -374,3 +634,8 @@ static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd)
 const struct ath10k_hw_ops qca99x0_ops = {
 	.rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes,
 };
+
+const struct ath10k_hw_ops qca6174_ops = {
+	.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
+	.enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock,
+};
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 38aa7c9..1ca1278 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -251,6 +251,9 @@ struct ath10k_hw_regs {
 	u32 pcie_intr_fw_mask;
 	u32 pcie_intr_ce_mask_all;
 	u32 pcie_intr_clr_address;
+	u32 cpu_pll_init_address;
+	u32 cpu_speed_address;
+	u32 core_clk_div_address;
 };
 
 extern const struct ath10k_hw_regs qca988x_regs;
@@ -359,6 +362,30 @@ enum ath10k_hw_cc_wraparound_type {
 	ATH10K_HW_CC_WRAP_SHIFTED_EACH = 2,
 };
 
+enum ath10k_hw_refclk_speed {
+	ATH10K_HW_REFCLK_UNKNOWN = -1,
+	ATH10K_HW_REFCLK_48_MHZ = 0,
+	ATH10K_HW_REFCLK_19_2_MHZ = 1,
+	ATH10K_HW_REFCLK_24_MHZ = 2,
+	ATH10K_HW_REFCLK_26_MHZ = 3,
+	ATH10K_HW_REFCLK_37_4_MHZ = 4,
+	ATH10K_HW_REFCLK_38_4_MHZ = 5,
+	ATH10K_HW_REFCLK_40_MHZ = 6,
+	ATH10K_HW_REFCLK_52_MHZ = 7,
+
+	/* must be the last one */
+	ATH10K_HW_REFCLK_COUNT,
+};
+
+struct ath10k_hw_clk_params {
+	u32 refclk;
+	u32 div;
+	u32 rnfrac;
+	u32 settle_time;
+	u32 refdiv;
+	u32 outdiv;
+};
+
 struct ath10k_hw_params {
 	u32 id;
 	u16 dev_id;
@@ -412,6 +439,10 @@ struct ath10k_hw_params {
 
 	/* Number of bytes used for alignment in rx_hdr_status of rx desc. */
 	int decap_align_bytes;
+
+	/* hw specific clock control parameters */
+	const struct ath10k_hw_clk_params *hw_clk;
+	int target_cpu_freq;
 };
 
 struct htt_rx_desc;
@@ -420,10 +451,14 @@ struct ath10k_hw_params {
 struct ath10k_hw_ops {
 	int (*rx_desc_get_l3_pad_bytes)(struct htt_rx_desc *rxd);
 	void (*set_coverage_class)(struct ath10k *ar, s16 value);
+	int (*enable_pll_clk)(struct ath10k *ar);
 };
 
 extern const struct ath10k_hw_ops qca988x_ops;
 extern const struct ath10k_hw_ops qca99x0_ops;
+extern const struct ath10k_hw_ops qca6174_ops;
+
+extern const struct ath10k_hw_clk_params qca6174_clk[];
 
 static inline int
 ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
@@ -843,4 +878,38 @@ struct ath10k_hw_ops {
 #define WAVE1_PHYCLK_USEC_MASK			0x0000007F
 #define WAVE1_PHYCLK_USEC_LSB			0
 
+/* qca6174 PLL offset/mask */
+#define SOC_CORE_CLK_CTRL_OFFSET		0x00000114
+#define SOC_CORE_CLK_CTRL_DIV_LSB		0
+#define SOC_CORE_CLK_CTRL_DIV_MASK		0x00000007
+
+#define EFUSE_OFFSET				0x0000032c
+#define EFUSE_XTAL_SEL_LSB			8
+#define EFUSE_XTAL_SEL_MASK			0x00000700
+
+#define BB_PLL_CONFIG_OFFSET			0x000002f4
+#define BB_PLL_CONFIG_FRAC_LSB			0
+#define BB_PLL_CONFIG_FRAC_MASK			0x0003ffff
+#define BB_PLL_CONFIG_OUTDIV_LSB		18
+#define BB_PLL_CONFIG_OUTDIV_MASK		0x001c0000
+
+#define WLAN_PLL_SETTLE_OFFSET			0x0018
+#define WLAN_PLL_SETTLE_TIME_LSB		0
+#define WLAN_PLL_SETTLE_TIME_MASK		0x000007ff
+
+#define WLAN_PLL_CONTROL_OFFSET			0x0014
+#define WLAN_PLL_CONTROL_DIV_LSB		0
+#define WLAN_PLL_CONTROL_DIV_MASK		0x000003ff
+#define WLAN_PLL_CONTROL_REFDIV_LSB		10
+#define WLAN_PLL_CONTROL_REFDIV_MASK		0x00003c00
+#define WLAN_PLL_CONTROL_BYPASS_LSB		16
+#define WLAN_PLL_CONTROL_BYPASS_MASK		0x00010000
+#define WLAN_PLL_CONTROL_NOPWD_LSB		18
+#define WLAN_PLL_CONTROL_NOPWD_MASK		0x00040000
+
+#define RTC_SYNC_STATUS_OFFSET			0x0244
+#define RTC_SYNC_STATUS_PLL_CHANGING_LSB	5
+#define RTC_SYNC_STATUS_PLL_CHANGING_MASK	0x00000020
+/* qca6174 PLL offset/mask end */
+
 #endif /* _HW_H_ */
-- 
1.9.1

^ permalink raw reply related

* [PATCH 2/2] ath10k: improve the firmware download time for QCA9377
From: ryanhsu @ 2017-02-15 23:50 UTC (permalink / raw)
  To: ath10k, linux-wireless; +Cc: lenb, ryanhsu
In-Reply-To: <1487202638-13244-1-git-send-email-ryanhsu@qca.qualcomm.com>

From: Ryan Hsu <ryanhsu@qca.qualcomm.com>

QCA9377 is the family of QCA61x4 which shared the same procedure
to enable the hardware clock that could improve the firmware download time.

Signed-off-by: Ryan Hsu <ryanhsu@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/core.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index c6de267..91e2731 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -282,7 +282,9 @@
 			.board_size = QCA9377_BOARD_DATA_SZ,
 			.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
 		},
-		.hw_ops = &qca988x_ops,
+		.hw_ops = &qca6174_ops,
+		.hw_clk = qca6174_clk,
+		.target_cpu_freq = 176000000,
 		.decap_align_bytes = 4,
 	},
 	{
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH v5 1/3] Documentation: dt: net: add mt76 wireless device binding
From: Rob Herring @ 2017-02-15 22:33 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, kvalo, sgruszka, devicetree
In-Reply-To: <20170207202035.64224-2-nbd@nbd.name>

On Tue, Feb 07, 2017 at 09:20:33PM +0100, Felix Fietkau wrote:
> Signed-off-by: Felix Fietkau <nbd@nbd.name>

Commit msg? Also, use "dt-bindings: net: " for the subject prefix.

> ---
>  .../bindings/net/wireless/mediatek,mt76.txt        | 24 ++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt
> 
> diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt
> new file mode 100644
> index 000000000000..19522ab97d62
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt
> @@ -0,0 +1,24 @@
> +* MediaTek mt76xx devices
> +
> +This node provides properties for configuring the MediaTek mt76xx wireless
> +device. The node is expected to be specified as a child node of the PCI
> +controller to which the wireless chip is connected.
> +
> +Optional properties:
> +
> +- mac-address: See ethernet.txt in the parent directory
> +- local-mac-address: See ethernet.txt in the parent directory
> +- ieee80211-freq-limit: See ieee80211.txt
> +- mediatek,mtd-eeprom: Specify a MTD partition + offset containing EEPROM data
> +
> +&pcie {
> +	status = "okay";
> +
> +	pcie0 {
> +		wifi@0,0 {
> +			reg = <0x0000 0 0 0 0>;
> +			ieee80211-freq-limit = <5000000 6000000>;
> +			mediatek,mtd-eeprom = <&factory 0x8000>;
> +		};
> +	};
> +};
> -- 
> 2.11.0
> 

^ permalink raw reply

* [PATCH 2/2] brcmfmac: don't warn user if loading firmware file with NVRAM fails
From: Rafał Miłecki @ 2017-02-15 22:29 UTC (permalink / raw)
  To: Ming Lei, Luis R . Rodriguez, Greg KH, Linux Kernel Mailing List
  Cc: Kalle Valo, Arend van Spriel, linux-wireless,
	brcm80211-dev-list.pdl, Rafał Miłecki
In-Reply-To: <20170215222948.21030-1-zajec5@gmail.com>

From: Rafał Miłecki <rafal@milecki.pl>

This isn't critical as we use platform NVRAM as fallback and it's very
common case of all Broadcom home routers. Thanks for the new firmware
loading function we can achieve this by simply passing FW_OPT_NO_WARN.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
Kalle, Arend: this patch is strictly related to the bigger 1/2. Could you ack
this change as I expect this patchset to be picked by Ming, Luis or Greg.
---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index c7c1e9906500..26ec445a8d2d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -504,9 +504,9 @@ static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
 		return;
 	}
 	fwctx->code = fw;
-	ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
-				      fwctx->dev, GFP_KERNEL, fwctx,
-				      brcmf_fw_request_nvram_done);
+	ret = request_firmware_async(THIS_MODULE, FW_OPT_NO_WARN,
+				     fwctx->nvram_name, fwctx->dev, GFP_KERNEL,
+				     fwctx, brcmf_fw_request_nvram_done);
 
 	if (!ret)
 		return;
-- 
2.11.0

^ permalink raw reply related

* [PATCH 1/2] firmware: add more flexible request_firmware_async function
From: Rafał Miłecki @ 2017-02-15 22:29 UTC (permalink / raw)
  To: Ming Lei, Luis R . Rodriguez, Greg KH, Linux Kernel Mailing List
  Cc: Kalle Valo, Arend van Spriel, linux-wireless,
	brcm80211-dev-list.pdl, Rafał Miłecki

From: Rafał Miłecki <rafal@milecki.pl>

So far we got only one function for loading firmware asynchronously:
request_firmware_nowait. It didn't allow much customization of firmware
loading process - there is only one bool uevent argument. Moreover this
bool also controls user helper in an unclear way.

Resolve this problem by adding a one flexible function and making old
request_firmware_nowait a simple inline using new solution. This
implementation:
1) Modifies only single bits on existing code
2) Doesn't require adjusting / rewriting current drivers
3) Adds new function for drivers that need more control over loading a
   firmware. Thanks to using flags more features can be added later.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
This patch is based on top of
[PATCH V2 RESEND] firmware: simplify defining and handling FW_OPT_FALLBACK
applied on top of Linux 4.10-rc8.

Ming/Luis/Greg: assuming this gets a positive review, could someone of you pick
this patchset? Second patch modifies brcmfmac, I'll try to get a proper Ack for
that one.
Unless you want this to go through wireless tree, then let me know please.
---
 drivers/base/firmware_class.c | 25 ++++++-------------------
 include/linux/firmware.h      | 34 +++++++++++++++++++++++++++++-----
 2 files changed, 35 insertions(+), 24 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index d05be1732c8b..7b3f0a018dc3 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -182,18 +182,6 @@ static int __fw_state_check(struct fw_state *fw_st, enum fw_status status)
 
 #endif /* CONFIG_FW_LOADER_USER_HELPER */
 
-/* firmware behavior options */
-#define FW_OPT_UEVENT	(1U << 0)
-#define FW_OPT_NOWAIT	(1U << 1)
-#ifdef CONFIG_FW_LOADER_USER_HELPER
-#define FW_OPT_USERHELPER	(1U << 2)
-#else
-#define FW_OPT_USERHELPER	0
-#endif
-#define FW_OPT_NO_WARN	(1U << 3)
-#define FW_OPT_NOCACHE	(1U << 4)
-#define FW_OPT_FALLBACK	(1U << 5)
-
 struct firmware_cache {
 	/* firmware_buf instance will be added into the below list */
 	spinlock_t lock;
@@ -1356,7 +1344,7 @@ static void request_firmware_work_func(struct work_struct *work)
 	_request_firmware(&fw, fw_work->name, fw_work->device, NULL, 0,
 			  fw_work->opt_flags);
 	fw_work->cont(fw, fw_work->context);
-	put_device(fw_work->device); /* taken in request_firmware_nowait() */
+	put_device(fw_work->device); /* taken in request_firmware_async() */
 
 	module_put(fw_work->module);
 	kfree_const(fw_work->name);
@@ -1364,7 +1352,7 @@ static void request_firmware_work_func(struct work_struct *work)
 }
 
 /**
- * request_firmware_nowait - asynchronous version of request_firmware
+ * request_firmware_async - asynchronous version of request_firmware
  * @module: module requesting the firmware
  * @uevent: sends uevent to copy the firmware image if this flag
  *	is non-zero else the firmware copy must be done manually.
@@ -1387,8 +1375,8 @@ static void request_firmware_work_func(struct work_struct *work)
  *		- can't sleep at all if @gfp is GFP_ATOMIC.
  **/
 int
-request_firmware_nowait(
-	struct module *module, bool uevent,
+request_firmware_async(
+	struct module *module, unsigned int opt_flags,
 	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context))
 {
@@ -1407,8 +1395,7 @@ request_firmware_nowait(
 	fw_work->device = device;
 	fw_work->context = context;
 	fw_work->cont = cont;
-	fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK |
-		(uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
+	fw_work->opt_flags = FW_OPT_NOWAIT | opt_flags;
 
 	if (!try_module_get(module)) {
 		kfree_const(fw_work->name);
@@ -1421,7 +1408,7 @@ request_firmware_nowait(
 	schedule_work(&fw_work->work);
 	return 0;
 }
-EXPORT_SYMBOL(request_firmware_nowait);
+EXPORT_SYMBOL(request_firmware_async);
 
 #ifdef CONFIG_PM_SLEEP
 static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
diff --git a/include/linux/firmware.h b/include/linux/firmware.h
index b1f9f0ccb8ac..1f2bf14aa441 100644
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -8,6 +8,18 @@
 #define FW_ACTION_NOHOTPLUG 0
 #define FW_ACTION_HOTPLUG 1
 
+/* firmware behavior options */
+#define FW_OPT_UEVENT	(1U << 0)
+#define FW_OPT_NOWAIT	(1U << 1)
+#ifdef CONFIG_FW_LOADER_USER_HELPER
+#define FW_OPT_USERHELPER	(1U << 2)
+#else
+#define FW_OPT_USERHELPER	0
+#endif
+#define FW_OPT_NO_WARN	(1U << 3)
+#define FW_OPT_NOCACHE	(1U << 4)
+#define FW_OPT_FALLBACK	(1U << 5)
+
 struct firmware {
 	size_t size;
 	const u8 *data;
@@ -41,8 +53,8 @@ struct builtin_fw {
 #if defined(CONFIG_FW_LOADER) || (defined(CONFIG_FW_LOADER_MODULE) && defined(MODULE))
 int request_firmware(const struct firmware **fw, const char *name,
 		     struct device *device);
-int request_firmware_nowait(
-	struct module *module, bool uevent,
+int request_firmware_async(
+	struct module *module, unsigned int opt_flags,
 	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context));
 int request_firmware_direct(const struct firmware **fw, const char *name,
@@ -58,8 +70,8 @@ static inline int request_firmware(const struct firmware **fw,
 {
 	return -EINVAL;
 }
-static inline int request_firmware_nowait(
-	struct module *module, bool uevent,
+static inline int request_firmware_async(
+	struct module *module, unsigned int opt_flags,
 	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context))
 {
@@ -82,6 +94,18 @@ static inline int request_firmware_into_buf(const struct firmware **firmware_p,
 {
 	return -EINVAL;
 }
-
 #endif
+
+static inline int request_firmware_nowait(
+	struct module *module, bool uevent,
+	const char *name, struct device *device, gfp_t gfp, void *context,
+	void (*cont)(const struct firmware *fw, void *context))
+{
+	unsigned int opt_flags = FW_OPT_FALLBACK |
+		(uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
+
+	return request_firmware_async(module, opt_flags, name, device, gfp,
+				      context, cont);
+}
+
 #endif
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2] mac80211: fix mesh fail_avg check
From: Rajkumar Manoharan @ 2017-02-15 20:46 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, rmanohar, Rajkumar Manoharan

Mesh failure average never be more than 100. Only in case of
fixed path, average will be more than threshold limit (95%).
With recent EWMA changes it may go upto 99 as it is scaled to
100. It make sense to return maximum metric when average is
greater than threshold limit.

Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
---
v2: define MACRO for threshold

 net/mac80211/mesh_hwmp.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index d07ee3ca07ee..4005edd71fe8 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -16,6 +16,7 @@
 #define TEST_FRAME_LEN	8192
 #define MAX_METRIC	0xffffffff
 #define ARITH_SHIFT	8
+#define LINK_FAIL_THRESH 95
 
 #define MAX_PREQ_QUEUE_LEN	64
 
@@ -311,7 +312,8 @@ void ieee80211s_update_metric(struct ieee80211_local *local,
 	 * feed failure as 100 and success as 0
 	 */
 	ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, failed * 100);
-	if (ewma_mesh_fail_avg_read(&sta->mesh->fail_avg) > 95)
+	if (ewma_mesh_fail_avg_read(&sta->mesh->fail_avg) >
+			LINK_FAIL_THRESH)
 		mesh_plink_broken(sta);
 }
 
@@ -339,7 +341,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
 	if (rate) {
 		err = 0;
 	} else {
-		if (fail_avg >= 100)
+		if (fail_avg > LINK_FAIL_THRESH)
 			return MAX_METRIC;
 
 		sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
-- 
1.9.1

^ 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