mac80211: backport brcmfmac firmware & clm_blob loading rework
It backports remaining brcmfmac changes from 4.17. Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
This commit is contained in:
		
							parent
							
								
									f5bce268b0
								
							
						
					
					
						commit
						7e8eb7f309
					
				@ -0,0 +1,574 @@
 | 
			
		||||
From d09ae51a4b676151edaf572bcd5f272b5532639f Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Date: Thu, 22 Mar 2018 21:28:26 +0100
 | 
			
		||||
Subject: [PATCH] brcmfmac: pass struct in brcmf_fw_get_firmwares()
 | 
			
		||||
 | 
			
		||||
Make the function brcmf_fw_get_firmwares() a bit more easy to extend
 | 
			
		||||
using a structure to pass the request parameters.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
 | 
			
		||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
 | 
			
		||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
 | 
			
		||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 | 
			
		||||
---
 | 
			
		||||
 .../broadcom/brcm80211/brcmfmac/firmware.c         | 175 ++++++++++++++-------
 | 
			
		||||
 .../broadcom/brcm80211/brcmfmac/firmware.h         |  43 +++--
 | 
			
		||||
 .../wireless/broadcom/brcm80211/brcmfmac/pcie.c    |  38 ++++-
 | 
			
		||||
 .../wireless/broadcom/brcm80211/brcmfmac/sdio.c    |  32 +++-
 | 
			
		||||
 .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c |  43 ++++-
 | 
			
		||||
 5 files changed, 245 insertions(+), 86 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
@@ -438,18 +438,31 @@ void brcmf_fw_nvram_free(void *nvram)
 | 
			
		||||
 
 | 
			
		||||
 struct brcmf_fw {
 | 
			
		||||
 	struct device *dev;
 | 
			
		||||
-	u16 flags;
 | 
			
		||||
-	const struct firmware *code;
 | 
			
		||||
-	const char *nvram_name;
 | 
			
		||||
-	u16 domain_nr;
 | 
			
		||||
-	u16 bus_nr;
 | 
			
		||||
-	void (*done)(struct device *dev, int err, const struct firmware *fw,
 | 
			
		||||
-		     void *nvram_image, u32 nvram_len);
 | 
			
		||||
+	struct brcmf_fw_request *req;
 | 
			
		||||
+	u32 curpos;
 | 
			
		||||
+	void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
 | 
			
		||||
+
 | 
			
		||||
+static void brcmf_fw_free_request(struct brcmf_fw_request *req)
 | 
			
		||||
+{
 | 
			
		||||
+	struct brcmf_fw_item *item;
 | 
			
		||||
+	int i;
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
 | 
			
		||||
+		if (item->type == BRCMF_FW_TYPE_BINARY)
 | 
			
		||||
+			release_firmware(item->binary);
 | 
			
		||||
+		else if (item->type == BRCMF_FW_TYPE_NVRAM)
 | 
			
		||||
+			brcmf_fw_nvram_free(item->nv_data.data);
 | 
			
		||||
+	}
 | 
			
		||||
+	kfree(req);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
 | 
			
		||||
 {
 | 
			
		||||
 	struct brcmf_fw *fwctx = ctx;
 | 
			
		||||
+	struct brcmf_fw_item *cur;
 | 
			
		||||
 	u32 nvram_length = 0;
 | 
			
		||||
 	void *nvram = NULL;
 | 
			
		||||
 	u8 *data = NULL;
 | 
			
		||||
@@ -457,83 +470,150 @@ static void brcmf_fw_request_nvram_done(
 | 
			
		||||
 	bool raw_nvram;
 | 
			
		||||
 
 | 
			
		||||
 	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
 | 
			
		||||
+
 | 
			
		||||
+	cur = &fwctx->req->items[fwctx->curpos];
 | 
			
		||||
+
 | 
			
		||||
 	if (fw && fw->data) {
 | 
			
		||||
 		data = (u8 *)fw->data;
 | 
			
		||||
 		data_len = fw->size;
 | 
			
		||||
 		raw_nvram = false;
 | 
			
		||||
 	} else {
 | 
			
		||||
 		data = bcm47xx_nvram_get_contents(&data_len);
 | 
			
		||||
-		if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
 | 
			
		||||
+		if (!data && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
 | 
			
		||||
 			goto fail;
 | 
			
		||||
 		raw_nvram = true;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	if (data)
 | 
			
		||||
 		nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
 | 
			
		||||
-					     fwctx->domain_nr, fwctx->bus_nr);
 | 
			
		||||
+					     fwctx->req->domain_nr,
 | 
			
		||||
+					     fwctx->req->bus_nr);
 | 
			
		||||
 
 | 
			
		||||
 	if (raw_nvram)
 | 
			
		||||
 		bcm47xx_nvram_release_contents(data);
 | 
			
		||||
 	release_firmware(fw);
 | 
			
		||||
-	if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
 | 
			
		||||
+	if (!nvram && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
 | 
			
		||||
 		goto fail;
 | 
			
		||||
 
 | 
			
		||||
-	fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length);
 | 
			
		||||
-	kfree(fwctx);
 | 
			
		||||
+	brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length);
 | 
			
		||||
+	cur->nv_data.data = nvram;
 | 
			
		||||
+	cur->nv_data.len = nvram_length;
 | 
			
		||||
 	return;
 | 
			
		||||
 
 | 
			
		||||
 fail:
 | 
			
		||||
 	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
 | 
			
		||||
-	release_firmware(fwctx->code);
 | 
			
		||||
-	fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0);
 | 
			
		||||
+	fwctx->done(fwctx->dev, -ENOENT, NULL);
 | 
			
		||||
+	brcmf_fw_free_request(fwctx->req);
 | 
			
		||||
 	kfree(fwctx);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
 | 
			
		||||
+static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async)
 | 
			
		||||
+{
 | 
			
		||||
+	struct brcmf_fw_item *cur;
 | 
			
		||||
+	const struct firmware *fw = NULL;
 | 
			
		||||
+	int ret;
 | 
			
		||||
+
 | 
			
		||||
+	cur = &fwctx->req->items[fwctx->curpos];
 | 
			
		||||
+
 | 
			
		||||
+	brcmf_dbg(TRACE, "%srequest for %s\n", async ? "async " : "",
 | 
			
		||||
+		  cur->path);
 | 
			
		||||
+
 | 
			
		||||
+	if (async)
 | 
			
		||||
+		ret = request_firmware_nowait(THIS_MODULE, true, cur->path,
 | 
			
		||||
+					      fwctx->dev, GFP_KERNEL, fwctx,
 | 
			
		||||
+					      brcmf_fw_request_done);
 | 
			
		||||
+	else
 | 
			
		||||
+		ret = request_firmware(&fw, cur->path, fwctx->dev);
 | 
			
		||||
+
 | 
			
		||||
+	if (ret < 0) {
 | 
			
		||||
+		brcmf_fw_request_done(NULL, fwctx);
 | 
			
		||||
+	} else if (!async && fw) {
 | 
			
		||||
+		brcmf_dbg(TRACE, "firmware %s %sfound\n", cur->path,
 | 
			
		||||
+			  fw ? "" : "not ");
 | 
			
		||||
+		if (cur->type == BRCMF_FW_TYPE_BINARY)
 | 
			
		||||
+			cur->binary = fw;
 | 
			
		||||
+		else if (cur->type == BRCMF_FW_TYPE_NVRAM)
 | 
			
		||||
+			brcmf_fw_request_nvram_done(fw, fwctx);
 | 
			
		||||
+		else
 | 
			
		||||
+			release_firmware(fw);
 | 
			
		||||
+
 | 
			
		||||
+		return -EAGAIN;
 | 
			
		||||
+	}
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void brcmf_fw_request_done(const struct firmware *fw, void *ctx)
 | 
			
		||||
 {
 | 
			
		||||
 	struct brcmf_fw *fwctx = ctx;
 | 
			
		||||
+	struct brcmf_fw_item *cur;
 | 
			
		||||
 	int ret = 0;
 | 
			
		||||
 
 | 
			
		||||
-	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
 | 
			
		||||
-	if (!fw) {
 | 
			
		||||
+	cur = &fwctx->req->items[fwctx->curpos];
 | 
			
		||||
+
 | 
			
		||||
+	brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path,
 | 
			
		||||
+		  fw ? "" : "not ");
 | 
			
		||||
+
 | 
			
		||||
+	if (fw) {
 | 
			
		||||
+		if (cur->type == BRCMF_FW_TYPE_BINARY)
 | 
			
		||||
+			cur->binary = fw;
 | 
			
		||||
+		else if (cur->type == BRCMF_FW_TYPE_NVRAM)
 | 
			
		||||
+			brcmf_fw_request_nvram_done(fw, fwctx);
 | 
			
		||||
+		else
 | 
			
		||||
+			release_firmware(fw);
 | 
			
		||||
+	} else if (cur->type == BRCMF_FW_TYPE_NVRAM) {
 | 
			
		||||
+		brcmf_fw_request_nvram_done(NULL, fwctx);
 | 
			
		||||
+	} else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) {
 | 
			
		||||
 		ret = -ENOENT;
 | 
			
		||||
 		goto fail;
 | 
			
		||||
 	}
 | 
			
		||||
-	/* only requested code so done here */
 | 
			
		||||
-	if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM))
 | 
			
		||||
-		goto done;
 | 
			
		||||
-
 | 
			
		||||
-	fwctx->code = fw;
 | 
			
		||||
-	ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
 | 
			
		||||
-				      fwctx->dev, GFP_KERNEL, fwctx,
 | 
			
		||||
-				      brcmf_fw_request_nvram_done);
 | 
			
		||||
 
 | 
			
		||||
-	/* pass NULL to nvram callback for bcm47xx fallback */
 | 
			
		||||
-	if (ret)
 | 
			
		||||
-		brcmf_fw_request_nvram_done(NULL, fwctx);
 | 
			
		||||
+	do {
 | 
			
		||||
+		if (++fwctx->curpos == fwctx->req->n_items) {
 | 
			
		||||
+			ret = 0;
 | 
			
		||||
+			goto done;
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+		ret = brcmf_fw_request_next_item(fwctx, false);
 | 
			
		||||
+	} while (ret == -EAGAIN);
 | 
			
		||||
+
 | 
			
		||||
 	return;
 | 
			
		||||
 
 | 
			
		||||
 fail:
 | 
			
		||||
-	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
 | 
			
		||||
+	brcmf_dbg(TRACE, "failed err=%d: dev=%s, fw=%s\n", ret,
 | 
			
		||||
+		  dev_name(fwctx->dev), cur->path);
 | 
			
		||||
+	brcmf_fw_free_request(fwctx->req);
 | 
			
		||||
+	fwctx->req = NULL;
 | 
			
		||||
 done:
 | 
			
		||||
-	fwctx->done(fwctx->dev, ret, fw, NULL, 0);
 | 
			
		||||
+	fwctx->done(fwctx->dev, ret, fwctx->req);
 | 
			
		||||
 	kfree(fwctx);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
 | 
			
		||||
-				const char *code, const char *nvram,
 | 
			
		||||
-				void (*fw_cb)(struct device *dev, int err,
 | 
			
		||||
-					      const struct firmware *fw,
 | 
			
		||||
-					      void *nvram_image, u32 nvram_len),
 | 
			
		||||
-				u16 domain_nr, u16 bus_nr)
 | 
			
		||||
+static bool brcmf_fw_request_is_valid(struct brcmf_fw_request *req)
 | 
			
		||||
+{
 | 
			
		||||
+	struct brcmf_fw_item *item;
 | 
			
		||||
+	int i;
 | 
			
		||||
+
 | 
			
		||||
+	if (!req->n_items)
 | 
			
		||||
+		return false;
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
 | 
			
		||||
+		if (!item->path)
 | 
			
		||||
+			return false;
 | 
			
		||||
+	}
 | 
			
		||||
+	return true;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
 | 
			
		||||
+			   void (*fw_cb)(struct device *dev, int err,
 | 
			
		||||
+					 struct brcmf_fw_request *req))
 | 
			
		||||
 {
 | 
			
		||||
 	struct brcmf_fw *fwctx;
 | 
			
		||||
 
 | 
			
		||||
 	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
 | 
			
		||||
-	if (!fw_cb || !code)
 | 
			
		||||
+	if (!fw_cb)
 | 
			
		||||
 		return -EINVAL;
 | 
			
		||||
 
 | 
			
		||||
-	if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram)
 | 
			
		||||
+	if (!brcmf_fw_request_is_valid(req))
 | 
			
		||||
 		return -EINVAL;
 | 
			
		||||
 
 | 
			
		||||
 	fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL);
 | 
			
		||||
@@ -541,26 +621,11 @@ int brcmf_fw_get_firmwares_pcie(struct d
 | 
			
		||||
 		return -ENOMEM;
 | 
			
		||||
 
 | 
			
		||||
 	fwctx->dev = dev;
 | 
			
		||||
-	fwctx->flags = flags;
 | 
			
		||||
+	fwctx->req = req;
 | 
			
		||||
 	fwctx->done = fw_cb;
 | 
			
		||||
-	if (flags & BRCMF_FW_REQUEST_NVRAM)
 | 
			
		||||
-		fwctx->nvram_name = nvram;
 | 
			
		||||
-	fwctx->domain_nr = domain_nr;
 | 
			
		||||
-	fwctx->bus_nr = bus_nr;
 | 
			
		||||
-
 | 
			
		||||
-	return request_firmware_nowait(THIS_MODULE, true, code, dev,
 | 
			
		||||
-				       GFP_KERNEL, fwctx,
 | 
			
		||||
-				       brcmf_fw_request_code_done);
 | 
			
		||||
-}
 | 
			
		||||
 
 | 
			
		||||
-int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
 | 
			
		||||
-			   const char *code, const char *nvram,
 | 
			
		||||
-			   void (*fw_cb)(struct device *dev, int err,
 | 
			
		||||
-					 const struct firmware *fw,
 | 
			
		||||
-					 void *nvram_image, u32 nvram_len))
 | 
			
		||||
-{
 | 
			
		||||
-	return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0,
 | 
			
		||||
-					   0);
 | 
			
		||||
+	brcmf_fw_request_next_item(fwctx, true);
 | 
			
		||||
+	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void brcmf_fw_get_full_name(char fw_name[BRCMF_FW_NAME_LEN],
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
 | 
			
		||||
@@ -16,10 +16,7 @@
 | 
			
		||||
 #ifndef BRCMFMAC_FIRMWARE_H
 | 
			
		||||
 #define BRCMFMAC_FIRMWARE_H
 | 
			
		||||
 
 | 
			
		||||
-#define BRCMF_FW_REQUEST		0x000F
 | 
			
		||||
-#define  BRCMF_FW_REQUEST_NVRAM		0x0001
 | 
			
		||||
-#define BRCMF_FW_REQ_FLAGS		0x00F0
 | 
			
		||||
-#define  BRCMF_FW_REQ_NV_OPTIONAL	0x0010
 | 
			
		||||
+#define BRCMF_FW_REQF_OPTIONAL		0x0001
 | 
			
		||||
 
 | 
			
		||||
 #define	BRCMF_FW_NAME_LEN		320
 | 
			
		||||
 
 | 
			
		||||
@@ -54,21 +51,39 @@ int brcmf_fw_map_chip_to_name(u32 chip,
 | 
			
		||||
 			      u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
 | 
			
		||||
 			      char nvram_name[BRCMF_FW_NAME_LEN]);
 | 
			
		||||
 void brcmf_fw_nvram_free(void *nvram);
 | 
			
		||||
+
 | 
			
		||||
+enum brcmf_fw_type {
 | 
			
		||||
+	BRCMF_FW_TYPE_BINARY,
 | 
			
		||||
+	BRCMF_FW_TYPE_NVRAM
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+struct brcmf_fw_item {
 | 
			
		||||
+	const char *path;
 | 
			
		||||
+	enum brcmf_fw_type type;
 | 
			
		||||
+	u16 flags;
 | 
			
		||||
+	union {
 | 
			
		||||
+		const struct firmware *binary;
 | 
			
		||||
+		struct {
 | 
			
		||||
+			void *data;
 | 
			
		||||
+			u32 len;
 | 
			
		||||
+		} nv_data;
 | 
			
		||||
+	};
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+struct brcmf_fw_request {
 | 
			
		||||
+	u16 domain_nr;
 | 
			
		||||
+	u16 bus_nr;
 | 
			
		||||
+	u32 n_items;
 | 
			
		||||
+	struct brcmf_fw_item items[0];
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
 /*
 | 
			
		||||
  * Request firmware(s) asynchronously. When the asynchronous request
 | 
			
		||||
  * fails it will not use the callback, but call device_release_driver()
 | 
			
		||||
  * instead which will call the driver .remove() callback.
 | 
			
		||||
  */
 | 
			
		||||
-int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
 | 
			
		||||
-				const char *code, const char *nvram,
 | 
			
		||||
-				void (*fw_cb)(struct device *dev, int err,
 | 
			
		||||
-					      const struct firmware *fw,
 | 
			
		||||
-					      void *nvram_image, u32 nvram_len),
 | 
			
		||||
-				u16 domain_nr, u16 bus_nr);
 | 
			
		||||
-int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
 | 
			
		||||
-			   const char *code, const char *nvram,
 | 
			
		||||
+int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
 | 
			
		||||
 			   void (*fw_cb)(struct device *dev, int err,
 | 
			
		||||
-					 const struct firmware *fw,
 | 
			
		||||
-					 void *nvram_image, u32 nvram_len));
 | 
			
		||||
+					 struct brcmf_fw_request *req));
 | 
			
		||||
 
 | 
			
		||||
 #endif /* BRCMFMAC_FIRMWARE_H */
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
 | 
			
		||||
@@ -1651,15 +1651,19 @@ static const struct brcmf_buscore_ops br
 | 
			
		||||
 	.write32 = brcmf_pcie_buscore_write32,
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+#define BRCMF_PCIE_FW_CODE	0
 | 
			
		||||
+#define BRCMF_PCIE_FW_NVRAM	1
 | 
			
		||||
+
 | 
			
		||||
 static void brcmf_pcie_setup(struct device *dev, int ret,
 | 
			
		||||
-			     const struct firmware *fw,
 | 
			
		||||
-			     void *nvram, u32 nvram_len)
 | 
			
		||||
+			     struct brcmf_fw_request *fwreq)
 | 
			
		||||
 {
 | 
			
		||||
+	const struct firmware *fw;
 | 
			
		||||
+	void *nvram;
 | 
			
		||||
 	struct brcmf_bus *bus;
 | 
			
		||||
 	struct brcmf_pciedev *pcie_bus_dev;
 | 
			
		||||
 	struct brcmf_pciedev_info *devinfo;
 | 
			
		||||
 	struct brcmf_commonring **flowrings;
 | 
			
		||||
-	u32 i;
 | 
			
		||||
+	u32 i, nvram_len;
 | 
			
		||||
 
 | 
			
		||||
 	/* check firmware loading result */
 | 
			
		||||
 	if (ret)
 | 
			
		||||
@@ -1670,6 +1674,11 @@ static void brcmf_pcie_setup(struct devi
 | 
			
		||||
 	devinfo = pcie_bus_dev->devinfo;
 | 
			
		||||
 	brcmf_pcie_attach(devinfo);
 | 
			
		||||
 
 | 
			
		||||
+	fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary;
 | 
			
		||||
+	nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
 | 
			
		||||
+	nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
 | 
			
		||||
+	kfree(fwreq);
 | 
			
		||||
+
 | 
			
		||||
 	/* Some of the firmwares have the size of the memory of the device
 | 
			
		||||
 	 * defined inside the firmware. This is because part of the memory in
 | 
			
		||||
 	 * the device is shared and the devision is determined by FW. Parse
 | 
			
		||||
@@ -1730,6 +1739,7 @@ static int
 | 
			
		||||
 brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 | 
			
		||||
 {
 | 
			
		||||
 	int ret;
 | 
			
		||||
+	struct brcmf_fw_request *fwreq;
 | 
			
		||||
 	struct brcmf_pciedev_info *devinfo;
 | 
			
		||||
 	struct brcmf_pciedev *pcie_bus_dev;
 | 
			
		||||
 	struct brcmf_bus *bus;
 | 
			
		||||
@@ -1800,12 +1810,26 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
 | 
			
		||||
 	if (ret)
 | 
			
		||||
 		goto fail_bus;
 | 
			
		||||
 
 | 
			
		||||
-	ret = brcmf_fw_get_firmwares_pcie(bus->dev, BRCMF_FW_REQUEST_NVRAM |
 | 
			
		||||
-						    BRCMF_FW_REQ_NV_OPTIONAL,
 | 
			
		||||
-					  devinfo->fw_name, devinfo->nvram_name,
 | 
			
		||||
-					  brcmf_pcie_setup, domain_nr, bus_nr);
 | 
			
		||||
+	fwreq = kzalloc(sizeof(*fwreq) + 2 * sizeof(struct brcmf_fw_item),
 | 
			
		||||
+			GFP_KERNEL);
 | 
			
		||||
+	if (!fwreq) {
 | 
			
		||||
+		ret = -ENOMEM;
 | 
			
		||||
+		goto fail_bus;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	fwreq->items[BRCMF_PCIE_FW_CODE].path = devinfo->fw_name;
 | 
			
		||||
+	fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 | 
			
		||||
+	fwreq->items[BRCMF_PCIE_FW_NVRAM].path = devinfo->nvram_name;
 | 
			
		||||
+	fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
 | 
			
		||||
+	fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
 | 
			
		||||
+	fwreq->n_items = 2;
 | 
			
		||||
+	fwreq->domain_nr = domain_nr;
 | 
			
		||||
+	fwreq->bus_nr = bus_nr;
 | 
			
		||||
+	ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
 | 
			
		||||
 	if (ret == 0)
 | 
			
		||||
 		return 0;
 | 
			
		||||
+
 | 
			
		||||
+	kfree(fwreq);
 | 
			
		||||
 fail_bus:
 | 
			
		||||
 	kfree(bus->msgbuf);
 | 
			
		||||
 	kfree(bus);
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
 | 
			
		||||
@@ -4031,14 +4031,19 @@ static const struct brcmf_bus_ops brcmf_
 | 
			
		||||
 	.get_fwname = brcmf_sdio_get_fwname,
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+#define BRCMF_SDIO_FW_CODE	0
 | 
			
		||||
+#define BRCMF_SDIO_FW_NVRAM	1
 | 
			
		||||
+
 | 
			
		||||
 static void brcmf_sdio_firmware_callback(struct device *dev, int err,
 | 
			
		||||
-					 const struct firmware *code,
 | 
			
		||||
-					 void *nvram, u32 nvram_len)
 | 
			
		||||
+					 struct brcmf_fw_request *fwreq)
 | 
			
		||||
 {
 | 
			
		||||
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 | 
			
		||||
 	struct brcmf_sdio_dev *sdiod = bus_if->bus_priv.sdio;
 | 
			
		||||
 	struct brcmf_sdio *bus = sdiod->bus;
 | 
			
		||||
 	struct brcmf_core *core = bus->sdio_core;
 | 
			
		||||
+	const struct firmware *code;
 | 
			
		||||
+	void *nvram;
 | 
			
		||||
+	u32 nvram_len;
 | 
			
		||||
 	u8 saveclk;
 | 
			
		||||
 
 | 
			
		||||
 	brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
 | 
			
		||||
@@ -4046,6 +4051,11 @@ static void brcmf_sdio_firmware_callback
 | 
			
		||||
 	if (err)
 | 
			
		||||
 		goto fail;
 | 
			
		||||
 
 | 
			
		||||
+	code = fwreq->items[BRCMF_SDIO_FW_CODE].binary;
 | 
			
		||||
+	nvram = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.data;
 | 
			
		||||
+	nvram_len = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.len;
 | 
			
		||||
+	kfree(fwreq);
 | 
			
		||||
+
 | 
			
		||||
 	/* try to download image and nvram to the dongle */
 | 
			
		||||
 	bus->alp_only = true;
 | 
			
		||||
 	err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
 | 
			
		||||
@@ -4150,6 +4160,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
 | 
			
		||||
 	int ret;
 | 
			
		||||
 	struct brcmf_sdio *bus;
 | 
			
		||||
 	struct workqueue_struct *wq;
 | 
			
		||||
+	struct brcmf_fw_request *fwreq;
 | 
			
		||||
 
 | 
			
		||||
 	brcmf_dbg(TRACE, "Enter\n");
 | 
			
		||||
 
 | 
			
		||||
@@ -4240,11 +4251,24 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
 | 
			
		||||
 	if (ret)
 | 
			
		||||
 		goto fail;
 | 
			
		||||
 
 | 
			
		||||
-	ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM,
 | 
			
		||||
-				     sdiodev->fw_name, sdiodev->nvram_name,
 | 
			
		||||
+	fwreq = kzalloc(sizeof(fwreq) + 2 * sizeof(struct brcmf_fw_item),
 | 
			
		||||
+			GFP_KERNEL);
 | 
			
		||||
+	if (!fwreq) {
 | 
			
		||||
+		ret = -ENOMEM;
 | 
			
		||||
+		goto fail;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	fwreq->items[BRCMF_SDIO_FW_CODE].path = sdiodev->fw_name;
 | 
			
		||||
+	fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 | 
			
		||||
+	fwreq->items[BRCMF_SDIO_FW_NVRAM].path = sdiodev->nvram_name;
 | 
			
		||||
+	fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
 | 
			
		||||
+	fwreq->n_items = 2;
 | 
			
		||||
+
 | 
			
		||||
+	ret = brcmf_fw_get_firmwares(sdiodev->dev, fwreq,
 | 
			
		||||
 				     brcmf_sdio_firmware_callback);
 | 
			
		||||
 	if (ret != 0) {
 | 
			
		||||
 		brcmf_err("async firmware request failed: %d\n", ret);
 | 
			
		||||
+		kfree(fwreq);
 | 
			
		||||
 		goto fail;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
 | 
			
		||||
@@ -1155,18 +1155,23 @@ static const struct brcmf_bus_ops brcmf_
 | 
			
		||||
 	.get_fwname = brcmf_usb_get_fwname,
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+#define BRCMF_USB_FW_CODE	0
 | 
			
		||||
+
 | 
			
		||||
 static void brcmf_usb_probe_phase2(struct device *dev, int ret,
 | 
			
		||||
-				   const struct firmware *fw,
 | 
			
		||||
-				   void *nvram, u32 nvlen)
 | 
			
		||||
+				   struct brcmf_fw_request *fwreq)
 | 
			
		||||
 {
 | 
			
		||||
 	struct brcmf_bus *bus = dev_get_drvdata(dev);
 | 
			
		||||
 	struct brcmf_usbdev_info *devinfo = bus->bus_priv.usb->devinfo;
 | 
			
		||||
+	const struct firmware *fw;
 | 
			
		||||
 
 | 
			
		||||
 	if (ret)
 | 
			
		||||
 		goto error;
 | 
			
		||||
 
 | 
			
		||||
 	brcmf_dbg(USB, "Start fw downloading\n");
 | 
			
		||||
 
 | 
			
		||||
+	fw = fwreq->items[BRCMF_USB_FW_CODE].binary;
 | 
			
		||||
+	kfree(fwreq);
 | 
			
		||||
+
 | 
			
		||||
 	ret = check_file(fw->data);
 | 
			
		||||
 	if (ret < 0) {
 | 
			
		||||
 		brcmf_err("invalid firmware\n");
 | 
			
		||||
@@ -1200,6 +1205,7 @@ static int brcmf_usb_probe_cb(struct brc
 | 
			
		||||
 	struct brcmf_bus *bus = NULL;
 | 
			
		||||
 	struct brcmf_usbdev *bus_pub = NULL;
 | 
			
		||||
 	struct device *dev = devinfo->dev;
 | 
			
		||||
+	struct brcmf_fw_request *fwreq;
 | 
			
		||||
 	int ret;
 | 
			
		||||
 
 | 
			
		||||
 	brcmf_dbg(USB, "Enter\n");
 | 
			
		||||
@@ -1250,11 +1256,22 @@ static int brcmf_usb_probe_cb(struct brc
 | 
			
		||||
 	if (ret)
 | 
			
		||||
 		goto fail;
 | 
			
		||||
 
 | 
			
		||||
+	fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
 | 
			
		||||
+			GFP_KERNEL);
 | 
			
		||||
+	if (!fwreq) {
 | 
			
		||||
+		ret = -ENOMEM;
 | 
			
		||||
+		goto fail;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
 | 
			
		||||
+	fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 | 
			
		||||
+	fwreq->n_items = 1;
 | 
			
		||||
+
 | 
			
		||||
 	/* request firmware here */
 | 
			
		||||
-	ret = brcmf_fw_get_firmwares(dev, 0, devinfo->fw_name, NULL,
 | 
			
		||||
-				     brcmf_usb_probe_phase2);
 | 
			
		||||
+	ret = brcmf_fw_get_firmwares(dev, fwreq, brcmf_usb_probe_phase2);
 | 
			
		||||
 	if (ret) {
 | 
			
		||||
 		brcmf_err("firmware request failed: %d\n", ret);
 | 
			
		||||
+		kfree(fwreq);
 | 
			
		||||
 		goto fail;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@@ -1447,11 +1464,25 @@ static int brcmf_usb_reset_resume(struct
 | 
			
		||||
 {
 | 
			
		||||
 	struct usb_device *usb = interface_to_usbdev(intf);
 | 
			
		||||
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
 | 
			
		||||
+	struct brcmf_fw_request *fwreq;
 | 
			
		||||
+	int ret;
 | 
			
		||||
 
 | 
			
		||||
 	brcmf_dbg(USB, "Enter\n");
 | 
			
		||||
 
 | 
			
		||||
-	return brcmf_fw_get_firmwares(&usb->dev, 0, devinfo->fw_name, NULL,
 | 
			
		||||
-				      brcmf_usb_probe_phase2);
 | 
			
		||||
+	fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
 | 
			
		||||
+			GFP_KERNEL);
 | 
			
		||||
+	if (!fwreq)
 | 
			
		||||
+		return -ENOMEM;
 | 
			
		||||
+
 | 
			
		||||
+	fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
 | 
			
		||||
+	fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 | 
			
		||||
+	fwreq->n_items = 1;
 | 
			
		||||
+
 | 
			
		||||
+	ret = brcmf_fw_get_firmwares(&usb->dev, fwreq, brcmf_usb_probe_phase2);
 | 
			
		||||
+	if (ret < 0)
 | 
			
		||||
+		kfree(fwreq);
 | 
			
		||||
+
 | 
			
		||||
+	return ret;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 #define BRCMF_USB_DEVICE(dev_id)	\
 | 
			
		||||
@ -0,0 +1,328 @@
 | 
			
		||||
From 2baa3aaee27f137b8db9a9224d0fe9b281d28e34 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Date: Thu, 22 Mar 2018 21:28:27 +0100
 | 
			
		||||
Subject: [PATCH] brcmfmac: introduce brcmf_fw_alloc_request() function
 | 
			
		||||
 | 
			
		||||
The function brcmf_fw_alloc_request() takes a list of required files
 | 
			
		||||
and allocated the struct brcmf_fw_request instance accordingly. The
 | 
			
		||||
request can be modified by the caller before being passed to the
 | 
			
		||||
brcmf_fw_request_firmwares() function.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
 | 
			
		||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
 | 
			
		||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
 | 
			
		||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 | 
			
		||||
---
 | 
			
		||||
 .../broadcom/brcm80211/brcmfmac/firmware.c         | 58 ++++++++++++++++++++++
 | 
			
		||||
 .../broadcom/brcm80211/brcmfmac/firmware.h         | 11 ++++
 | 
			
		||||
 .../wireless/broadcom/brcm80211/brcmfmac/pcie.c    | 58 ++++++++++++----------
 | 
			
		||||
 .../wireless/broadcom/brcm80211/brcmfmac/sdio.c    | 38 ++++++++------
 | 
			
		||||
 .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 42 +++++++++-------
 | 
			
		||||
 5 files changed, 147 insertions(+), 60 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
@@ -688,3 +688,61 @@ int brcmf_fw_map_chip_to_name(u32 chip,
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+struct brcmf_fw_request *
 | 
			
		||||
+brcmf_fw_alloc_request(u32 chip, u32 chiprev,
 | 
			
		||||
+		       struct brcmf_firmware_mapping mapping_table[],
 | 
			
		||||
+		       u32 table_size, struct brcmf_fw_name *fwnames,
 | 
			
		||||
+		       u32 n_fwnames)
 | 
			
		||||
+{
 | 
			
		||||
+	struct brcmf_fw_request *fwreq;
 | 
			
		||||
+	char chipname[12];
 | 
			
		||||
+	const char *mp_path;
 | 
			
		||||
+	u32 i, j;
 | 
			
		||||
+	char end;
 | 
			
		||||
+	size_t reqsz;
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0; i < table_size; i++) {
 | 
			
		||||
+		if (mapping_table[i].chipid == chip &&
 | 
			
		||||
+		    mapping_table[i].revmask & BIT(chiprev))
 | 
			
		||||
+			break;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	if (i == table_size) {
 | 
			
		||||
+		brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev);
 | 
			
		||||
+		return NULL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	reqsz = sizeof(*fwreq) + n_fwnames * sizeof(struct brcmf_fw_item);
 | 
			
		||||
+	fwreq = kzalloc(reqsz, GFP_KERNEL);
 | 
			
		||||
+	if (!fwreq)
 | 
			
		||||
+		return NULL;
 | 
			
		||||
+
 | 
			
		||||
+	brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname));
 | 
			
		||||
+
 | 
			
		||||
+	brcmf_info("using %s for chip %s\n",
 | 
			
		||||
+		   mapping_table[i].fw_base, chipname);
 | 
			
		||||
+
 | 
			
		||||
+	mp_path = brcmf_mp_global.firmware_path;
 | 
			
		||||
+	end = mp_path[strlen(mp_path) - 1];
 | 
			
		||||
+	fwreq->n_items = n_fwnames;
 | 
			
		||||
+
 | 
			
		||||
+	for (j = 0; j < n_fwnames; j++) {
 | 
			
		||||
+		fwreq->items[j].path = fwnames[j].path;
 | 
			
		||||
+		/* check if firmware path is provided by module parameter */
 | 
			
		||||
+		if (brcmf_mp_global.firmware_path[0] != '\0') {
 | 
			
		||||
+			strlcpy(fwnames[j].path, mp_path,
 | 
			
		||||
+				BRCMF_FW_NAME_LEN);
 | 
			
		||||
+
 | 
			
		||||
+			if (end != '/') {
 | 
			
		||||
+				strlcat(fwnames[j].path, "/",
 | 
			
		||||
+					BRCMF_FW_NAME_LEN);
 | 
			
		||||
+			}
 | 
			
		||||
+		}
 | 
			
		||||
+		brcmf_fw_get_full_name(fwnames[j].path,
 | 
			
		||||
+				       mapping_table[i].fw_base,
 | 
			
		||||
+				       fwnames[j].extension);
 | 
			
		||||
+		fwreq->items[j].path = fwnames[j].path;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return fwreq;
 | 
			
		||||
+}
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
 | 
			
		||||
@@ -77,6 +77,17 @@ struct brcmf_fw_request {
 | 
			
		||||
 	struct brcmf_fw_item items[0];
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+struct brcmf_fw_name {
 | 
			
		||||
+	const char *extension;
 | 
			
		||||
+	char *path;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+struct brcmf_fw_request *
 | 
			
		||||
+brcmf_fw_alloc_request(u32 chip, u32 chiprev,
 | 
			
		||||
+		       struct brcmf_firmware_mapping mapping_table[],
 | 
			
		||||
+		       u32 table_size, struct brcmf_fw_name *fwnames,
 | 
			
		||||
+		       u32 n_fwnames);
 | 
			
		||||
+
 | 
			
		||||
 /*
 | 
			
		||||
  * Request firmware(s) asynchronously. When the asynchronous request
 | 
			
		||||
  * fails it will not use the callback, but call device_release_driver()
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
 | 
			
		||||
@@ -1735,6 +1735,31 @@ fail:
 | 
			
		||||
 	device_release_driver(dev);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static struct brcmf_fw_request *
 | 
			
		||||
+brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
 | 
			
		||||
+{
 | 
			
		||||
+	struct brcmf_fw_request *fwreq;
 | 
			
		||||
+	struct brcmf_fw_name fwnames[] = {
 | 
			
		||||
+		{ ".bin", devinfo->fw_name },
 | 
			
		||||
+		{ ".txt", devinfo->nvram_name },
 | 
			
		||||
+	};
 | 
			
		||||
+
 | 
			
		||||
+	fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
 | 
			
		||||
+				       brcmf_pcie_fwnames,
 | 
			
		||||
+				       ARRAY_SIZE(brcmf_pcie_fwnames),
 | 
			
		||||
+				       fwnames, ARRAY_SIZE(fwnames));
 | 
			
		||||
+	if (!fwreq)
 | 
			
		||||
+		return NULL;
 | 
			
		||||
+
 | 
			
		||||
+	fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 | 
			
		||||
+	fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
 | 
			
		||||
+	fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
 | 
			
		||||
+	fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus);
 | 
			
		||||
+	fwreq->bus_nr = devinfo->pdev->bus->number;
 | 
			
		||||
+
 | 
			
		||||
+	return fwreq;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int
 | 
			
		||||
 brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 | 
			
		||||
 {
 | 
			
		||||
@@ -1743,13 +1768,8 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
 | 
			
		||||
 	struct brcmf_pciedev_info *devinfo;
 | 
			
		||||
 	struct brcmf_pciedev *pcie_bus_dev;
 | 
			
		||||
 	struct brcmf_bus *bus;
 | 
			
		||||
-	u16 domain_nr;
 | 
			
		||||
-	u16 bus_nr;
 | 
			
		||||
 
 | 
			
		||||
-	domain_nr = pci_domain_nr(pdev->bus) + 1;
 | 
			
		||||
-	bus_nr = pdev->bus->number;
 | 
			
		||||
-	brcmf_dbg(PCIE, "Enter %x:%x (%d/%d)\n", pdev->vendor, pdev->device,
 | 
			
		||||
-		  domain_nr, bus_nr);
 | 
			
		||||
+	brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
 | 
			
		||||
 
 | 
			
		||||
 	ret = -ENOMEM;
 | 
			
		||||
 	devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
 | 
			
		||||
@@ -1803,33 +1823,19 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
 | 
			
		||||
 	bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot);
 | 
			
		||||
 	dev_set_drvdata(&pdev->dev, bus);
 | 
			
		||||
 
 | 
			
		||||
-	ret = brcmf_fw_map_chip_to_name(devinfo->ci->chip, devinfo->ci->chiprev,
 | 
			
		||||
-					brcmf_pcie_fwnames,
 | 
			
		||||
-					ARRAY_SIZE(brcmf_pcie_fwnames),
 | 
			
		||||
-					devinfo->fw_name, devinfo->nvram_name);
 | 
			
		||||
-	if (ret)
 | 
			
		||||
-		goto fail_bus;
 | 
			
		||||
-
 | 
			
		||||
-	fwreq = kzalloc(sizeof(*fwreq) + 2 * sizeof(struct brcmf_fw_item),
 | 
			
		||||
-			GFP_KERNEL);
 | 
			
		||||
+	fwreq = brcmf_pcie_prepare_fw_request(devinfo);
 | 
			
		||||
 	if (!fwreq) {
 | 
			
		||||
 		ret = -ENOMEM;
 | 
			
		||||
 		goto fail_bus;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	fwreq->items[BRCMF_PCIE_FW_CODE].path = devinfo->fw_name;
 | 
			
		||||
-	fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 | 
			
		||||
-	fwreq->items[BRCMF_PCIE_FW_NVRAM].path = devinfo->nvram_name;
 | 
			
		||||
-	fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
 | 
			
		||||
-	fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
 | 
			
		||||
-	fwreq->n_items = 2;
 | 
			
		||||
-	fwreq->domain_nr = domain_nr;
 | 
			
		||||
-	fwreq->bus_nr = bus_nr;
 | 
			
		||||
 	ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
 | 
			
		||||
-	if (ret == 0)
 | 
			
		||||
-		return 0;
 | 
			
		||||
+	if (ret < 0) {
 | 
			
		||||
+		kfree(fwreq);
 | 
			
		||||
+		goto fail_bus;
 | 
			
		||||
+	}
 | 
			
		||||
+	return 0;
 | 
			
		||||
 
 | 
			
		||||
-	kfree(fwreq);
 | 
			
		||||
 fail_bus:
 | 
			
		||||
 	kfree(bus->msgbuf);
 | 
			
		||||
 	kfree(bus);
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
 | 
			
		||||
@@ -4155,6 +4155,28 @@ fail:
 | 
			
		||||
 	device_release_driver(dev);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static struct brcmf_fw_request *
 | 
			
		||||
+brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
 | 
			
		||||
+{
 | 
			
		||||
+	struct brcmf_fw_request *fwreq;
 | 
			
		||||
+	struct brcmf_fw_name fwnames[] = {
 | 
			
		||||
+		{ ".bin", bus->sdiodev->fw_name },
 | 
			
		||||
+		{ ".txt", bus->sdiodev->nvram_name },
 | 
			
		||||
+	};
 | 
			
		||||
+
 | 
			
		||||
+	fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
 | 
			
		||||
+				       brcmf_sdio_fwnames,
 | 
			
		||||
+				       ARRAY_SIZE(brcmf_sdio_fwnames),
 | 
			
		||||
+				       fwnames, ARRAY_SIZE(fwnames));
 | 
			
		||||
+	if (!fwreq)
 | 
			
		||||
+		return NULL;
 | 
			
		||||
+
 | 
			
		||||
+	fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 | 
			
		||||
+	fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
 | 
			
		||||
+
 | 
			
		||||
+	return fwreq;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
 | 
			
		||||
 {
 | 
			
		||||
 	int ret;
 | 
			
		||||
@@ -4244,26 +4266,12 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
 | 
			
		||||
 
 | 
			
		||||
 	brcmf_dbg(INFO, "completed!!\n");
 | 
			
		||||
 
 | 
			
		||||
-	ret = brcmf_fw_map_chip_to_name(bus->ci->chip, bus->ci->chiprev,
 | 
			
		||||
-					brcmf_sdio_fwnames,
 | 
			
		||||
-					ARRAY_SIZE(brcmf_sdio_fwnames),
 | 
			
		||||
-					sdiodev->fw_name, sdiodev->nvram_name);
 | 
			
		||||
-	if (ret)
 | 
			
		||||
-		goto fail;
 | 
			
		||||
-
 | 
			
		||||
-	fwreq = kzalloc(sizeof(fwreq) + 2 * sizeof(struct brcmf_fw_item),
 | 
			
		||||
-			GFP_KERNEL);
 | 
			
		||||
+	fwreq = brcmf_sdio_prepare_fw_request(bus);
 | 
			
		||||
 	if (!fwreq) {
 | 
			
		||||
 		ret = -ENOMEM;
 | 
			
		||||
 		goto fail;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	fwreq->items[BRCMF_SDIO_FW_CODE].path = sdiodev->fw_name;
 | 
			
		||||
-	fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 | 
			
		||||
-	fwreq->items[BRCMF_SDIO_FW_NVRAM].path = sdiodev->nvram_name;
 | 
			
		||||
-	fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
 | 
			
		||||
-	fwreq->n_items = 2;
 | 
			
		||||
-
 | 
			
		||||
 	ret = brcmf_fw_get_firmwares(sdiodev->dev, fwreq,
 | 
			
		||||
 				     brcmf_sdio_firmware_callback);
 | 
			
		||||
 	if (ret != 0) {
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
 | 
			
		||||
@@ -1200,6 +1200,27 @@ error:
 | 
			
		||||
 	device_release_driver(dev);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static struct brcmf_fw_request *
 | 
			
		||||
+brcmf_usb_prepare_fw_request(struct brcmf_usbdev_info *devinfo)
 | 
			
		||||
+{
 | 
			
		||||
+	struct brcmf_fw_request *fwreq;
 | 
			
		||||
+	struct brcmf_fw_name fwnames[] = {
 | 
			
		||||
+		{ ".bin", devinfo->fw_name },
 | 
			
		||||
+	};
 | 
			
		||||
+
 | 
			
		||||
+	fwreq = brcmf_fw_alloc_request(devinfo->bus_pub.devid,
 | 
			
		||||
+				       devinfo->bus_pub.chiprev,
 | 
			
		||||
+				       brcmf_usb_fwnames,
 | 
			
		||||
+				       ARRAY_SIZE(brcmf_usb_fwnames),
 | 
			
		||||
+				       fwnames, ARRAY_SIZE(fwnames));
 | 
			
		||||
+	if (!fwreq)
 | 
			
		||||
+		return NULL;
 | 
			
		||||
+
 | 
			
		||||
+	fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 | 
			
		||||
+
 | 
			
		||||
+	return fwreq;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
 | 
			
		||||
 {
 | 
			
		||||
 	struct brcmf_bus *bus = NULL;
 | 
			
		||||
@@ -1249,24 +1270,12 @@ static int brcmf_usb_probe_cb(struct brc
 | 
			
		||||
 	bus->chip = bus_pub->devid;
 | 
			
		||||
 	bus->chiprev = bus_pub->chiprev;
 | 
			
		||||
 
 | 
			
		||||
-	ret = brcmf_fw_map_chip_to_name(bus_pub->devid, bus_pub->chiprev,
 | 
			
		||||
-					brcmf_usb_fwnames,
 | 
			
		||||
-					ARRAY_SIZE(brcmf_usb_fwnames),
 | 
			
		||||
-					devinfo->fw_name, NULL);
 | 
			
		||||
-	if (ret)
 | 
			
		||||
-		goto fail;
 | 
			
		||||
-
 | 
			
		||||
-	fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
 | 
			
		||||
-			GFP_KERNEL);
 | 
			
		||||
+	fwreq = brcmf_usb_prepare_fw_request(devinfo);
 | 
			
		||||
 	if (!fwreq) {
 | 
			
		||||
 		ret = -ENOMEM;
 | 
			
		||||
 		goto fail;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
 | 
			
		||||
-	fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 | 
			
		||||
-	fwreq->n_items = 1;
 | 
			
		||||
-
 | 
			
		||||
 	/* request firmware here */
 | 
			
		||||
 	ret = brcmf_fw_get_firmwares(dev, fwreq, brcmf_usb_probe_phase2);
 | 
			
		||||
 	if (ret) {
 | 
			
		||||
@@ -1469,15 +1478,10 @@ static int brcmf_usb_reset_resume(struct
 | 
			
		||||
 
 | 
			
		||||
 	brcmf_dbg(USB, "Enter\n");
 | 
			
		||||
 
 | 
			
		||||
-	fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
 | 
			
		||||
-			GFP_KERNEL);
 | 
			
		||||
+	fwreq = brcmf_usb_prepare_fw_request(devinfo);
 | 
			
		||||
 	if (!fwreq)
 | 
			
		||||
 		return -ENOMEM;
 | 
			
		||||
 
 | 
			
		||||
-	fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
 | 
			
		||||
-	fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 | 
			
		||||
-	fwreq->n_items = 1;
 | 
			
		||||
-
 | 
			
		||||
 	ret = brcmf_fw_get_firmwares(&usb->dev, fwreq, brcmf_usb_probe_phase2);
 | 
			
		||||
 	if (ret < 0)
 | 
			
		||||
 		kfree(fwreq);
 | 
			
		||||
@ -0,0 +1,231 @@
 | 
			
		||||
From bf7a7b37f6ef5090a2bae7e7ae23cd26b741cca4 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Date: Thu, 22 Mar 2018 21:28:28 +0100
 | 
			
		||||
Subject: [PATCH] brcmfmac: add extension to .get_fwname() callbacks
 | 
			
		||||
 | 
			
		||||
This changes the bus layer api by having the caller provide an
 | 
			
		||||
extension. With this the callback can use brcmf_fw_alloc_request()
 | 
			
		||||
to get the needed firmware name.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
 | 
			
		||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
 | 
			
		||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
 | 
			
		||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 | 
			
		||||
---
 | 
			
		||||
 .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h |  6 +--
 | 
			
		||||
 .../wireless/broadcom/brcm80211/brcmfmac/common.c  | 43 +++-------------------
 | 
			
		||||
 .../wireless/broadcom/brcm80211/brcmfmac/pcie.c    | 27 +++++++-------
 | 
			
		||||
 .../wireless/broadcom/brcm80211/brcmfmac/sdio.c    | 26 +++++++------
 | 
			
		||||
 .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 27 ++++++++------
 | 
			
		||||
 5 files changed, 51 insertions(+), 78 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
 | 
			
		||||
@@ -88,7 +88,7 @@ struct brcmf_bus_ops {
 | 
			
		||||
 	void (*wowl_config)(struct device *dev, bool enabled);
 | 
			
		||||
 	size_t (*get_ramsize)(struct device *dev);
 | 
			
		||||
 	int (*get_memdump)(struct device *dev, void *data, size_t len);
 | 
			
		||||
-	int (*get_fwname)(struct device *dev, uint chip, uint chiprev,
 | 
			
		||||
+	int (*get_fwname)(struct device *dev, const char *ext,
 | 
			
		||||
 			  unsigned char *fw_name);
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
@@ -228,10 +228,10 @@ int brcmf_bus_get_memdump(struct brcmf_b
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static inline
 | 
			
		||||
-int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev,
 | 
			
		||||
+int brcmf_bus_get_fwname(struct brcmf_bus *bus, const char *ext,
 | 
			
		||||
 			 unsigned char *fw_name)
 | 
			
		||||
 {
 | 
			
		||||
-	return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name);
 | 
			
		||||
+	return bus->ops->get_fwname(bus->dev, ext, fw_name);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 /*
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
 | 
			
		||||
@@ -129,42 +129,9 @@ static int brcmf_c_download(struct brcmf
 | 
			
		||||
 	return err;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name)
 | 
			
		||||
-{
 | 
			
		||||
-	struct brcmf_bus *bus = ifp->drvr->bus_if;
 | 
			
		||||
-	u8 fw_name[BRCMF_FW_NAME_LEN];
 | 
			
		||||
-	u8 *ptr;
 | 
			
		||||
-	size_t len;
 | 
			
		||||
-	s32 err;
 | 
			
		||||
-
 | 
			
		||||
-	memset(fw_name, 0, BRCMF_FW_NAME_LEN);
 | 
			
		||||
-	err = brcmf_bus_get_fwname(bus, bus->chip, bus->chiprev, fw_name);
 | 
			
		||||
-	if (err) {
 | 
			
		||||
-		brcmf_err("get firmware name failed (%d)\n", err);
 | 
			
		||||
-		goto done;
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
-	/* generate CLM blob file name */
 | 
			
		||||
-	ptr = strrchr(fw_name, '.');
 | 
			
		||||
-	if (!ptr) {
 | 
			
		||||
-		err = -ENOENT;
 | 
			
		||||
-		goto done;
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
-	len = ptr - fw_name + 1;
 | 
			
		||||
-	if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) {
 | 
			
		||||
-		err = -E2BIG;
 | 
			
		||||
-	} else {
 | 
			
		||||
-		strlcpy(clm_name, fw_name, len);
 | 
			
		||||
-		strlcat(clm_name, ".clm_blob", BRCMF_FW_NAME_LEN);
 | 
			
		||||
-	}
 | 
			
		||||
-done:
 | 
			
		||||
-	return err;
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
 static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
 | 
			
		||||
 {
 | 
			
		||||
-	struct device *dev = ifp->drvr->bus_if->dev;
 | 
			
		||||
+	struct brcmf_bus *bus = ifp->drvr->bus_if;
 | 
			
		||||
 	struct brcmf_dload_data_le *chunk_buf;
 | 
			
		||||
 	const struct firmware *clm = NULL;
 | 
			
		||||
 	u8 clm_name[BRCMF_FW_NAME_LEN];
 | 
			
		||||
@@ -177,16 +144,16 @@ static int brcmf_c_process_clm_blob(stru
 | 
			
		||||
 
 | 
			
		||||
 	brcmf_dbg(TRACE, "Enter\n");
 | 
			
		||||
 
 | 
			
		||||
-	memset(clm_name, 0, BRCMF_FW_NAME_LEN);
 | 
			
		||||
-	err = brcmf_c_get_clm_name(ifp, clm_name);
 | 
			
		||||
+	memset(clm_name, 0, sizeof(clm_name));
 | 
			
		||||
+	err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name);
 | 
			
		||||
 	if (err) {
 | 
			
		||||
 		brcmf_err("get CLM blob file name failed (%d)\n", err);
 | 
			
		||||
 		return err;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	err = request_firmware(&clm, clm_name, dev);
 | 
			
		||||
+	err = request_firmware(&clm, clm_name, bus->dev);
 | 
			
		||||
 	if (err) {
 | 
			
		||||
-		brcmf_info("no clm_blob available(err=%d), device may have limited channels available\n",
 | 
			
		||||
+		brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
 | 
			
		||||
 			   err);
 | 
			
		||||
 		return 0;
 | 
			
		||||
 	}
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
 | 
			
		||||
@@ -1350,23 +1350,24 @@ static int brcmf_pcie_get_memdump(struct
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int brcmf_pcie_get_fwname(struct device *dev, u32 chip, u32 chiprev,
 | 
			
		||||
-				 u8 *fw_name)
 | 
			
		||||
+static
 | 
			
		||||
+int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
 | 
			
		||||
 {
 | 
			
		||||
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 | 
			
		||||
-	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
 | 
			
		||||
-	struct brcmf_pciedev_info *devinfo = buspub->devinfo;
 | 
			
		||||
-	int ret = 0;
 | 
			
		||||
+	struct brcmf_fw_request *fwreq;
 | 
			
		||||
+	struct brcmf_fw_name fwnames[] = {
 | 
			
		||||
+		{ ext, fw_name },
 | 
			
		||||
+	};
 | 
			
		||||
 
 | 
			
		||||
-	if (devinfo->fw_name[0] != '\0')
 | 
			
		||||
-		strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN);
 | 
			
		||||
-	else
 | 
			
		||||
-		ret = brcmf_fw_map_chip_to_name(chip, chiprev,
 | 
			
		||||
-						brcmf_pcie_fwnames,
 | 
			
		||||
-						ARRAY_SIZE(brcmf_pcie_fwnames),
 | 
			
		||||
-						fw_name, NULL);
 | 
			
		||||
+	fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
 | 
			
		||||
+				       brcmf_pcie_fwnames,
 | 
			
		||||
+				       ARRAY_SIZE(brcmf_pcie_fwnames),
 | 
			
		||||
+				       fwnames, ARRAY_SIZE(fwnames));
 | 
			
		||||
+	if (!fwreq)
 | 
			
		||||
+		return -ENOMEM;
 | 
			
		||||
 
 | 
			
		||||
-	return ret;
 | 
			
		||||
+	kfree(fwreq);
 | 
			
		||||
+	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
 | 
			
		||||
@@ -4000,22 +4000,24 @@ brcmf_sdio_watchdog(unsigned long data)
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int brcmf_sdio_get_fwname(struct device *dev, u32 chip, u32 chiprev,
 | 
			
		||||
-				 u8 *fw_name)
 | 
			
		||||
+static
 | 
			
		||||
+int brcmf_sdio_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
 | 
			
		||||
 {
 | 
			
		||||
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 | 
			
		||||
-	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 | 
			
		||||
-	int ret = 0;
 | 
			
		||||
+	struct brcmf_fw_request *fwreq;
 | 
			
		||||
+	struct brcmf_fw_name fwnames[] = {
 | 
			
		||||
+		{ ext, fw_name },
 | 
			
		||||
+	};
 | 
			
		||||
 
 | 
			
		||||
-	if (sdiodev->fw_name[0] != '\0')
 | 
			
		||||
-		strlcpy(fw_name, sdiodev->fw_name, BRCMF_FW_NAME_LEN);
 | 
			
		||||
-	else
 | 
			
		||||
-		ret = brcmf_fw_map_chip_to_name(chip, chiprev,
 | 
			
		||||
-						brcmf_sdio_fwnames,
 | 
			
		||||
-						ARRAY_SIZE(brcmf_sdio_fwnames),
 | 
			
		||||
-						fw_name, NULL);
 | 
			
		||||
+	fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
 | 
			
		||||
+				       brcmf_sdio_fwnames,
 | 
			
		||||
+				       ARRAY_SIZE(brcmf_sdio_fwnames),
 | 
			
		||||
+				       fwnames, ARRAY_SIZE(fwnames));
 | 
			
		||||
+	if (!fwreq)
 | 
			
		||||
+		return -ENOMEM;
 | 
			
		||||
 
 | 
			
		||||
-	return ret;
 | 
			
		||||
+	kfree(fwreq);
 | 
			
		||||
+	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
 | 
			
		||||
@@ -1128,21 +1128,24 @@ static void brcmf_usb_wowl_config(struct
 | 
			
		||||
 		device_set_wakeup_enable(devinfo->dev, false);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int brcmf_usb_get_fwname(struct device *dev, u32 chip, u32 chiprev,
 | 
			
		||||
-				u8 *fw_name)
 | 
			
		||||
+static
 | 
			
		||||
+int brcmf_usb_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
 | 
			
		||||
 {
 | 
			
		||||
-	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
 | 
			
		||||
-	int ret = 0;
 | 
			
		||||
+	struct brcmf_bus *bus = dev_get_drvdata(dev);
 | 
			
		||||
+	struct brcmf_fw_request *fwreq;
 | 
			
		||||
+	struct brcmf_fw_name fwnames[] = {
 | 
			
		||||
+		{ ext, fw_name },
 | 
			
		||||
+	};
 | 
			
		||||
 
 | 
			
		||||
-	if (devinfo->fw_name[0] != '\0')
 | 
			
		||||
-		strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN);
 | 
			
		||||
-	else
 | 
			
		||||
-		ret = brcmf_fw_map_chip_to_name(chip, chiprev,
 | 
			
		||||
-						brcmf_usb_fwnames,
 | 
			
		||||
-						ARRAY_SIZE(brcmf_usb_fwnames),
 | 
			
		||||
-						fw_name, NULL);
 | 
			
		||||
+	fwreq = brcmf_fw_alloc_request(bus->chip, bus->chiprev,
 | 
			
		||||
+				       brcmf_usb_fwnames,
 | 
			
		||||
+				       ARRAY_SIZE(brcmf_usb_fwnames),
 | 
			
		||||
+				       fwnames, ARRAY_SIZE(fwnames));
 | 
			
		||||
+	if (!fwreq)
 | 
			
		||||
+		return -ENOMEM;
 | 
			
		||||
 
 | 
			
		||||
-	return ret;
 | 
			
		||||
+	kfree(fwreq);
 | 
			
		||||
+	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
 | 
			
		||||
@ -0,0 +1,92 @@
 | 
			
		||||
From 18c2b20e276e04476a3350b4a92c1dfad725d45d Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Date: Thu, 22 Mar 2018 21:28:29 +0100
 | 
			
		||||
Subject: [PATCH] brcmfmac: get rid of brcmf_fw_map_chip_to_name()
 | 
			
		||||
 | 
			
		||||
The function is no longer used so removing it.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
 | 
			
		||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
 | 
			
		||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
 | 
			
		||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 | 
			
		||||
---
 | 
			
		||||
 .../broadcom/brcm80211/brcmfmac/firmware.c         | 53 ----------------------
 | 
			
		||||
 .../broadcom/brcm80211/brcmfmac/firmware.h         |  4 --
 | 
			
		||||
 2 files changed, 57 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
@@ -635,59 +635,6 @@ static void brcmf_fw_get_full_name(char
 | 
			
		||||
 	strlcat(fw_name, extension, BRCMF_FW_NAME_LEN);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
 | 
			
		||||
-			      struct brcmf_firmware_mapping mapping_table[],
 | 
			
		||||
-			      u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
 | 
			
		||||
-			      char nvram_name[BRCMF_FW_NAME_LEN])
 | 
			
		||||
-{
 | 
			
		||||
-	char chipname[12];
 | 
			
		||||
-	u32 i;
 | 
			
		||||
-	char end;
 | 
			
		||||
-
 | 
			
		||||
-	for (i = 0; i < table_size; i++) {
 | 
			
		||||
-		if (mapping_table[i].chipid == chip &&
 | 
			
		||||
-		    mapping_table[i].revmask & BIT(chiprev))
 | 
			
		||||
-			break;
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
-	if (i == table_size) {
 | 
			
		||||
-		brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev);
 | 
			
		||||
-		return -ENODEV;
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
-	brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname));
 | 
			
		||||
-
 | 
			
		||||
-	/* check if firmware path is provided by module parameter */
 | 
			
		||||
-	if (brcmf_mp_global.firmware_path[0] != '\0') {
 | 
			
		||||
-		if (fw_name)
 | 
			
		||||
-			strlcpy(fw_name, brcmf_mp_global.firmware_path,
 | 
			
		||||
-				BRCMF_FW_NAME_LEN);
 | 
			
		||||
-		if (nvram_name)
 | 
			
		||||
-			strlcpy(nvram_name, brcmf_mp_global.firmware_path,
 | 
			
		||||
-				BRCMF_FW_NAME_LEN);
 | 
			
		||||
-
 | 
			
		||||
-		end = brcmf_mp_global.firmware_path[
 | 
			
		||||
-				strlen(brcmf_mp_global.firmware_path) - 1];
 | 
			
		||||
-		if (end != '/') {
 | 
			
		||||
-			if (fw_name)
 | 
			
		||||
-				strlcat(fw_name, "/", BRCMF_FW_NAME_LEN);
 | 
			
		||||
-			if (nvram_name)
 | 
			
		||||
-				strlcat(nvram_name, "/", BRCMF_FW_NAME_LEN);
 | 
			
		||||
-		}
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
-	brcmf_info("using %s for chip %s\n",
 | 
			
		||||
-		   mapping_table[i].fw_base, chipname);
 | 
			
		||||
-	if (fw_name)
 | 
			
		||||
-		brcmf_fw_get_full_name(fw_name,
 | 
			
		||||
-				       mapping_table[i].fw_base, ".bin");
 | 
			
		||||
-	if (nvram_name)
 | 
			
		||||
-		brcmf_fw_get_full_name(nvram_name,
 | 
			
		||||
-				       mapping_table[i].fw_base, ".txt");
 | 
			
		||||
-
 | 
			
		||||
-	return 0;
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
 struct brcmf_fw_request *
 | 
			
		||||
 brcmf_fw_alloc_request(u32 chip, u32 chiprev,
 | 
			
		||||
 		       struct brcmf_firmware_mapping mapping_table[],
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
 | 
			
		||||
@@ -46,10 +46,6 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw
 | 
			
		||||
 #define BRCMF_FW_ENTRY(chipid, mask, name) \
 | 
			
		||||
 	{ chipid, mask, BRCM_ ## name ## _FIRMWARE_BASENAME }
 | 
			
		||||
 
 | 
			
		||||
-int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
 | 
			
		||||
-			      struct brcmf_firmware_mapping mapping_table[],
 | 
			
		||||
-			      u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
 | 
			
		||||
-			      char nvram_name[BRCMF_FW_NAME_LEN]);
 | 
			
		||||
 void brcmf_fw_nvram_free(void *nvram);
 | 
			
		||||
 
 | 
			
		||||
 enum brcmf_fw_type {
 | 
			
		||||
@ -0,0 +1,44 @@
 | 
			
		||||
From bf291b7247e53f52a4236c0b55a5df046d6177df Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Date: Thu, 22 Mar 2018 21:28:30 +0100
 | 
			
		||||
Subject: [PATCH] brcmfmac: get rid of brcmf_fw_get_full_name()
 | 
			
		||||
 | 
			
		||||
The function was pretty minimal and now it is called only from one
 | 
			
		||||
place so just get rid of it.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 | 
			
		||||
---
 | 
			
		||||
 .../net/wireless/broadcom/brcm80211/brcmfmac/firmware.c    | 14 ++++----------
 | 
			
		||||
 1 file changed, 4 insertions(+), 10 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
@@ -628,13 +628,6 @@ int brcmf_fw_get_firmwares(struct device
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static void brcmf_fw_get_full_name(char fw_name[BRCMF_FW_NAME_LEN],
 | 
			
		||||
-				   const char *fw_base, const char *extension)
 | 
			
		||||
-{
 | 
			
		||||
-	strlcat(fw_name, fw_base, BRCMF_FW_NAME_LEN);
 | 
			
		||||
-	strlcat(fw_name, extension, BRCMF_FW_NAME_LEN);
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
 struct brcmf_fw_request *
 | 
			
		||||
 brcmf_fw_alloc_request(u32 chip, u32 chiprev,
 | 
			
		||||
 		       struct brcmf_firmware_mapping mapping_table[],
 | 
			
		||||
@@ -685,9 +678,10 @@ brcmf_fw_alloc_request(u32 chip, u32 chi
 | 
			
		||||
 					BRCMF_FW_NAME_LEN);
 | 
			
		||||
 			}
 | 
			
		||||
 		}
 | 
			
		||||
-		brcmf_fw_get_full_name(fwnames[j].path,
 | 
			
		||||
-				       mapping_table[i].fw_base,
 | 
			
		||||
-				       fwnames[j].extension);
 | 
			
		||||
+		strlcat(fwnames[j].path, mapping_table[i].fw_base,
 | 
			
		||||
+			BRCMF_FW_NAME_LEN);
 | 
			
		||||
+		strlcat(fwnames[j].path, fwnames[j].extension,
 | 
			
		||||
+			BRCMF_FW_NAME_LEN);
 | 
			
		||||
 		fwreq->items[j].path = fwnames[j].path;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,23 @@
 | 
			
		||||
From 48eaee3f272a5bfe6986d07c51f6975d3c2f74d1 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Date: Thu, 22 Mar 2018 21:28:31 +0100
 | 
			
		||||
Subject: [PATCH] brcmfmac: add kerneldoc for struct brcmf_bus::msgbuf
 | 
			
		||||
 | 
			
		||||
This field did not have kerneldoc description so adding it now.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 1 +
 | 
			
		||||
 1 file changed, 1 insertion(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
 | 
			
		||||
@@ -140,6 +140,7 @@ struct brcmf_bus_stats {
 | 
			
		||||
  * @always_use_fws_queue: bus wants use queue also when fwsignal is inactive.
 | 
			
		||||
  * @wowl_supported: is wowl supported by bus driver.
 | 
			
		||||
  * @chiprev: revision of the dongle chip.
 | 
			
		||||
+ * @msgbuf: msgbuf protocol parameters provided by bus layer.
 | 
			
		||||
  */
 | 
			
		||||
 struct brcmf_bus {
 | 
			
		||||
 	union {
 | 
			
		||||
@ -0,0 +1,81 @@
 | 
			
		||||
From 0b5c0305e57ca940713bcb2b202fd2b412c62f31 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Date: Tue, 3 Apr 2018 10:18:15 +0200
 | 
			
		||||
Subject: [PATCH] brcmfmac: fix firmware request processing if nvram load fails
 | 
			
		||||
 | 
			
		||||
When nvram loading fails a double free occurred. Fix this and reorg the
 | 
			
		||||
code a little.
 | 
			
		||||
 | 
			
		||||
Fixes: d09ae51a4b67 ("brcmfmac: pass struct in brcmf_fw_get_firmwares()")
 | 
			
		||||
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
 | 
			
		||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 | 
			
		||||
---
 | 
			
		||||
 .../broadcom/brcm80211/brcmfmac/firmware.c         | 36 ++++++++++++----------
 | 
			
		||||
 1 file changed, 20 insertions(+), 16 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
@@ -459,7 +459,7 @@ static void brcmf_fw_free_request(struct
 | 
			
		||||
 	kfree(req);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
 | 
			
		||||
+static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
 | 
			
		||||
 {
 | 
			
		||||
 	struct brcmf_fw *fwctx = ctx;
 | 
			
		||||
 	struct brcmf_fw_item *cur;
 | 
			
		||||
@@ -498,13 +498,10 @@ static void brcmf_fw_request_nvram_done(
 | 
			
		||||
 	brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length);
 | 
			
		||||
 	cur->nv_data.data = nvram;
 | 
			
		||||
 	cur->nv_data.len = nvram_length;
 | 
			
		||||
-	return;
 | 
			
		||||
+	return 0;
 | 
			
		||||
 
 | 
			
		||||
 fail:
 | 
			
		||||
-	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
 | 
			
		||||
-	fwctx->done(fwctx->dev, -ENOENT, NULL);
 | 
			
		||||
-	brcmf_fw_free_request(fwctx->req);
 | 
			
		||||
-	kfree(fwctx);
 | 
			
		||||
+	return -ENOENT;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async)
 | 
			
		||||
@@ -553,20 +550,27 @@ static void brcmf_fw_request_done(const
 | 
			
		||||
 	brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path,
 | 
			
		||||
 		  fw ? "" : "not ");
 | 
			
		||||
 
 | 
			
		||||
-	if (fw) {
 | 
			
		||||
-		if (cur->type == BRCMF_FW_TYPE_BINARY)
 | 
			
		||||
-			cur->binary = fw;
 | 
			
		||||
-		else if (cur->type == BRCMF_FW_TYPE_NVRAM)
 | 
			
		||||
-			brcmf_fw_request_nvram_done(fw, fwctx);
 | 
			
		||||
-		else
 | 
			
		||||
-			release_firmware(fw);
 | 
			
		||||
-	} else if (cur->type == BRCMF_FW_TYPE_NVRAM) {
 | 
			
		||||
-		brcmf_fw_request_nvram_done(NULL, fwctx);
 | 
			
		||||
-	} else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) {
 | 
			
		||||
+	if (!fw)
 | 
			
		||||
 		ret = -ENOENT;
 | 
			
		||||
+
 | 
			
		||||
+	switch (cur->type) {
 | 
			
		||||
+	case BRCMF_FW_TYPE_NVRAM:
 | 
			
		||||
+		ret = brcmf_fw_request_nvram_done(fw, fwctx);
 | 
			
		||||
+		break;
 | 
			
		||||
+	case BRCMF_FW_TYPE_BINARY:
 | 
			
		||||
+		cur->binary = fw;
 | 
			
		||||
+		break;
 | 
			
		||||
+	default:
 | 
			
		||||
+		/* something fishy here so bail out early */
 | 
			
		||||
+		brcmf_err("unknown fw type: %d\n", cur->type);
 | 
			
		||||
+		release_firmware(fw);
 | 
			
		||||
+		ret = -EINVAL;
 | 
			
		||||
 		goto fail;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	if (ret < 0 && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
 | 
			
		||||
+		goto fail;
 | 
			
		||||
+
 | 
			
		||||
 	do {
 | 
			
		||||
 		if (++fwctx->curpos == fwctx->req->n_items) {
 | 
			
		||||
 			ret = 0;
 | 
			
		||||
@ -23,66 +23,44 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
 | 
			
		||||
 }
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 | 
			
		||||
@@ -445,6 +445,7 @@ struct brcmf_fw {
 | 
			
		||||
 	u16 bus_nr;
 | 
			
		||||
 	void (*done)(struct device *dev, int err, const struct firmware *fw,
 | 
			
		||||
 		     void *nvram_image, u32 nvram_len);
 | 
			
		||||
@@ -441,6 +441,7 @@ struct brcmf_fw {
 | 
			
		||||
 	struct brcmf_fw_request *req;
 | 
			
		||||
 	u32 curpos;
 | 
			
		||||
 	void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
 | 
			
		||||
+	struct completion *completion;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
 | 
			
		||||
@@ -479,6 +480,8 @@ static void brcmf_fw_request_nvram_done(
 | 
			
		||||
 		goto fail;
 | 
			
		||||
 
 | 
			
		||||
 	fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length);
 | 
			
		||||
+	if (fwctx->completion)
 | 
			
		||||
+		complete(fwctx->completion);
 | 
			
		||||
 	kfree(fwctx);
 | 
			
		||||
 	return;
 | 
			
		||||
 
 | 
			
		||||
@@ -486,6 +489,8 @@ fail:
 | 
			
		||||
 	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
 | 
			
		||||
 	release_firmware(fwctx->code);
 | 
			
		||||
 	fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0);
 | 
			
		||||
+	if (fwctx->completion)
 | 
			
		||||
+		complete(fwctx->completion);
 | 
			
		||||
 	kfree(fwctx);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -517,6 +522,8 @@ fail:
 | 
			
		||||
 	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
 | 
			
		||||
 static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
 | 
			
		||||
@@ -589,6 +590,8 @@ fail:
 | 
			
		||||
 	fwctx->req = NULL;
 | 
			
		||||
 done:
 | 
			
		||||
 	fwctx->done(fwctx->dev, ret, fw, NULL, 0);
 | 
			
		||||
 	fwctx->done(fwctx->dev, ret, fwctx->req);
 | 
			
		||||
+	if (fwctx->completion)
 | 
			
		||||
+		complete(fwctx->completion);
 | 
			
		||||
 	kfree(fwctx);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -528,6 +535,8 @@ int brcmf_fw_get_firmwares_pcie(struct d
 | 
			
		||||
 				u16 domain_nr, u16 bus_nr)
 | 
			
		||||
@@ -612,6 +615,8 @@ int brcmf_fw_get_firmwares(struct device
 | 
			
		||||
 					 struct brcmf_fw_request *req))
 | 
			
		||||
 {
 | 
			
		||||
 	struct brcmf_fw *fwctx;
 | 
			
		||||
+	struct completion completion;
 | 
			
		||||
+	int err;
 | 
			
		||||
 
 | 
			
		||||
 	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
 | 
			
		||||
 	if (!fw_cb || !code)
 | 
			
		||||
@@ -548,9 +557,17 @@ int brcmf_fw_get_firmwares_pcie(struct d
 | 
			
		||||
 	fwctx->domain_nr = domain_nr;
 | 
			
		||||
 	fwctx->bus_nr = bus_nr;
 | 
			
		||||
 	if (!fw_cb)
 | 
			
		||||
@@ -628,7 +633,14 @@ int brcmf_fw_get_firmwares(struct device
 | 
			
		||||
 	fwctx->req = req;
 | 
			
		||||
 	fwctx->done = fw_cb;
 | 
			
		||||
 
 | 
			
		||||
-	return request_firmware_nowait(THIS_MODULE, true, code, dev,
 | 
			
		||||
+	init_completion(&completion);
 | 
			
		||||
+	fwctx->completion = &completion;
 | 
			
		||||
+
 | 
			
		||||
+	err = request_firmware_nowait(THIS_MODULE, true, code, dev,
 | 
			
		||||
 				       GFP_KERNEL, fwctx,
 | 
			
		||||
 				       brcmf_fw_request_code_done);
 | 
			
		||||
+	if (!err)
 | 
			
		||||
+		wait_for_completion_timeout(fwctx->completion,
 | 
			
		||||
+					    msecs_to_jiffies(5000));
 | 
			
		||||
 	brcmf_fw_request_next_item(fwctx, true);
 | 
			
		||||
+
 | 
			
		||||
+	wait_for_completion_timeout(fwctx->completion, msecs_to_jiffies(5000));
 | 
			
		||||
+	fwctx->completion = NULL;
 | 
			
		||||
+	return err;
 | 
			
		||||
+
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user