diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index 0497b721136a..7570dbf22cdd 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -427,6 +427,8 @@ void brcmf_fw_nvram_free(void *nvram)
 struct brcmf_fw {
 	struct device *dev;
 	struct brcmf_fw_request *req;
+	const char *alt_paths[BRCMF_FW_MAX_ALT_PATHS];
+	int alt_index;
 	u32 curpos;
 	void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
 };
@@ -592,14 +594,18 @@ static int brcmf_fw_complete_request(const struct firmware *fw,
 	return (cur->flags & BRCMF_FW_REQF_OPTIONAL) ? 0 : ret;
 }
 
-static char *brcm_alt_fw_path(const char *path, const char *board_type)
+static int brcm_alt_fw_paths(const char *path, const char *board_type,
+			     const char *alt_paths[BRCMF_FW_MAX_ALT_PATHS])
 {
 	char alt_path[BRCMF_FW_NAME_LEN];
 	const char *suffix;
 
+	memset(alt_paths, 0, array_size(sizeof(*alt_paths),
+					BRCMF_FW_MAX_ALT_PATHS));
+
 	suffix = strrchr(path, '.');
 	if (!suffix || suffix == path)
-		return NULL;
+		return -EINVAL;
 
 	/* strip extension at the end */
 	strscpy(alt_path, path, BRCMF_FW_NAME_LEN);
@@ -609,7 +615,18 @@ static char *brcm_alt_fw_path(const char *path, const char *board_type)
 	strlcat(alt_path, board_type, BRCMF_FW_NAME_LEN);
 	strlcat(alt_path, suffix, BRCMF_FW_NAME_LEN);
 
-	return kstrdup(alt_path, GFP_KERNEL);
+	alt_paths[0] = kstrdup(alt_path, GFP_KERNEL);
+
+	return 0;
+}
+
+static void
+brcm_free_alt_fw_paths(const char *alt_paths[BRCMF_FW_MAX_ALT_PATHS])
+{
+	unsigned int i;
+
+	for (i = 0; alt_paths[i]; i++)
+		kfree(alt_paths[i]);
 }
 
 static int brcmf_fw_request_firmware(const struct firmware **fw,
@@ -617,19 +634,25 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,
 {
 	struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos];
 	int ret;
+	unsigned int i;
 
 	/* Files can be board-specific, first try a board-specific path */
 	if (fwctx->req->board_type) {
-		char *alt_path;
+		const char *alt_paths[BRCMF_FW_MAX_ALT_PATHS];
 
-		alt_path = brcm_alt_fw_path(cur->path, fwctx->req->board_type);
-		if (!alt_path)
+		if (brcm_alt_fw_paths(cur->path, fwctx->req->board_type,
+				      alt_paths) != 0)
 			goto fallback;
 
-		ret = request_firmware(fw, alt_path, fwctx->dev);
-		kfree(alt_path);
-		if (ret == 0)
-			return ret;
+		for (i = 0; i < BRCMF_FW_MAX_ALT_PATHS && 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 +664,8 @@ 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);
+
 	ret = brcmf_fw_complete_request(fw, fwctx);
 
 	while (ret == 0 && ++fwctx->curpos < fwctx->req->n_items) {
@@ -662,13 +687,27 @@ static void brcmf_fw_request_done_alt_path(const struct firmware *fw, void *ctx)
 	struct brcmf_fw_item *first = &fwctx->req->items[0];
 	int ret = 0;
 
-	/* Fall back to canonical path if board firmware not found */
-	if (!fw)
+	if (fw) {
+		brcmf_fw_request_done(fw, ctx);
+		return;
+	}
+
+	fwctx->alt_index++;
+	if (fwctx->alt_index < BRCMF_FW_MAX_ALT_PATHS &&
+	    fwctx->alt_paths[fwctx->alt_index]) {
+		/* Try the next alt firmware */
+		ret = request_firmware_nowait(THIS_MODULE, true,
+					      fwctx->alt_paths[fwctx->alt_index],
+					      fwctx->dev, GFP_KERNEL, fwctx,
+					      brcmf_fw_request_done_alt_path);
+	} else {
+		/* Fall back to canonical path if board firmware not found */
 		ret = request_firmware_nowait(THIS_MODULE, true, first->path,
 					      fwctx->dev, GFP_KERNEL, fwctx,
 					      brcmf_fw_request_done);
+	}
 
-	if (fw || ret < 0)
+	if (ret < 0)
 		brcmf_fw_request_done(fw, ctx);
 }
 
@@ -693,7 +732,6 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
 {
 	struct brcmf_fw_item *first = &req->items[0];
 	struct brcmf_fw *fwctx;
-	char *alt_path;
 	int ret;
 
 	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
@@ -712,12 +750,13 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
 	fwctx->done = fw_cb;
 
 	/* First try alternative board-specific path if any */
-	alt_path = brcm_alt_fw_path(first->path, fwctx->req->board_type);
-	if (alt_path) {
-		ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
+	if (brcm_alt_fw_paths(first->path, req->board_type,
+			      fwctx->alt_paths) == 0) {
+		fwctx->alt_index = 0;
+		ret = request_firmware_nowait(THIS_MODULE, true,
+					      fwctx->alt_paths[0],
 					      fwctx->dev, GFP_KERNEL, fwctx,
 					      brcmf_fw_request_done_alt_path);
-		kfree(alt_path);
 	} else {
 		ret = request_firmware_nowait(THIS_MODULE, true, first->path,
 					      fwctx->dev, GFP_KERNEL, fwctx,
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
index e290dec9c53d..7f4e6e359c82 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
@@ -11,6 +11,8 @@
 
 #define BRCMF_FW_DEFAULT_PATH		"brcm/"
 
+#define BRCMF_FW_MAX_ALT_PATHS	8
+
 /**
  * struct brcmf_firmware_mapping - Used to map chipid/revmask to firmware
  *	filename and nvram filename. Each bus type implementation should create
