diff mbox series

[v3] brcmfmac: Add support for getting nvram contents from EFI variables

Message ID 20181010071620.14197-1-hdegoede@redhat.com (mailing list archive)
State Changes Requested
Delegated to: Kalle Valo
Headers show
Series [v3] brcmfmac: Add support for getting nvram contents from EFI variables | expand

Commit Message

Hans de Goede Oct. 10, 2018, 7:16 a.m. UTC
Various X86 laptops with a SDIO attached brcmfmac wifi chip, store the
nvram contents in a special EFI variable. This commit adds support for
getting nvram directly from this EFI variable, without the user needing
to manually copy it.

This makes Wifi / Bluetooth work out of the box on these devices instead of
requiring manual setup.

This has been tested on the following models: Acer Iconia Tab8 w1-810,
Acer One 10, Asus T100CHI, Asus T100HA, Asus T100TA, Asus T200TA and a
Lenovo Mixx 2 8.

Tested-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v3:
-Drop ccode fixup code (to be re-added in a separate commit), so that we
 can get the main EFI nvram support merged while we figure out the ccode
 handling

Changes in v2:
-Stop testing for asus in the dmi sys_vendor string at least the Toshiba
 Encore uses the nvram efivar variable too
-Use a table mapping the firmare name to the correct ccode value (XV / X2) to
 use for the worldwide regulatory domain for that firmware, assuming the
 firmware from linux-firmware is used. This fixes the T200TA and T100HA not
 seeing 5GHz networks
-Not only fixup ccode=ALL, but also ccode=XV, this is necessary since the
 T100HA nvram efivar containts ccode=XV, but the firmware from Linux firmware
 needs ccode=X2 for proper operation
---
 .../broadcom/brcm80211/brcmfmac/firmware.c    | 63 +++++++++++++++++--
 1 file changed, 57 insertions(+), 6 deletions(-)

Comments

kernel test robot Oct. 10, 2018, 5:43 p.m. UTC | #1
Hi Hans,

I love your patch! Yet something to improve:

[auto build test ERROR on wireless-drivers-next/master]
[also build test ERROR on v4.19-rc7 next-20181010]
[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/Hans-de-Goede/brcmfmac-Add-support-for-getting-nvram-contents-from-EFI-variables/20181010-211419
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master
config: i386-randconfig-c0-10102322 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c: In function 'brcmf_fw_request_nvram_done':
>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c:529:44: error: passing argument 1 of 'brcmf_fw_nvram_from_efi' from incompatible pointer type [-Werror=incompatible-pointer-types]
      else if ((data = brcmf_fw_nvram_from_efi(cur->path, &data_len)))
                                               ^~~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c:491:12: note: expected 'size_t * {aka unsigned int *}' but argument is of type 'const char *'
    static u8 *brcmf_fw_nvram_from_efi(size_t *data_len) { return NULL; }
               ^~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c:529:20: error: too many arguments to function 'brcmf_fw_nvram_from_efi'
      else if ((data = brcmf_fw_nvram_from_efi(cur->path, &data_len)))
                       ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c:491:12: note: declared here
    static u8 *brcmf_fw_nvram_from_efi(size_t *data_len) { return NULL; }
               ^~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/brcmf_fw_nvram_from_efi +529 drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c

   507	
   508	static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
   509	{
   510		struct brcmf_fw *fwctx = ctx;
   511		struct brcmf_fw_item *cur;
   512		bool free_bcm47xx_nvram = false;
   513		bool kfree_nvram = false;
   514		u32 nvram_length = 0;
   515		void *nvram = NULL;
   516		u8 *data = NULL;
   517		size_t data_len;
   518	
   519		brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
   520	
   521		cur = &fwctx->req->items[fwctx->curpos];
   522	
   523		if (fw && fw->data) {
   524			data = (u8 *)fw->data;
   525			data_len = fw->size;
   526		} else {
   527			if ((data = bcm47xx_nvram_get_contents(&data_len)))
   528				free_bcm47xx_nvram = true;
 > 529			else if ((data = brcmf_fw_nvram_from_efi(cur->path, &data_len)))
   530				kfree_nvram = true;
   531			else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL))
   532				goto fail;
   533		}
   534	
   535		if (data)
   536			nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
   537						     fwctx->req->domain_nr,
   538						     fwctx->req->bus_nr);
   539	
   540		if (free_bcm47xx_nvram)
   541			bcm47xx_nvram_release_contents(data);
   542		if (kfree_nvram)
   543			kfree(data);
   544	
   545		release_firmware(fw);
   546		if (!nvram && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
   547			goto fail;
   548	
   549		brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length);
   550		cur->nv_data.data = nvram;
   551		cur->nv_data.len = nvram_length;
   552		return 0;
   553	
   554	fail:
   555		return -ENOENT;
   556	}
   557	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox series

Patch

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index b38c4b40b235..a1dfe75c835f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -14,6 +14,7 @@ 
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <linux/efi.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/device.h>
@@ -445,6 +446,51 @@  struct brcmf_fw {
 
 static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
 
+#ifdef CONFIG_EFI
+static u8 *brcmf_fw_nvram_from_efi(const char *path, size_t *data_len_ret)
+{
+	const u16 name[] = { 'n', 'v', 'r', 'a', 'm', 0 };
+	struct efivar_entry *nvram_efivar;
+	unsigned long data_len = 0;
+	u8 *data = NULL;
+	int err;
+
+	nvram_efivar = kzalloc(sizeof(*nvram_efivar), GFP_KERNEL);
+	if (!nvram_efivar)
+		return NULL;
+
+	memcpy(&nvram_efivar->var.VariableName, name, sizeof(name));
+	nvram_efivar->var.VendorGuid = EFI_GUID(0x74b00bd9, 0x805a, 0x4d61,
+						0xb5, 0x1f, 0x43, 0x26,
+						0x81, 0x23, 0xd1, 0x13);
+
+	err = efivar_entry_size(nvram_efivar, &data_len);
+	if (err)
+		goto fail;
+
+	data = kmalloc(data_len, GFP_KERNEL);
+	if (!data)
+		goto fail;
+
+	err = efivar_entry_get(nvram_efivar, NULL, &data_len, data);
+	if (err)
+		goto fail;
+
+	brcmf_info("Using nvram EFI variable\n");
+
+	kfree(nvram_efivar);
+	*data_len_ret = data_len;
+	return data;
+
+fail:
+	kfree(data);
+	kfree(nvram_efivar);
+	return NULL;
+}
+#else
+static u8 *brcmf_fw_nvram_from_efi(size_t *data_len) { return NULL; }
+#endif
+
 static void brcmf_fw_free_request(struct brcmf_fw_request *req)
 {
 	struct brcmf_fw_item *item;
@@ -463,11 +509,12 @@  static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
 {
 	struct brcmf_fw *fwctx = ctx;
 	struct brcmf_fw_item *cur;
+	bool free_bcm47xx_nvram = false;
+	bool kfree_nvram = false;
 	u32 nvram_length = 0;
 	void *nvram = NULL;
 	u8 *data = NULL;
 	size_t data_len;
-	bool raw_nvram;
 
 	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
 
@@ -476,12 +523,13 @@  static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
 	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 && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
+		if ((data = bcm47xx_nvram_get_contents(&data_len)))
+			free_bcm47xx_nvram = true;
+		else if ((data = brcmf_fw_nvram_from_efi(cur->path, &data_len)))
+			kfree_nvram = true;
+		else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL))
 			goto fail;
-		raw_nvram = true;
 	}
 
 	if (data)
@@ -489,8 +537,11 @@  static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
 					     fwctx->req->domain_nr,
 					     fwctx->req->bus_nr);
 
-	if (raw_nvram)
+	if (free_bcm47xx_nvram)
 		bcm47xx_nvram_release_contents(data);
+	if (kfree_nvram)
+		kfree(data);
+
 	release_firmware(fw);
 	if (!nvram && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
 		goto fail;