[openwrt/openwrt] mac80211: brcmfmac: enlarge caps buffer & final sdio restructuring

LEDE Commits lede-commits at lists.infradead.org
Thu Mar 1 09:30:52 PST 2018


rmilecki pushed a commit to openwrt/openwrt.git, branch master:
https://git.lede-project.org/8d78cccc6e06c0bdd15634de14855c7b7a86dcd6

commit 8d78cccc6e06c0bdd15634de14855c7b7a86dcd6
Author: Rafał Miłecki <rafal at milecki.pl>
AuthorDate: Thu Mar 1 18:22:51 2018 +0100

    mac80211: brcmfmac: enlarge caps buffer & final sdio restructuring
    
    Signed-off-by: Rafał Miłecki <rafal at milecki.pl>
---
 ...-enlarge-buffer-size-of-caps-to-512-bytes.patch |  44 +++
 ...4-v4.16-0001-brcmfmac-Remove-r-w-_sdreg32.patch | 227 ++++++++++++++
 ...ac-Rename-buscore-to-core-for-consistency.patch |  33 ++
 ...abilise-the-value-of-sbwad-in-use-for-som.patch |  82 +++++
 ...c-Correctly-handle-accesses-to-SDIO-func0.patch |  45 +++
 ...brcmfmac-Remove-func0-from-function-array.patch | 111 +++++++
 ...re-efficient-and-slightly-easier-to-read-.patch |  40 +++
 ...place-function-index-with-function-pointe.patch | 347 +++++++++++++++++++++
 ...6-0008-brcmfmac-Clean-up-interrupt-macros.patch |  53 ++++
 9 files changed, 982 insertions(+)

diff --git a/package/kernel/mac80211/patches/313-v4.16-0001-brcmfmac-enlarge-buffer-size-of-caps-to-512-bytes.patch b/package/kernel/mac80211/patches/313-v4.16-0001-brcmfmac-enlarge-buffer-size-of-caps-to-512-bytes.patch
new file mode 100644
index 0000000..731b7ed
--- /dev/null
+++ b/package/kernel/mac80211/patches/313-v4.16-0001-brcmfmac-enlarge-buffer-size-of-caps-to-512-bytes.patch
@@ -0,0 +1,44 @@
+From 7762bb134e3b40e8ee2611365775b7432190a9c7 Mon Sep 17 00:00:00 2001
+From: Wright Feng <wright.feng at cypress.com>
+Date: Mon, 11 Dec 2017 15:38:21 +0800
+Subject: [PATCH] brcmfmac: enlarge buffer size of caps to 512 bytes
+
+The buffer size of return of cap iovar is greater than 256 bytes in some
+firmwares. For instance, the return size of cap iovar is 271 bytes in 4373
+13.10.246.79 firmare. It makes feature capability parsing failed because
+caps buffer is default value.
+So we enlarge caps buffer size to 512 bytes and add the error print for
+cap iovar error.
+
+Signed-off-by: Wright Feng <wright.feng at cypress.com>
+Acked-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Kalle Valo <kvalo at codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+@@ -130,13 +130,19 @@ static void brcmf_feat_iovar_data_set(st
+ 	}
+ }
+ 
++#define MAX_CAPS_BUFFER_SIZE	512
+ static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp)
+ {
+-	char caps[256];
++	char caps[MAX_CAPS_BUFFER_SIZE];
+ 	enum brcmf_feat_id id;
+-	int i;
++	int i, err;
++
++	err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
++	if (err) {
++		brcmf_err("could not get firmware cap (%d)\n", err);
++		return;
++	}
+ 
+-	brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
+ 	brcmf_dbg(INFO, "[ %s]\n", caps);
+ 
+ 	for (i = 0; i < ARRAY_SIZE(brcmf_fwcap_map); i++) {
diff --git a/package/kernel/mac80211/patches/314-v4.16-0001-brcmfmac-Remove-r-w-_sdreg32.patch b/package/kernel/mac80211/patches/314-v4.16-0001-brcmfmac-Remove-r-w-_sdreg32.patch
new file mode 100644
index 0000000..291cd5d
--- /dev/null
+++ b/package/kernel/mac80211/patches/314-v4.16-0001-brcmfmac-Remove-r-w-_sdreg32.patch
@@ -0,0 +1,227 @@
+From 3d110df8f74781354051e4bb1e3e97fa368b2f80 Mon Sep 17 00:00:00 2001
+From: Ian Molton <ian at mnementh.co.uk>
+Date: Tue, 19 Dec 2017 13:47:07 +0100
+Subject: [PATCH] brcmfmac: Remove {r,w}_sdreg32
+
+Remove yet another IO function from the code and replace with one
+that already exists.
+
+Signed-off-by: Ian Molton <ian at mnementh.co.uk>
+Reviewed-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+[arend: keep address calculation, ie. (base + offset) in one line]
+Signed-off-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Kalle Valo <kvalo at codeaurora.org>
+---
+ .../wireless/broadcom/brcm80211/brcmfmac/sdio.c    | 88 +++++++++++-----------
+ 1 file changed, 42 insertions(+), 46 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -660,30 +660,6 @@ static bool data_ok(struct brcmf_sdio *b
+ 	       ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
+ }
+ 
+-/*
+- * Reads a register in the SDIO hardware block. This block occupies a series of
+- * adresses on the 32 bit backplane bus.
+- */
+-static int r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset)
+-{
+-	struct brcmf_core *core = bus->sdio_core;
+-	int ret;
+-
+-	*regvar = brcmf_sdiod_readl(bus->sdiodev, core->base + offset, &ret);
+-
+-	return ret;
+-}
+-
+-static int w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
+-{
+-	struct brcmf_core *core = bus->sdio_core;
+-	int ret;
+-
+-	brcmf_sdiod_writel(bus->sdiodev, core->base + reg_offset, regval, &ret);
+-
+-	return ret;
+-}
+-
+ static int
+ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
+ {
+@@ -1078,6 +1054,8 @@ static void brcmf_sdio_get_console_addr(
+ 
+ static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus)
+ {
++	struct brcmf_sdio_dev *sdiod = bus->sdiodev;
++	struct brcmf_core *core = bus->sdio_core;
+ 	u32 intstatus = 0;
+ 	u32 hmb_data;
+ 	u8 fcbits;
+@@ -1086,10 +1064,14 @@ static u32 brcmf_sdio_hostmail(struct br
+ 	brcmf_dbg(SDIO, "Enter\n");
+ 
+ 	/* Read mailbox data and ack that we did so */
+-	ret = r_sdreg32(bus, &hmb_data,	SD_REG(tohostmailboxdata));
++	hmb_data = brcmf_sdiod_readl(sdiod,
++				     core->base + SD_REG(tohostmailboxdata),
++				     &ret);
++
++	if (!ret)
++		brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailbox),
++				   SMB_INT_ACK, &ret);
+ 
+-	if (ret == 0)
+-		w_sdreg32(bus, SMB_INT_ACK, SD_REG(tosbmailbox));
+ 	bus->sdcnt.f1regdata += 2;
+ 
+ 	/* dongle indicates the firmware has halted/crashed */
+@@ -1163,6 +1145,8 @@ static u32 brcmf_sdio_hostmail(struct br
+ 
+ static void brcmf_sdio_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
+ {
++	struct brcmf_sdio_dev *sdiod = bus->sdiodev;
++	struct brcmf_core *core = bus->sdio_core;
+ 	uint retries = 0;
+ 	u16 lastrbc;
+ 	u8 hi, lo;
+@@ -1204,7 +1188,8 @@ static void brcmf_sdio_rxfail(struct brc
+ 
+ 	if (rtx) {
+ 		bus->sdcnt.rxrtx++;
+-		err = w_sdreg32(bus, SMB_NAK, SD_REG(tosbmailbox));
++		brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailbox),
++				   SMB_NAK, &err);
+ 
+ 		bus->sdcnt.f1regdata++;
+ 		if (err == 0)
+@@ -2291,6 +2276,7 @@ static uint brcmf_sdio_sendfromq(struct
+ {
+ 	struct sk_buff *pkt;
+ 	struct sk_buff_head pktq;
++	u32 intstat_addr = bus->sdio_core->base + SD_REG(intstatus);
+ 	u32 intstatus = 0;
+ 	int ret = 0, prec_out, i;
+ 	uint cnt = 0;
+@@ -2329,7 +2315,8 @@ static uint brcmf_sdio_sendfromq(struct
+ 		if (!bus->intr) {
+ 			/* Check device status, signal pending interrupt */
+ 			sdio_claim_host(bus->sdiodev->func[1]);
+-			ret = r_sdreg32(bus, &intstatus, SD_REG(intstatus));
++			intstatus = brcmf_sdiod_readl(bus->sdiodev,
++						      intstat_addr, &ret);
+ 			sdio_release_host(bus->sdiodev->func[1]);
+ 			bus->sdcnt.f2txdata++;
+ 			if (ret != 0)
+@@ -2413,12 +2400,13 @@ static int brcmf_sdio_tx_ctrlframe(struc
+ 
+ static void brcmf_sdio_bus_stop(struct device *dev)
+ {
+-	u32 local_hostintmask;
+-	u8 saveclk;
+-	int err;
+ 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ 	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+ 	struct brcmf_sdio *bus = sdiodev->bus;
++	struct brcmf_core *core = bus->sdio_core;
++	u32 local_hostintmask;
++	u8 saveclk;
++	int err;
+ 
+ 	brcmf_dbg(TRACE, "Enter\n");
+ 
+@@ -2435,7 +2423,9 @@ static void brcmf_sdio_bus_stop(struct d
+ 		brcmf_sdio_bus_sleep(bus, false, false);
+ 
+ 		/* Disable and clear interrupts at the chip level also */
+-		w_sdreg32(bus, 0, SD_REG(hostintmask));
++		brcmf_sdiod_writel(sdiodev, core->base + SD_REG(hostintmask),
++				   0, NULL);
++
+ 		local_hostintmask = bus->hostintmask;
+ 		bus->hostintmask = 0;
+ 
+@@ -2454,7 +2444,8 @@ static void brcmf_sdio_bus_stop(struct d
+ 		sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
+ 
+ 		/* Clear any pending interrupts now that F2 is disabled */
+-		w_sdreg32(bus, local_hostintmask, SD_REG(intstatus));
++		brcmf_sdiod_writel(sdiodev, core->base + SD_REG(intstatus),
++				   local_hostintmask, NULL);
+ 
+ 		sdio_release_host(sdiodev->func[1]);
+ 	}
+@@ -2521,7 +2512,9 @@ static int brcmf_sdio_intr_rstatus(struc
+ 
+ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
+ {
++	struct brcmf_sdio_dev *sdiod = bus->sdiodev;
+ 	u32 newstatus = 0;
++	u32 intstat_addr = bus->sdio_core->base + SD_REG(intstatus);
+ 	unsigned long intstatus;
+ 	uint txlimit = bus->txbound;	/* Tx frames to send before resched */
+ 	uint framecnt;			/* Temporary counter of tx/rx frames */
+@@ -2576,9 +2569,10 @@ static void brcmf_sdio_dpc(struct brcmf_
+ 	 */
+ 	if (intstatus & I_HMB_FC_CHANGE) {
+ 		intstatus &= ~I_HMB_FC_CHANGE;
+-		err = w_sdreg32(bus, I_HMB_FC_CHANGE, SD_REG(intstatus));
++		brcmf_sdiod_writel(sdiod, intstat_addr, I_HMB_FC_CHANGE, &err);
++
++		newstatus = brcmf_sdiod_readl(sdiod, intstat_addr, &err);
+ 
+-		err = r_sdreg32(bus, &newstatus, SD_REG(intstatus));
+ 		bus->sdcnt.f1regdata += 2;
+ 		atomic_set(&bus->fcstate,
+ 			   !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)));
+@@ -4017,22 +4011,21 @@ static void brcmf_sdio_firmware_callback
+ 					 const struct firmware *code,
+ 					 void *nvram, u32 nvram_len)
+ {
+-	struct brcmf_bus *bus_if;
+-	struct brcmf_sdio_dev *sdiodev;
+-	struct brcmf_sdio *bus;
++	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
++	struct brcmf_sdio *bus = sdiodev->bus;
++	struct brcmf_sdio_dev *sdiod = bus->sdiodev;
++	struct brcmf_core *core = bus->sdio_core;
+ 	u8 saveclk;
+ 
+ 	brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
+-	bus_if = dev_get_drvdata(dev);
+-	sdiodev = bus_if->bus_priv.sdio;
++
+ 	if (err)
+ 		goto fail;
+ 
+ 	if (!bus_if->drvr)
+ 		return;
+ 
+-	bus = sdiodev->bus;
+-
+ 	/* try to download image and nvram to the dongle */
+ 	bus->alp_only = true;
+ 	err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
+@@ -4063,8 +4056,9 @@ static void brcmf_sdio_firmware_callback
+ 	}
+ 
+ 	/* Enable function 2 (frame transfers) */
+-	w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
+-		  SD_REG(tosbmailboxdata));
++	brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata),
++			   SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL);
++
+ 	err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]);
+ 
+ 
+@@ -4074,7 +4068,9 @@ static void brcmf_sdio_firmware_callback
+ 	if (!err) {
+ 		/* Set up the interrupt mask and enable interrupts */
+ 		bus->hostintmask = HOSTINTMASK;
+-		w_sdreg32(bus, bus->hostintmask, SD_REG(hostintmask));
++		brcmf_sdiod_writel(sdiod, core->base + SD_REG(hostintmask),
++				   bus->hostintmask, NULL);
++
+ 
+ 		brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
+ 	} else {
diff --git a/package/kernel/mac80211/patches/314-v4.16-0002-brcmfmac-Rename-buscore-to-core-for-consistency.patch b/package/kernel/mac80211/patches/314-v4.16-0002-brcmfmac-Rename-buscore-to-core-for-consistency.patch
new file mode 100644
index 0000000..e9b5628
--- /dev/null
+++ b/package/kernel/mac80211/patches/314-v4.16-0002-brcmfmac-Rename-buscore-to-core-for-consistency.patch
@@ -0,0 +1,33 @@
+From dbda7dacb79a377e8ed9d38ce0e4a58b70aa9060 Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel at broadcom.com>
+Date: Tue, 19 Dec 2017 13:47:08 +0100
+Subject: [PATCH] brcmfmac: Rename buscore to core for consistency
+
+Avoid confusion with unrelated _buscore labels.
+
+Signed-off-by: Ian Molton <ian at mnementh.co.uk>
+Acked-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+[arend: only do the rename]
+Signed-off-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Kalle Valo <kvalo at codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -2485,12 +2485,12 @@ static inline void brcmf_sdio_clrintr(st
+ 
+ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
+ {
+-	struct brcmf_core *buscore = bus->sdio_core;
++	struct brcmf_core *core = bus->sdio_core;
+ 	u32 addr;
+ 	unsigned long val;
+ 	int ret;
+ 
+-	addr = buscore->base + SD_REG(intstatus);
++	addr = core->base + SD_REG(intstatus);
+ 
+ 	val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret);
+ 	bus->sdcnt.f1regdata++;
diff --git a/package/kernel/mac80211/patches/314-v4.16-0003-brcmfmac-stabilise-the-value-of-sbwad-in-use-for-som.patch b/package/kernel/mac80211/patches/314-v4.16-0003-brcmfmac-stabilise-the-value-of-sbwad-in-use-for-som.patch
new file mode 100644
index 0000000..3828c32
--- /dev/null
+++ b/package/kernel/mac80211/patches/314-v4.16-0003-brcmfmac-stabilise-the-value-of-sbwad-in-use-for-som.patch
@@ -0,0 +1,82 @@
+From 874bb8e49b7c6368f8ff9f2566c7bd06a2249be0 Mon Sep 17 00:00:00 2001
+From: Ian Molton <ian at mnementh.co.uk>
+Date: Tue, 19 Dec 2017 13:47:09 +0100
+Subject: [PATCH] brcmfmac: stabilise the value of ->sbwad in use for some xfer
+ routines.
+
+The IO functions operate within the Chipcommon IO window. Explicitly
+set this, rather than relying on the last initialisation IO access to
+leave it set to the right value by chance.
+
+Signed-off-by: Ian Molton <ian at mnementh.co.uk>
+Acked-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Kalle Valo <kvalo at codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 8 ++++----
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c   | 5 +++++
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h   | 1 +
+ 3 files changed, 10 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -529,7 +529,7 @@ int brcmf_sdiod_recv_buf(struct brcmf_sd
+ 
+ int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt)
+ {
+-	u32 addr = sdiodev->sbwad;
++	u32 addr = sdiodev->cc_core->base;
+ 	int err = 0;
+ 
+ 	brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len);
+@@ -552,7 +552,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_
+ {
+ 	struct sk_buff *glom_skb = NULL;
+ 	struct sk_buff *skb;
+-	u32 addr = sdiodev->sbwad;
++	u32 addr = sdiodev->cc_core->base;
+ 	int err = 0;
+ 
+ 	brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n",
+@@ -593,7 +593,7 @@ done:
+ int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
+ {
+ 	struct sk_buff *mypkt;
+-	u32 addr = sdiodev->sbwad;
++	u32 addr = sdiodev->cc_core->base;
+ 	int err;
+ 
+ 	mypkt = brcmu_pkt_buf_get_skb(nbytes);
+@@ -625,7 +625,7 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
+ 			 struct sk_buff_head *pktq)
+ {
+ 	struct sk_buff *skb;
+-	u32 addr = sdiodev->sbwad;
++	u32 addr = sdiodev->cc_core->base;
+ 	int err;
+ 
+ 	brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -3842,6 +3842,11 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
+ 	if (!bus->sdio_core)
+ 		goto fail;
+ 
++	/* Pick up the CHIPCOMMON core info struct, for bulk IO in bcmsdh.c */
++	sdiodev->cc_core = brcmf_chip_get_core(bus->ci, BCMA_CORE_CHIPCOMMON);
++	if (!sdiodev->cc_core)
++		goto fail;
++
+ 	sdiodev->settings = brcmf_get_module_param(sdiodev->dev,
+ 						   BRCMF_BUSTYPE_SDIO,
+ 						   bus->ci->chip,
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+@@ -178,6 +178,7 @@ struct brcmf_sdio_dev {
+ 	struct sdio_func *func[SDIO_MAX_FUNCS];
+ 	u8 num_funcs;			/* Supported funcs on client */
+ 	u32 sbwad;			/* Save backplane window address */
++	struct brcmf_core *cc_core;	/* chipcommon core info struct */
+ 	struct brcmf_sdio *bus;
+ 	struct device *dev;
+ 	struct brcmf_bus *bus_if;
diff --git a/package/kernel/mac80211/patches/314-v4.16-0004-brcmfmac-Correctly-handle-accesses-to-SDIO-func0.patch b/package/kernel/mac80211/patches/314-v4.16-0004-brcmfmac-Correctly-handle-accesses-to-SDIO-func0.patch
new file mode 100644
index 0000000..86b269a
--- /dev/null
+++ b/package/kernel/mac80211/patches/314-v4.16-0004-brcmfmac-Correctly-handle-accesses-to-SDIO-func0.patch
@@ -0,0 +1,45 @@
+From 508422f3695bf66f7b85fb4723c22f5166003ec6 Mon Sep 17 00:00:00 2001
+From: Ian Molton <ian at mnementh.co.uk>
+Date: Tue, 19 Dec 2017 13:47:10 +0100
+Subject: [PATCH] brcmfmac: Correctly handle accesses to SDIO func0
+
+Rather than workaround the restrictions on func0 addressing in the
+driver, set MMC_QUIRK_LENIENT_FN0
+
+Signed-off-by: Ian Molton <ian at mnementh.co.uk>
+Acked-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Kalle Valo <kvalo at codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 4 ++++
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h   | 4 ++--
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -995,6 +995,10 @@ static int brcmf_ops_sdio_probe(struct s
+ 	brcmf_dbg(SDIO, "Function#: %d\n", func->num);
+ 
+ 	dev = &func->dev;
++
++	/* Set MMC_QUIRK_LENIENT_FN0 for this card */
++	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
++
+ 	/* prohibit ACPI power management for this device */
+ 	brcmf_sdiod_acpi_set_power_manageable(dev, 0);
+ 
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+@@ -297,10 +297,10 @@ void brcmf_sdiod_intr_unregister(struct
+ /* SDIO device register access interface */
+ /* Accessors for SDIO Function 0 */
+ #define brcmf_sdiod_func0_rb(sdiodev, addr, r) \
+-	sdio_readb((sdiodev)->func[0], (addr), (r))
++	sdio_f0_readb((sdiodev)->func[0], (addr), (r))
+ 
+ #define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \
+-	sdio_writeb((sdiodev)->func[0], (v), (addr), (ret))
++	sdio_f0_writeb((sdiodev)->func[0], (v), (addr), (ret))
+ 
+ /* Accessors for SDIO Function 1 */
+ #define brcmf_sdiod_readb(sdiodev, addr, r) \
diff --git a/package/kernel/mac80211/patches/314-v4.16-0005-brcmfmac-Remove-func0-from-function-array.patch b/package/kernel/mac80211/patches/314-v4.16-0005-brcmfmac-Remove-func0-from-function-array.patch
new file mode 100644
index 0000000..715b865
--- /dev/null
+++ b/package/kernel/mac80211/patches/314-v4.16-0005-brcmfmac-Remove-func0-from-function-array.patch
@@ -0,0 +1,111 @@
+From 99d7b6fdfc8c24052c92c720330d31ca1332f996 Mon Sep 17 00:00:00 2001
+From: Ian Molton <ian at mnementh.co.uk>
+Date: Tue, 19 Dec 2017 13:47:11 +0100
+Subject: [PATCH] brcmfmac: Remove func0 from function array
+
+func0 is not provided by the mmc stack as a function when probing.
+Instead providing specific access functions to read/write it.
+
+This prepares for a patch to remove the actual array entry itself.
+
+Signed-off-by: Ian Molton <ian at mnementh.co.uk>
+Acked-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+[arend: rephrased the commit message]
+[arend: removed unrelated comment for which separate patch is warranted]
+Signed-off-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Kalle Valo <kvalo at codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c |  5 +----
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c   |  7 ++++---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h   | 13 ++++++-------
+ 3 files changed, 11 insertions(+), 14 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -1022,8 +1022,7 @@ static int brcmf_ops_sdio_probe(struct s
+ 	/* store refs to functions used. mmc_card does
+ 	 * not hold the F0 function pointer.
+ 	 */
+-	sdiodev->func[0] = kmemdup(func, sizeof(*func), GFP_KERNEL);
+-	sdiodev->func[0]->num = 0;
++	sdiodev->func[0] = NULL;
+ 	sdiodev->func[1] = func->card->sdio_func[0];
+ 	sdiodev->func[2] = func;
+ 
+@@ -1049,7 +1048,6 @@ static int brcmf_ops_sdio_probe(struct s
+ fail:
+ 	dev_set_drvdata(&func->dev, NULL);
+ 	dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
+-	kfree(sdiodev->func[0]);
+ 	kfree(sdiodev);
+ 	kfree(bus_if);
+ 	return err;
+@@ -1082,7 +1080,6 @@ static void brcmf_ops_sdio_remove(struct
+ 		dev_set_drvdata(&sdiodev->func[2]->dev, NULL);
+ 
+ 		kfree(bus_if);
+-		kfree(sdiodev->func[0]);
+ 		kfree(sdiodev);
+ 	}
+ 
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -3771,9 +3771,10 @@ static u32 brcmf_sdio_buscore_read32(voi
+ 	u32 val, rev;
+ 
+ 	val = brcmf_sdiod_readl(sdiodev, addr, NULL);
+-	if ((sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
+-	     sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
+-	    addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
++
++	if ((sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
++	     sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
++	     addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
+ 		rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
+ 		if (rev >= 2) {
+ 			val &= ~CID_ID_MASK;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+@@ -21,7 +21,9 @@
+ #include <linux/firmware.h>
+ #include "firmware.h"
+ 
+-#define SDIO_FUNC_0		0
++/* Maximum number of I/O funcs */
++#define NUM_SDIO_FUNCS	3
++
+ #define SDIO_FUNC_1		1
+ #define SDIO_FUNC_2		2
+ 
+@@ -39,9 +41,6 @@
+ #define INTR_STATUS_FUNC1	0x2
+ #define INTR_STATUS_FUNC2	0x4
+ 
+-/* Maximum number of I/O funcs */
+-#define SDIOD_MAX_IOFUNCS	7
+-
+ /* mask of register map */
+ #define REG_F0_REG_MASK		0x7FF
+ #define REG_F1_MISC_MASK	0x1FFFF
+@@ -175,7 +174,7 @@ struct brcmf_sdio;
+ struct brcmf_sdiod_freezer;
+ 
+ struct brcmf_sdio_dev {
+-	struct sdio_func *func[SDIO_MAX_FUNCS];
++	struct sdio_func *func[NUM_SDIO_FUNCS];
+ 	u8 num_funcs;			/* Supported funcs on client */
+ 	u32 sbwad;			/* Save backplane window address */
+ 	struct brcmf_core *cc_core;	/* chipcommon core info struct */
+@@ -297,10 +296,10 @@ void brcmf_sdiod_intr_unregister(struct
+ /* SDIO device register access interface */
+ /* Accessors for SDIO Function 0 */
+ #define brcmf_sdiod_func0_rb(sdiodev, addr, r) \
+-	sdio_f0_readb((sdiodev)->func[0], (addr), (r))
++	sdio_f0_readb((sdiodev)->func[1], (addr), (r))
+ 
+ #define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \
+-	sdio_f0_writeb((sdiodev)->func[0], (v), (addr), (ret))
++	sdio_f0_writeb((sdiodev)->func[1], (v), (addr), (ret))
+ 
+ /* Accessors for SDIO Function 1 */
+ #define brcmf_sdiod_readb(sdiodev, addr, r) \
diff --git a/package/kernel/mac80211/patches/314-v4.16-0006-brcmfmac-More-efficient-and-slightly-easier-to-read-.patch b/package/kernel/mac80211/patches/314-v4.16-0006-brcmfmac-More-efficient-and-slightly-easier-to-read-.patch
new file mode 100644
index 0000000..71e4894
--- /dev/null
+++ b/package/kernel/mac80211/patches/314-v4.16-0006-brcmfmac-More-efficient-and-slightly-easier-to-read-.patch
@@ -0,0 +1,40 @@
+From bcadaaa097c7ec103fe75f9da41f8fe52693b644 Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel at broadcom.com>
+Date: Tue, 19 Dec 2017 13:47:12 +0100
+Subject: [PATCH] brcmfmac: More efficient and slightly easier to read fixup
+ for 4339 chips
+
+Its more efficient to test the register we're interested in first,
+potentially avoiding two more comparisons, and therefore always avoiding
+one comparison per call on all other chips.
+
+Signed-off-by: Ian Molton <ian at mnementh.co.uk>
+[arend: fix some checkpatch warnings]
+Signed-off-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Kalle Valo <kvalo at codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -3772,15 +3772,16 @@ static u32 brcmf_sdio_buscore_read32(voi
+ 
+ 	val = brcmf_sdiod_readl(sdiodev, addr, NULL);
+ 
+-	if ((sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
+-	     sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
+-	     addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
++	if (addr == CORE_CC_REG(SI_ENUM_BASE, chipid) &&
++	    (sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339 ||
++	     sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) {
+ 		rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
+ 		if (rev >= 2) {
+ 			val &= ~CID_ID_MASK;
+ 			val |= BRCM_CC_4339_CHIP_ID;
+ 		}
+ 	}
++
+ 	return val;
+ }
+ 
diff --git a/package/kernel/mac80211/patches/314-v4.16-0007-brcmfmac-Replace-function-index-with-function-pointe.patch b/package/kernel/mac80211/patches/314-v4.16-0007-brcmfmac-Replace-function-index-with-function-pointe.patch
new file mode 100644
index 0000000..4354a70
--- /dev/null
+++ b/package/kernel/mac80211/patches/314-v4.16-0007-brcmfmac-Replace-function-index-with-function-pointe.patch
@@ -0,0 +1,347 @@
+From 00eb62cfc5f806b003fe5d54c8b5fe9a9665482f Mon Sep 17 00:00:00 2001
+From: Ian Molton <ian at mnementh.co.uk>
+Date: Tue, 19 Dec 2017 13:47:13 +0100
+Subject: [PATCH] brcmfmac: Replace function index with function pointer
+
+In preparation for removing the function array, remove all code that
+refers to function by index and replace with pointers to the function
+itself.
+
+Signed-off-by: Ian Molton <ian at mnementh.co.uk>
+Reviewed-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+[arend: replace BUG() with WARN() macro]
+Signed-off-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Kalle Valo <kvalo at codeaurora.org>
+---
+ .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c  | 85 ++++++++++++----------
+ .../wireless/broadcom/brcm80211/brcmfmac/sdio.c    | 15 ++--
+ .../wireless/broadcom/brcm80211/brcmfmac/sdio.h    |  6 +-
+ 3 files changed, 56 insertions(+), 50 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -291,8 +291,9 @@ out:
+ 		*ret = retval;
+ }
+ 
+-static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev, uint fn,
+-				 u32 addr, struct sk_buff *pkt)
++static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev,
++				 struct sdio_func *func, u32 addr,
++				 struct sk_buff *pkt)
+ {
+ 	unsigned int req_sz;
+ 	int err;
+@@ -301,13 +302,19 @@ static int brcmf_sdiod_buff_read(struct
+ 	req_sz = pkt->len + 3;
+ 	req_sz &= (uint)~3;
+ 
+-	if (fn == 1)
+-		err = sdio_memcpy_fromio(sdiodev->func[fn],
+-					 ((u8 *)(pkt->data)), addr, req_sz);
+-	else
+-		/* function 2 read is FIFO operation */
+-		err = sdio_readsb(sdiodev->func[fn],
+-				  ((u8 *)(pkt->data)), addr, req_sz);
++	switch (func->num) {
++	case 1:
++		err = sdio_memcpy_fromio(func, ((u8 *)(pkt->data)), addr,
++					 req_sz);
++		break;
++	case 2:
++		err = sdio_readsb(func, ((u8 *)(pkt->data)), addr, req_sz);
++		break;
++	default:
++		/* bail out as things are really fishy here */
++		WARN(1, "invalid sdio function number: %d\n", func->num);
++		err = -ENOMEDIUM;
++	};
+ 
+ 	if (err == -ENOMEDIUM)
+ 		brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
+@@ -315,8 +322,9 @@ static int brcmf_sdiod_buff_read(struct
+ 	return err;
+ }
+ 
+-static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev, uint fn,
+-				  u32 addr, struct sk_buff *pkt)
++static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev,
++				  struct sdio_func *func, u32 addr,
++				  struct sk_buff *pkt)
+ {
+ 	unsigned int req_sz;
+ 	int err;
+@@ -325,8 +333,7 @@ static int brcmf_sdiod_buff_write(struct
+ 	req_sz = pkt->len + 3;
+ 	req_sz &= (uint)~3;
+ 
+-	err = sdio_memcpy_toio(sdiodev->func[fn], addr,
+-			       ((u8 *)(pkt->data)), req_sz);
++	err = sdio_memcpy_toio(func, addr, ((u8 *)(pkt->data)), req_sz);
+ 
+ 	if (err == -ENOMEDIUM)
+ 		brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
+@@ -337,7 +344,7 @@ static int brcmf_sdiod_buff_write(struct
+ /**
+  * brcmf_sdiod_sglist_rw - SDIO interface function for block data access
+  * @sdiodev: brcmfmac sdio device
+- * @fn: SDIO function number
++ * @func: SDIO function
+  * @write: direction flag
+  * @addr: dongle memory address as source/destination
+  * @pkt: skb pointer
+@@ -346,7 +353,8 @@ static int brcmf_sdiod_buff_write(struct
+  * stack for block data access. It assumes that the skb passed down by the
+  * caller has already been padded and aligned.
+  */
+-static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
++static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev,
++				 struct sdio_func *func,
+ 				 bool write, u32 addr,
+ 				 struct sk_buff_head *pktlist)
+ {
+@@ -372,7 +380,7 @@ static int brcmf_sdiod_sglist_rw(struct
+ 		req_sz = 0;
+ 		skb_queue_walk(pktlist, pkt_next)
+ 			req_sz += pkt_next->len;
+-		req_sz = ALIGN(req_sz, sdiodev->func[fn]->cur_blksize);
++		req_sz = ALIGN(req_sz, func->cur_blksize);
+ 		while (req_sz > PAGE_SIZE) {
+ 			pkt_next = brcmu_pkt_buf_get_skb(PAGE_SIZE);
+ 			if (pkt_next == NULL) {
+@@ -391,7 +399,7 @@ static int brcmf_sdiod_sglist_rw(struct
+ 		target_list = &local_list;
+ 	}
+ 
+-	func_blk_sz = sdiodev->func[fn]->cur_blksize;
++	func_blk_sz = func->cur_blksize;
+ 	max_req_sz = sdiodev->max_request_size;
+ 	max_seg_cnt = min_t(unsigned short, sdiodev->max_segment_count,
+ 			    target_list->qlen);
+@@ -408,10 +416,10 @@ static int brcmf_sdiod_sglist_rw(struct
+ 	mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
+ 	mmc_cmd.opcode = SD_IO_RW_EXTENDED;
+ 	mmc_cmd.arg = write ? 1<<31 : 0;	/* write flag  */
+-	mmc_cmd.arg |= (fn & 0x7) << 28;	/* SDIO func num */
+-	mmc_cmd.arg |= 1<<27;			/* block mode */
++	mmc_cmd.arg |= (func->num & 0x7) << 28;	/* SDIO func num */
++	mmc_cmd.arg |= 1 << 27;			/* block mode */
+ 	/* for function 1 the addr will be incremented */
+-	mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0;
++	mmc_cmd.arg |= (func->num == 1) ? 1 << 26 : 0;
+ 	mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
+ 	mmc_req.cmd = &mmc_cmd;
+ 	mmc_req.data = &mmc_dat;
+@@ -457,11 +465,11 @@ static int brcmf_sdiod_sglist_rw(struct
+ 		mmc_cmd.arg |= (addr & 0x1FFFF) << 9;	/* address */
+ 		mmc_cmd.arg |= mmc_dat.blocks & 0x1FF;	/* block count */
+ 		/* incrementing addr for function 1 */
+-		if (fn == 1)
++		if (func->num == 1)
+ 			addr += req_sz;
+ 
+-		mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card);
+-		mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req);
++		mmc_set_data_timeout(&mmc_dat, func->card);
++		mmc_wait_for_req(func->card->host, &mmc_req);
+ 
+ 		ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
+ 		if (ret == -ENOMEDIUM) {
+@@ -541,7 +549,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
+ 	addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ 	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+ 
+-	err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, pkt);
++	err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr, pkt);
+ 
+ done:
+ 	return err;
+@@ -566,13 +574,13 @@ int brcmf_sdiod_recv_chain(struct brcmf_
+ 	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+ 
+ 	if (pktq->qlen == 1)
+-		err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
++		err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr,
+ 					    pktq->next);
+ 	else if (!sdiodev->sg_support) {
+ 		glom_skb = brcmu_pkt_buf_get_skb(totlen);
+ 		if (!glom_skb)
+ 			return -ENOMEM;
+-		err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
++		err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr,
+ 					    glom_skb);
+ 		if (err)
+ 			goto done;
+@@ -582,8 +590,8 @@ int brcmf_sdiod_recv_chain(struct brcmf_
+ 			skb_pull(glom_skb, skb->len);
+ 		}
+ 	} else
+-		err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, false, addr,
+-					    pktq);
++		err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], false,
++					    addr, pktq);
+ 
+ done:
+ 	brcmu_pkt_buf_free_skb(glom_skb);
+@@ -614,7 +622,8 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
+ 	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+ 
+ 	if (!err)
+-		err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt);
++		err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2], addr,
++					     mypkt);
+ 
+ 	brcmu_pkt_buf_free_skb(mypkt);
+ 
+@@ -639,14 +648,14 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
+ 
+ 	if (pktq->qlen == 1 || !sdiodev->sg_support) {
+ 		skb_queue_walk(pktq, skb) {
+-			err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2,
++			err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2],
+ 						     addr, skb);
+ 			if (err)
+ 				break;
+ 		}
+ 	} else {
+-		err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, true, addr,
+-					    pktq);
++		err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], true,
++					    addr, pktq);
+ 	}
+ 
+ 	return err;
+@@ -696,10 +705,10 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
+ 
+ 		if (write) {
+ 			memcpy(pkt->data, data, dsize);
+-			err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_1,
++			err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[1],
+ 						     sdaddr, pkt);
+ 		} else {
+-			err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_1,
++			err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[1],
+ 						    sdaddr, pkt);
+ 		}
+ 
+@@ -728,12 +737,12 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
+ 	return err;
+ }
+ 
+-int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn)
++int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, struct sdio_func *func)
+ {
+ 	brcmf_dbg(SDIO, "Enter\n");
+ 
+ 	/* Issue abort cmd52 command through F0 */
+-	brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, fn, NULL);
++	brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, func->num, NULL);
+ 
+ 	brcmf_dbg(SDIO, "Exit\n");
+ 	return 0;
+@@ -1105,7 +1114,7 @@ static int brcmf_ops_sdio_suspend(struct
+ 
+ 	func = container_of(dev, struct sdio_func, dev);
+ 	brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
+-	if (func->num != SDIO_FUNC_1)
++	if (func->num != 1)
+ 		return 0;
+ 
+ 
+@@ -1134,7 +1143,7 @@ static int brcmf_ops_sdio_resume(struct
+ 	struct sdio_func *func = container_of(dev, struct sdio_func, dev);
+ 
+ 	brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
+-	if (func->num != SDIO_FUNC_2)
++	if (func->num != 2)
+ 		return 0;
+ 
+ 	brcmf_sdiod_freezer_off(sdiodev);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -1157,7 +1157,7 @@ static void brcmf_sdio_rxfail(struct brc
+ 		  rtx ? ", send NAK" : "");
+ 
+ 	if (abort)
+-		brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
++		brcmf_sdiod_abort(bus->sdiodev, bus->sdiodev->func[2]);
+ 
+ 	brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM,
+ 			   &err);
+@@ -1209,7 +1209,7 @@ static void brcmf_sdio_txfail(struct brc
+ 	brcmf_err("sdio error, abort command and terminate frame\n");
+ 	bus->sdcnt.tx_sderrs++;
+ 
+-	brcmf_sdiod_abort(sdiodev, SDIO_FUNC_2);
++	brcmf_sdiod_abort(sdiodev, sdiodev->func[2]);
+ 	brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL);
+ 	bus->sdcnt.f1regdata++;
+ 
+@@ -2072,7 +2072,7 @@ static int brcmf_sdio_txpkt_prep_sg(stru
+ 	int ntail, ret;
+ 
+ 	sdiodev = bus->sdiodev;
+-	blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize;
++	blksize = sdiodev->func[2]->cur_blksize;
+ 	/* sg entry alignment should be a divisor of block size */
+ 	WARN_ON(blksize % bus->sgentry_align);
+ 
+@@ -2441,7 +2441,7 @@ static void brcmf_sdio_bus_stop(struct d
+ 
+ 		/* Turn off the bus (F2), free any pending packets */
+ 		brcmf_dbg(INTR, "disable SDIO interrupts\n");
+-		sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
++		sdio_disable_func(sdiodev->func[2]);
+ 
+ 		/* Clear any pending interrupts now that F2 is disabled */
+ 		brcmf_sdiod_writel(sdiodev, core->base + SD_REG(intstatus),
+@@ -4066,8 +4066,7 @@ static void brcmf_sdio_firmware_callback
+ 	brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata),
+ 			   SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL);
+ 
+-	err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]);
+-
++	err = sdio_enable_func(sdiodev->func[2]);
+ 
+ 	brcmf_dbg(INFO, "enable F2: err=%d\n", err);
+ 
+@@ -4082,7 +4081,7 @@ static void brcmf_sdio_firmware_callback
+ 		brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
+ 	} else {
+ 		/* Disable F2 again */
+-		sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
++		sdio_disable_func(sdiodev->func[2]);
+ 		goto release;
+ 	}
+ 
+@@ -4219,7 +4218,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
+ 	sdio_claim_host(bus->sdiodev->func[1]);
+ 
+ 	/* Disable F2 to clear any intermediate frame state on the dongle */
+-	sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
++	sdio_disable_func(bus->sdiodev->func[2]);
+ 
+ 	bus->rxflow = false;
+ 
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+@@ -45,9 +45,6 @@
+ #define REG_F0_REG_MASK		0x7FF
+ #define REG_F1_MISC_MASK	0x1FFFF
+ 
+-/* as of sdiod rev 0, supports 3 functions */
+-#define SBSDIO_NUM_FUNCTION		3
+-
+ /* function 0 vendor specific CCCR registers */
+ 
+ #define SDIO_CCCR_BRCM_CARDCAP			0xf0
+@@ -350,7 +347,8 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_
+ 		      u8 *data, uint size);
+ 
+ /* Issue an abort to the specified function */
+-int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn);
++int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, struct sdio_func *func);
++
+ void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
+ void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
+ 			      enum brcmf_sdiod_state state);
diff --git a/package/kernel/mac80211/patches/314-v4.16-0008-brcmfmac-Clean-up-interrupt-macros.patch b/package/kernel/mac80211/patches/314-v4.16-0008-brcmfmac-Clean-up-interrupt-macros.patch
new file mode 100644
index 0000000..d732c8e
--- /dev/null
+++ b/package/kernel/mac80211/patches/314-v4.16-0008-brcmfmac-Clean-up-interrupt-macros.patch
@@ -0,0 +1,53 @@
+From 9c3438ed215adba7025268ee1f0b6f7a2af12316 Mon Sep 17 00:00:00 2001
+From: Ian Molton <ian at mnementh.co.uk>
+Date: Tue, 19 Dec 2017 13:47:14 +0100
+Subject: [PATCH] brcmfmac: Clean up interrupt macros
+
+Make it more obvious that this code acually enables interrupts, and
+provide nice definitions for the bits in the register.
+
+Signed-off-by: Ian Molton <ian at mnementh.co.uk>
+Acked-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel at broadcom.com>
+Signed-off-by: Kalle Valo <kvalo at codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 3 ++-
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h   | 8 +++++---
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -149,7 +149,8 @@ int brcmf_sdiod_intr_register(struct brc
+ 
+ 		/* must configure SDIO_CCCR_IENx to enable irq */
+ 		data = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_IENx, &ret);
+-		data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
++		data |= SDIO_CCCR_IEN_FUNC1 | SDIO_CCCR_IEN_FUNC2 |
++			SDIO_CCCR_IEN_FUNC0;
+ 		brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret);
+ 
+ 		/* redirect, configure and enable io for interrupt signal */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+@@ -24,9 +24,6 @@
+ /* Maximum number of I/O funcs */
+ #define NUM_SDIO_FUNCS	3
+ 
+-#define SDIO_FUNC_1		1
+-#define SDIO_FUNC_2		2
+-
+ #define SDIOD_FBR_SIZE		0x100
+ 
+ /* io_en */
+@@ -52,6 +49,11 @@
+ #define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT	BIT(2)
+ #define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC	BIT(3)
+ 
++/* Interrupt enable bits for each function */
++#define SDIO_CCCR_IEN_FUNC0			BIT(0)
++#define SDIO_CCCR_IEN_FUNC1			BIT(1)
++#define SDIO_CCCR_IEN_FUNC2			BIT(2)
++
+ #define SDIO_CCCR_BRCM_CARDCTRL			0xf1
+ #define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET	BIT(1)
+ 



More information about the lede-commits mailing list