On 2022/01/02 16:08, Dmitry Osipenko wrote: > 26.12.2021 18:35, Hector Martin пишет: >> +static void brcm_free_alt_fw_paths(const char **alt_paths) >> +{ >> + int i; >> + >> + if (!alt_paths) >> + return; >> + >> + for (i = 0; alt_paths[i]; i++) >> + kfree(alt_paths[i]); >> + >> + kfree(alt_paths); >> } >> >> static int brcmf_fw_request_firmware(const struct firmware **fw, >> struct brcmf_fw *fwctx) >> { >> struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos]; >> - int ret; >> + int ret, i; >> >> /* Files can be board-specific, first try a board-specific path */ >> if (cur->type == BRCMF_FW_TYPE_NVRAM && fwctx->req->board_type) { >> - char *alt_path; >> + const char **alt_paths = brcm_alt_fw_paths(cur->path, fwctx); >> >> - alt_path = brcm_alt_fw_path(cur->path, fwctx->req->board_type); >> - if (!alt_path) >> + if (!alt_paths) >> goto fallback; >> >> - ret = request_firmware(fw, alt_path, fwctx->dev); >> - kfree(alt_path); >> - if (ret == 0) >> - return ret; >> + for (i = 0; alt_paths[i]; i++) { >> + ret = firmware_request_nowarn(fw, alt_paths[i], fwctx->dev); >> + if (ret == 0) { >> + brcm_free_alt_fw_paths(alt_paths); >> + return ret; >> + } >> + } >> + brcm_free_alt_fw_paths(alt_paths); >> } >> >> fallback: >> @@ -641,6 +663,9 @@ static void brcmf_fw_request_done(const struct firmware *fw, void *ctx) >> struct brcmf_fw *fwctx = ctx; >> int ret; >> >> + brcm_free_alt_fw_paths(fwctx->alt_paths); >> + fwctx->alt_paths = NULL; > > It looks suspicious that fwctx->alt_paths isn't zero'ed by other code > paths. The brcm_free_alt_fw_paths() should take fwctx for the argument > and fwctx->alt_paths should be set to NULL there. There are multiple code paths for alt_paths; the initial firmware lookup uses fwctx->alt_paths, and once we know the firmware load succeeded we use blocking firmware requests for NVRAM/CLM/etc and those do not use the fwctx member, but rather just keep alt_paths in function scope (brcmf_fw_request_firmware). You're right that there was a rebase SNAFU there though, I'll compile test each patch before sending v2. Sorry about that. In this series the code should build again by patch #6. Are you thinking of any particular code paths? As far as I saw when writing this, brcmf_fw_request_done() should always get called whether things succeed or fail. There are no other code paths that free fwctx->alt_paths. > On the other hand, I'd change the **alt_paths to a fixed-size array. > This should simplify the code, making it easier to follow and maintain. > > - const char **alt_paths; > + char *alt_paths[BRCM_MAX_ALT_FW_PATHS]; > > Then you also won't need to NULL-terminate the array, which is a common > source of bugs in kernel. That sounds reasonable, it'll certainly make the code simpler. I'll do that for v2. -- Hector Martin (marcan@xxxxxxxxx) Public Key: https://mrcn.st/pub