The patch that would first try the board-specific firmware
had a bug because the fallback would not be called: the
asynchronous interface is used meaning request_firmware_nowait()
returns 0 immediately.
Harden the firmware loading like this:
- If we cannot build an alt_path (like if no board_type is
specified) just request the first firmware without any
suffix, like in the past.
- If the lookup of a board specific firmware fails, we get
a NULL fw in the async callback, so just try again without
the alt_path. Use a context state variable to check that
we do not try this indefinitely.
- Rename the brcm_fw_request_done to brcm_fw_request_done_first
reflecting the fact that this callback is only used for the
first (main) firmware file, and drop the unnecessary
prototype.
Fixes: 5ff013914c62 ("brcmfmac: firmware: Allow per-board firmware binaries")
Cc: Dmitry Osipenko <digetx@gmail.com>
Cc: Stefan Hansson <redacted>
Tested-by: Dmitry Osipenko <digetx@gmail.com>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Linus Walleij <redacted>
---
ChangeLog v2->v3:
- Rename state variable to "tried_board_variant".
ChangeLog v1->v2:
- Instead of using a static variable, add a context variable
"tested_board_variant"
- Collect Arend's review tag.
- Collect Tested-by from Dmitry.
---
.../broadcom/brcm80211/brcmfmac/firmware.c | 31 +++++++++++++------
1 file changed, 22 insertions(+), 9 deletions(-)
@@ -428,11 +428,10 @@ struct brcmf_fw {structdevice*dev;structbrcmf_fw_request*req;u32curpos;+booltried_board_variant;void(*done)(structdevice*dev,interr,structbrcmf_fw_request*req);};-staticvoidbrcmf_fw_request_done(conststructfirmware*fw,void*ctx);-#ifdef CONFIG_EFI/* In some cases the EFI-var stored nvram contains "ccode=ALL" or "ccode=XV"*tospecify"worldwide"compatiblesettings,butthese2ccode-sdonotwork
@@ -638,11 +637,25 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,returnrequest_firmware(fw,cur->path,fwctx->dev);}-staticvoidbrcmf_fw_request_done(conststructfirmware*fw,void*ctx)+staticvoidbrcmf_fw_request_done_first(conststructfirmware*fw,void*ctx){structbrcmf_fw*fwctx=ctx;+structbrcmf_fw_item*first=&fwctx->req->items[0];intret;+/* Something failed with the first firmware request, such as not+*gettingtheper-boardfirmware.Retrythis,nowusingtheless+*specificpathforthefirstfirmwareitem,i.e.withouttheboard+*suffix.+*/+if(!fw&&!fwctx->tried_board_variant){+fwctx->tried_board_variant=true;+ret=request_firmware_nowait(THIS_MODULE,true,first->path,+fwctx->dev,GFP_KERNEL,fwctx,+brcmf_fw_request_done_first);+return;+}+ret=brcmf_fw_complete_request(fw,fwctx);while(ret==0&&++fwctx->curpos<fwctx->req->n_items){
@@ -700,19 +713,19 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,/* First try alternative board-specific path if any */alt_path=brcm_alt_fw_path(first->path,fwctx->req->board_type);if(alt_path){+fwctx->tried_board_variant=false;ret=request_firmware_nowait(THIS_MODULE,true,alt_path,fwctx->dev,GFP_KERNEL,fwctx,-brcmf_fw_request_done);+brcmf_fw_request_done_first);kfree(alt_path);-}-/* Else try canonical path */-if(ret){+}else{+fwctx->tried_board_variant=true;ret=request_firmware_nowait(THIS_MODULE,true,first->path,fwctx->dev,GFP_KERNEL,fwctx,-brcmf_fw_request_done);+brcmf_fw_request_done_first);}if(ret<0)-brcmf_fw_request_done(NULL,fwctx);+brcmf_fw_request_done_first(NULL,fwctx);return0;}
The patch that would first try the board-specific firmware
had a bug because the fallback would not be called: the
asynchronous interface is used meaning request_firmware_nowait()
returns 0 immediately.
Harden the firmware loading like this:
- If we cannot build an alt_path (like if no board_type is
specified) just request the first firmware without any
suffix, like in the past.
- If the lookup of a board specific firmware fails, we get
a NULL fw in the async callback, so just try again without
the alt_path. Use a context state variable to check that
we do not try this indefinitely.
- Rename the brcm_fw_request_done to brcm_fw_request_done_first
reflecting the fact that this callback is only used for the
first (main) firmware file, and drop the unnecessary
prototype.
Fixes: 5ff013914c62 ("brcmfmac: firmware: Allow per-board firmware binaries")
Cc: Dmitry Osipenko <digetx@gmail.com>
Cc: Stefan Hansson <redacted>
Tested-by: Dmitry Osipenko <digetx@gmail.com>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Linus Walleij <redacted>
---
ChangeLog v2->v3:
- Rename state variable to "tried_board_variant".
ChangeLog v1->v2:
- Instead of using a static variable, add a context variable
"tested_board_variant"
- Collect Arend's review tag.
- Collect Tested-by from Dmitry.
---
Combining my previous comments together, I rewrote it like this:
@@ -431,8 +431,6 @@ struct brcmf_fw {void(*done)(structdevice*dev,interr,structbrcmf_fw_request*req);};-staticvoidbrcmf_fw_request_done(conststructfirmware*fw,void*ctx);-#ifdef CONFIG_EFI/* In some cases the EFI-var stored nvram contains "ccode=ALL" or "ccode=XV"*tospecify"worldwide"compatiblesettings,butthese2ccode-sdonotwork
From: Arend van Spriel <hidden> Date: 2021-08-05 11:35:17
On Thu, Aug 5, 2021 at 11:32 AM Linus Walleij [off-list ref] wrote:
The patch that would first try the board-specific firmware
had a bug because the fallback would not be called: the
asynchronous interface is used meaning request_firmware_nowait()
returns 0 immediately.
Harden the firmware loading like this:
- If we cannot build an alt_path (like if no board_type is
specified) just request the first firmware without any
suffix, like in the past.
- If the lookup of a board specific firmware fails, we get
a NULL fw in the async callback, so just try again without
the alt_path. Use a context state variable to check that
we do not try this indefinitely.
- Rename the brcm_fw_request_done to brcm_fw_request_done_first
reflecting the fact that this callback is only used for the
first (main) firmware file, and drop the unnecessary
prototype.
While implementing the firmware.c module at first I was doing every
firmware request with the 'nowait' variant hence the callback was used
repeatedly. However, I abandoned that as the reason for async request
was to avoid delay it may cause on kernel boot. Decoupling the initial
firmware request was sufficient for that and simplified things quite a
bit. As to the naming maybe 'brcmf_fw_async_request_done()' is a clear
alternative.
quoted hunk
Fixes: 5ff013914c62 ("brcmfmac: firmware: Allow per-board firmware binaries")
Cc: Dmitry Osipenko <digetx@gmail.com>
Cc: Stefan Hansson <redacted>
Tested-by: Dmitry Osipenko <digetx@gmail.com>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Linus Walleij <redacted>
---
ChangeLog v2->v3:
- Rename state variable to "tried_board_variant".
ChangeLog v1->v2:
- Instead of using a static variable, add a context variable
"tested_board_variant"
- Collect Arend's review tag.
- Collect Tested-by from Dmitry.
---
.../broadcom/brcm80211/brcmfmac/firmware.c | 31 +++++++++++++------
1 file changed, 22 insertions(+), 9 deletions(-)
@@ -428,11 +428,10 @@ struct brcmf_fw {structdevice*dev;structbrcmf_fw_request*req;u32curpos;+booltried_board_variant;void(*done)(structdevice*dev,interr,structbrcmf_fw_request*req);};-staticvoidbrcmf_fw_request_done(conststructfirmware*fw,void*ctx);-#ifdef CONFIG_EFI/* In some cases the EFI-var stored nvram contains "ccode=ALL" or "ccode=XV"*tospecify"worldwide"compatiblesettings,butthese2ccode-sdonotwork
@@ -638,11 +637,25 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,returnrequest_firmware(fw,cur->path,fwctx->dev);}-staticvoidbrcmf_fw_request_done(conststructfirmware*fw,void*ctx)+staticvoidbrcmf_fw_request_done_first(conststructfirmware*fw,void*ctx){structbrcmf_fw*fwctx=ctx;+structbrcmf_fw_item*first=&fwctx->req->items[0];intret;+/* Something failed with the first firmware request, such as not+*gettingtheper-boardfirmware.Retrythis,nowusingtheless+*specificpathforthefirstfirmwareitem,i.e.withouttheboard+*suffix.+*/+if(!fw&&!fwctx->tried_board_variant){+fwctx->tried_board_variant=true;+ret=request_firmware_nowait(THIS_MODULE,true,first->path,+fwctx->dev,GFP_KERNEL,fwctx,+brcmf_fw_request_done_first);+return;+}+
So here we could use the synchronous variant instead for the reason
explained earlier.
Regards,
Arend
On Thu, Aug 5, 2021 at 11:32 AM Linus Walleij [off-list ref] wrote:
quoted
The patch that would first try the board-specific firmware
had a bug because the fallback would not be called: the
asynchronous interface is used meaning request_firmware_nowait()
returns 0 immediately.
Harden the firmware loading like this:
- If we cannot build an alt_path (like if no board_type is
specified) just request the first firmware without any
suffix, like in the past.
- If the lookup of a board specific firmware fails, we get
a NULL fw in the async callback, so just try again without
the alt_path. Use a context state variable to check that
we do not try this indefinitely.
- Rename the brcm_fw_request_done to brcm_fw_request_done_first
reflecting the fact that this callback is only used for the
first (main) firmware file, and drop the unnecessary
prototype.
While implementing the firmware.c module at first I was doing every
firmware request with the 'nowait' variant hence the callback was used
repeatedly. However, I abandoned that as the reason for async request
was to avoid delay it may cause on kernel boot. Decoupling the initial
firmware request was sufficient for that and simplified things quite a
bit. As to the naming maybe 'brcmf_fw_async_request_done()' is a clear
alternative.
quoted
Fixes: 5ff013914c62 ("brcmfmac: firmware: Allow per-board firmware binaries")
Cc: Dmitry Osipenko <digetx@gmail.com>
Cc: Stefan Hansson <redacted>
Tested-by: Dmitry Osipenko <digetx@gmail.com>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Linus Walleij <redacted>
---
ChangeLog v2->v3:
- Rename state variable to "tried_board_variant".
ChangeLog v1->v2:
- Instead of using a static variable, add a context variable
"tested_board_variant"
- Collect Arend's review tag.
- Collect Tested-by from Dmitry.
---
.../broadcom/brcm80211/brcmfmac/firmware.c | 31 +++++++++++++------
1 file changed, 22 insertions(+), 9 deletions(-)
@@ -428,11 +428,10 @@ struct brcmf_fw {structdevice*dev;structbrcmf_fw_request*req;u32curpos;+booltried_board_variant;void(*done)(structdevice*dev,interr,structbrcmf_fw_request*req);};-staticvoidbrcmf_fw_request_done(conststructfirmware*fw,void*ctx);-#ifdef CONFIG_EFI/* In some cases the EFI-var stored nvram contains "ccode=ALL" or "ccode=XV"*tospecify"worldwide"compatiblesettings,butthese2ccode-sdonotwork
@@ -638,11 +637,25 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,returnrequest_firmware(fw,cur->path,fwctx->dev);}-staticvoidbrcmf_fw_request_done(conststructfirmware*fw,void*ctx)+staticvoidbrcmf_fw_request_done_first(conststructfirmware*fw,void*ctx){structbrcmf_fw*fwctx=ctx;+structbrcmf_fw_item*first=&fwctx->req->items[0];intret;+/* Something failed with the first firmware request, such as not+*gettingtheper-boardfirmware.Retrythis,nowusingtheless+*specificpathforthefirstfirmwareitem,i.e.withouttheboard+*suffix.+*/+if(!fw&&!fwctx->tried_board_variant){+fwctx->tried_board_variant=true;+ret=request_firmware_nowait(THIS_MODULE,true,first->path,+fwctx->dev,GFP_KERNEL,fwctx,+brcmf_fw_request_done_first);+return;+}+
So here we could use the synchronous variant instead for the reason
explained earlier.
The blocking variant doesn't work as-is, it locks up the probe.
On Thu, Aug 5, 2021 at 12:31 PM Dmitry Osipenko [off-list ref] wrote:
Combining my previous comments together, I rewrote it like this:
I like this, can you fold in your patch on top of mine, add your
Signed-off-by at the end and resend to the list?
That way we get a clean record of the delivery path and also the
patch looks like you want it :)
You can perhaps tag on v4 on the [PATCH] as well so it's clear
for Kalle to apply this version. (Hoping Arnd will be fine with it as
well.)
Yours,
Linus Walleij
On Thu, Aug 5, 2021 at 12:31 PM Dmitry Osipenko [off-list ref] wrote:
quoted
Combining my previous comments together, I rewrote it like this:
I like this, can you fold in your patch on top of mine, add your
Signed-off-by at the end and resend to the list?
That way we get a clean record of the delivery path and also the
patch looks like you want it :)
You can perhaps tag on v4 on the [PATCH] as well so it's clear
for Kalle to apply this version. (Hoping Arnd will be fine with it as
well.)