* 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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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
* Re: [PATCH 1/2] mac80211: Update the driver with beacon info constantly
From: kbuild test robot @ 2017-02-15 20:41 UTC (permalink / raw)
To: Doru
Cc: kbuild-all, linux-wireless, andra.paraschiv7, costin.raiciu,
dragos.niculescu, Doru Gucea
In-Reply-To: <1487185278-8643-1-git-send-email-gucea.doru@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1533 bytes --]
Hi Doru,
[auto build test ERROR on mac80211-next/master]
[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/Doru/mac80211-Update-the-driver-with-beacon-info-constantly/20170216-034614
base: https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git master
config: x86_64-lkp (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 >>):
net/mac80211/mlme.c: In function 'ieee80211_rx_mgmt_beacon':
>> net/mac80211/mlme.c:3555:35: error: 'sata' undeclared (first use in this function)
ieee80211_bss_info_change_notify(sata, changed);
^~~~
net/mac80211/mlme.c:3555:35: note: each undeclared identifier is reported only once for each function it appears in
vim +/sata +3555 net/mac80211/mlme.c
3549 }
3550
3551 /* trigger hardware timers adjustment
3552 * this needs to be done before beacon filtering
3553 */
3554 changed |= BSS_CHANGED_BEACON_INFO;
> 3555 ieee80211_bss_info_change_notify(sata, changed);
3556
3557 if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
3558 return;
---
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: 24694 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] ath9k_htc: Adjust beacon timers for power save
From: kbuild test robot @ 2017-02-15 20:31 UTC (permalink / raw)
To: Doru
Cc: kbuild-all, linux-wireless, andra.paraschiv7, costin.raiciu,
dragos.niculescu, Doru Gucea
In-Reply-To: <1487185303-8700-1-git-send-email-gucea.doru@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1885 bytes --]
Hi Doru,
[auto build test ERROR on mac80211-next/master]
[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/Doru/mac80211-Update-the-driver-with-beacon-info-constantly/20170216-034614
base: https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git master
config: i386-randconfig-s1-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=i386
All errors (new ones prefixed by >>):
drivers/net/wireless/ath/ath9k/main.c: In function 'ath9k_bss_info_changed':
>> drivers/net/wireless/ath/ath9k/main.c:1774:3: error: implicit declaration of function 'ath9k_htc_beacon_config' [-Werror=implicit-function-declaration]
ath9k_htc_beacon_config(priv, vif);
^~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/wireless/ath/ath9k/main.c:1774:27: error: 'priv' undeclared (first use in this function)
ath9k_htc_beacon_config(priv, vif);
^~~~
drivers/net/wireless/ath/ath9k/main.c:1774:27: note: each undeclared identifier is reported only once for each function it appears in
cc1: some warnings being treated as errors
vim +/ath9k_htc_beacon_config +1774 drivers/net/wireless/ath/ath9k/main.c
1768
1769 ath9k_ps_wakeup(sc);
1770 mutex_lock(&sc->mutex);
1771
1772 /* adjust beacon timers */
1773 if (changed && BSS_CHANGED_BEACON_INFO)
> 1774 ath9k_htc_beacon_config(priv, vif);
1775
1776 if (changed & BSS_CHANGED_ASSOC) {
1777 ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
---
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: 28726 bytes --]
^ permalink raw reply
* Re: [RFC-PATCH] ath9k_htc: Adjust beacon timers for Power Save
From: Gucea Doru @ 2017-02-15 19:03 UTC (permalink / raw)
To: Kalle Valo
Cc: linux-wireless, ath9k_htc_fw, Andra Paraschiv, Costin Raiciu,
Dragos N
In-Reply-To: <87r32z968n.fsf@purkki.adurom.net>
On Wed, Feb 15, 2017 at 11:02 AM, Kalle Valo <kvalo@codeaurora.org> wrote:
> Doru <gucea.doru@gmail.com> writes:
>
>> From: Doru Gucea <gucea.doru@gmail.com>
>>
>> Each time we receive a beacon we need to adjust the hardware
>> timers for next DTIM and next TBTT.
>>
>> Before this commit, the Power Save behaviour was incorrect.
>> The scenario was:
>> - STA receives a beacon from AP with TIM unset;
>> - mac80211 layers puts the chip to sleep;
>> - chip is woken up by mac80211's software timer reponsible for
>> beacon miss after 7 * beacon_interval period.
>>
>> Normally the chip should sleep at most DTIM period. This commit
>> configures hardware timers for waking up the chip correctly.
>>
>> More details on the wiki:
>> https://github.com/doru91/linux-stable/wiki/Single-Interface-Power-Save
>>
>> Signed-off-by: Doru Gucea <gucea.doru@gmail.com>
>> ---
>> drivers/net/wireless/ath/ath9k/htc_drv_main.c | 4 ++++
>> net/mac80211/mlme.c | 6 ++++++
>> 2 files changed, 10 insertions(+)
>
> [...]
>
>> --- a/net/mac80211/mlme.c
>> +++ b/net/mac80211/mlme.c
>> @@ -3536,6 +3536,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
>> sdata->vif.bss_conf.sync_dtim_count = 0;
>> }
>>
>> + /* trigger hardware timers adjustment
>> + * this needs to be done before beacon filtering
>> + */
>> + changed |= BSS_CHANGED_BEACON_INFO;
>> + ieee80211_bss_info_change_notify(sdata, changed);
>
> You shouldn't mix driver and mac80211 changes in the same patch, I
> suspect Johannes didn't even notice this change because of that. Create
> a new patchset with two patches, one for ath9k and another for mac80211.
Thanks, I've just sent two patches as you suggested.
>
> --
> Kalle Valo
^ permalink raw reply
* [PATCH 2/2] ath9k_htc: Adjust beacon timers for power save
From: Doru @ 2017-02-15 19:01 UTC (permalink / raw)
To: linux-wireless, andra.paraschiv7, costin.raiciu, dragos.niculescu
Cc: Doru Gucea
From: Doru Gucea <gucea.doru@gmail.com>
Each time we receive a beacon we need to adjust the hardware
timers for next DTIM and next TBTT.
Before this commit, the Power Save behaviour was incorrect.
The scenario was:
- STA receives a beacon from AP with TIM unset;
- mac80211 layers puts the chip to sleep;
- chip is woken up by mac80211's software timer reponsible for
beacon miss after 7 * beacon_interval period.
Normally the chip should sleep at most DTIM period. This commit
configures hardware timers for waking up the chip correctly.
More details on the wiki:
https://github.com/doru91/linux-stable/wiki/Single-Interface-Power-Save
Signed-off-by: Doru Gucea <gucea.doru@gmail.com>
---
drivers/net/wireless/ath/ath9k/main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index c27143b..d2934e1 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1749,6 +1749,10 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex);
+ /* adjust beacon timers */
+ if (changed && BSS_CHANGED_BEACON_INFO)
+ ath9k_htc_beacon_config(priv, vif);
+
if (changed & BSS_CHANGED_ASSOC) {
ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
bss_conf->bssid, bss_conf->assoc);
--
1.9.1
^ permalink raw reply related
* [PATCH 1/2] mac80211: Update the driver with beacon info constantly
From: Doru @ 2017-02-15 19:01 UTC (permalink / raw)
To: linux-wireless, andra.paraschiv7, costin.raiciu, dragos.niculescu
Cc: Doru Gucea
From: Doru Gucea <gucea.doru@gmail.com>
Once the mac80211 layer receives a beacon, it should send a notification
to the driver. This will allow finer timining control in case of drivers
that need a correct estimation for the arrival time of a beacon.
Signed-off-by: Doru Gucea <gucea.doru@gmail.com>
---
net/mac80211/mlme.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index cd7e55e..0b8eed5 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3536,6 +3536,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.sync_dtim_count = 0;
}
+ /* trigger hardware timers adjustment
+ * this needs to be done before beacon filtering
+ */
+ changed |= BSS_CHANGED_BEACON_INFO;
+ ieee80211_bss_info_change_notify(sata, changed);
+
if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
return;
ifmgd->beacon_crc = ncrc;
--
1.9.1
^ permalink raw reply related
* Re: [PATCH] average: change to declare precision, not factor
From: David Miller @ 2017-02-15 17:54 UTC (permalink / raw)
To: johannes
Cc: linux-wireless, netdev, mst, jasowang, virtualization,
mareklindner, sw, a, sgruszka, johannes.berg
In-Reply-To: <20170215084926.29482-1-johannes@sipsolutions.net>
From: Johannes Berg <johannes@sipsolutions.net>
Date: Wed, 15 Feb 2017 09:49:26 +0100
> From: Johannes Berg <johannes.berg@intel.com>
>
> Declaring the factor is counter-intuitive, and people are prone
> to using small(-ish) values even when that makes no sense.
>
> Change the DECLARE_EWMA() macro to take the fractional precision,
> in bits, rather than a factor, and update all users.
>
> While at it, add some more documentation.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
> Unless I hear any objections, I will take this through my tree.
Acked-by: David S. Miller <davem@davemloft.net>
^ permalink raw reply
* Re: [PATCH] mac80211: allow overriding station bandwidth.
From: Johannes Berg @ 2017-02-15 16:05 UTC (permalink / raw)
To: Ben Greear, linux-wireless
In-Reply-To: <58A46F91.6090707@candelatech.com>
> Likely for some time remote third-party peers will not update with
> your patches to advertise the proper IEs, even if the local system
> does?
I think they ought to start doing that pretty soon.
> Either way, I suspect that 4x4 VHT80 may perform quite well vs 2x2
> VHT160 if there is any sort of interference on the secondary 80Mhz
> band...
True. Rate scaling should probably pick that over 160 MHz bandwidth, if
supported. But if, for example, VHT opmode notification restricts
current operation to 2x2, rate scaling should still pick 160 MHz.
> But, I can just remove the 'why' part of the description entirely if
> you prefer?
Yes, I just don't want to give people the wrong idea about this :)
johannes
^ permalink raw reply
* Re: [PATCH] mac80211: allow overriding station bandwidth.
From: Ben Greear @ 2017-02-15 15:11 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
In-Reply-To: <1487144841.4026.1.camel@sipsolutions.net>
On 02/14/2017 11:47 PM, Johannes Berg wrote:
> On Tue, 2017-02-14 at 13:01 -0800, greearb@candelatech.com wrote:
>> From: Ben Greear <greearb@candelatech.com>
>>
>> This allows one to disable VHT160 (or 80+80) on hardware
>> that might otherwise try to use it. One potential reason
>> to do this is that at least some 160Mhz/80+80 hardware can
>> only do 2x2 at 160Mhz, but can do 4x4 at 80Mhz. And, due to
>> driver and firmware issues, it may effectively be limitted
>> to 1x1 at 160Mhz for some NICs.
>
> I think the feature is acceptable and don't mind adding that (though
> perhaps we should start thinking about making some of these things
> debug-only features), but I think the description of why you might want
> to do this is misleading - those issues you're describing really should
> be solved differently, and I posted the basis for that yesterday.
Likely for some time remote third-party peers will not update with your patches
to advertise the proper IEs, even if the local system does?
Either way, I suspect that 4x4 VHT80 may perform quite well vs 2x2 VHT160 if
there is any sort of interference on the secondary 80Mhz band...
But, I can just remove the 'why' part of the description entirely if you prefer?
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox