diff options
author | Rafał Miłecki <zajec5@gmail.com> | 2015-04-24 10:45:33 +0000 |
---|---|---|
committer | Rafał Miłecki <zajec5@gmail.com> | 2015-04-24 10:45:33 +0000 |
commit | c1a7e135873d5def34db3b9393e18241a8cf3231 (patch) | |
tree | bb70f57269d74d2950c773774a931b202d361684 /package/kernel | |
parent | 33e597b2417e2bc12559333f1c5374778935a8e1 (diff) | |
download | upstream-c1a7e135873d5def34db3b9393e18241a8cf3231.tar.gz upstream-c1a7e135873d5def34db3b9393e18241a8cf3231.tar.bz2 upstream-c1a7e135873d5def34db3b9393e18241a8cf3231.zip |
mac80211: update brcmfmac to the wireless-drivers-next-for-davem-2015-04-09
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
SVN-Revision: 45576
Diffstat (limited to 'package/kernel')
19 files changed, 1850 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/335-brcmfmac-Fix-oops-when-SDIO-device-is-removed.patch b/package/kernel/mac80211/patches/335-brcmfmac-Fix-oops-when-SDIO-device-is-removed.patch new file mode 100644 index 0000000000..5e63a803b0 --- /dev/null +++ b/package/kernel/mac80211/patches/335-brcmfmac-Fix-oops-when-SDIO-device-is-removed.patch @@ -0,0 +1,44 @@ +From: Hante Meuleman <meuleman@broadcom.com> +Date: Fri, 6 Mar 2015 18:40:38 +0100 +Subject: [PATCH] brcmfmac: Fix oops when SDIO device is removed. + +On removal of SDIO card both functions of card will be getting +a remove call. When the first is hanging in ctrl frame xmit then +the second will cause oops. This patch fixes the xmit ctrl +handling in case of serious errors and also limits the handling +for remove to function 1 only. + +Reviewed-by: Arend Van Spriel <arend@broadcom.com> +Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> +Signed-off-by: Hante Meuleman <meuleman@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +@@ -1194,7 +1194,7 @@ static void brcmf_ops_sdio_remove(struct + brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); + brcmf_dbg(SDIO, "Function: %d\n", func->num); + +- if (func->num != 1 && func->num != 2) ++ if (func->num != 1) + return; + + bus_if = dev_get_drvdata(&func->dev); +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -2740,6 +2740,11 @@ static void brcmf_sdio_dpc(struct brcmf_ + if ((bus->sdiodev->state != BRCMF_SDIOD_DATA) || (err != 0)) { + brcmf_err("failed backplane access over SDIO, halting operation\n"); + atomic_set(&bus->intstatus, 0); ++ if (bus->ctrl_frame_stat) { ++ bus->ctrl_frame_err = -ENODEV; ++ bus->ctrl_frame_stat = false; ++ brcmf_sdio_wait_event_wakeup(bus); ++ } + } else if (atomic_read(&bus->intstatus) || + atomic_read(&bus->ipend) > 0 || + (!atomic_read(&bus->fcstate) && diff --git a/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch b/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch new file mode 100644 index 0000000000..201da75bfc --- /dev/null +++ b/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch @@ -0,0 +1,157 @@ +From: Hante Meuleman <meuleman@broadcom.com> +Date: Fri, 6 Mar 2015 18:40:39 +0100 +Subject: [PATCH] brcmfmac: Simplify watchdog sleep. + +The watchdog thread is used to put the SDIO bus to sleep when the +system is idling. This patch simplifies the way it is determined +when sleep can be entered. + +Reviewed-by: Arend Van Spriel <arend@broadcom.com> +Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> +Signed-off-by: Hante Meuleman <meuleman@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -485,10 +485,9 @@ struct brcmf_sdio { + #endif /* DEBUG */ + + uint clkstate; /* State of sd and backplane clock(s) */ +- bool activity; /* Activity flag for clock down */ + s32 idletime; /* Control for activity timeout */ +- s32 idlecount; /* Activity timeout counter */ +- s32 idleclock; /* How to set bus driver when idle */ ++ s32 idlecount; /* Activity timeout counter */ ++ s32 idleclock; /* How to set bus driver when idle */ + bool rxflow_mode; /* Rx flow control mode */ + bool rxflow; /* Is rx flow control on */ + bool alp_only; /* Don't use HT clock (ALP only) */ +@@ -511,6 +510,7 @@ struct brcmf_sdio { + struct workqueue_struct *brcmf_wq; + struct work_struct datawork; + atomic_t dpc_tskcnt; ++ atomic_t dpc_running; + + bool txoff; /* Transmit flow-controlled */ + struct brcmf_sdio_count sdcnt; +@@ -959,13 +959,8 @@ static int brcmf_sdio_clkctl(struct brcm + brcmf_dbg(SDIO, "Enter\n"); + + /* Early exit if we're already there */ +- if (bus->clkstate == target) { +- if (target == CLK_AVAIL) { +- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); +- bus->activity = true; +- } ++ if (bus->clkstate == target) + return 0; +- } + + switch (target) { + case CLK_AVAIL: +@@ -975,7 +970,6 @@ static int brcmf_sdio_clkctl(struct brcm + /* Now request HT Avail on the backplane */ + brcmf_sdio_htclk(bus, true, pendok); + brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); +- bus->activity = true; + break; + + case CLK_SDONLY: +@@ -1024,17 +1018,6 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio * + + /* Going to sleep */ + if (sleep) { +- /* Don't sleep if something is pending */ +- if (atomic_read(&bus->intstatus) || +- atomic_read(&bus->ipend) > 0 || +- bus->ctrl_frame_stat || +- (!atomic_read(&bus->fcstate) && +- brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && +- data_ok(bus))) { +- err = -EBUSY; +- goto done; +- } +- + clkcsr = brcmf_sdiod_regrb(bus->sdiodev, + SBSDIO_FUNC1_CHIPCLKCSR, + &err); +@@ -1045,11 +1028,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio * + SBSDIO_ALP_AVAIL_REQ, &err); + } + err = brcmf_sdio_kso_control(bus, false); +- /* disable watchdog */ +- if (!err) +- brcmf_sdio_wd_timer(bus, 0); + } else { +- bus->idlecount = 0; + err = brcmf_sdio_kso_control(bus, true); + } + if (err) { +@@ -3566,7 +3545,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b + queue_work(bus->brcmf_wq, &bus->datawork); + } + +-static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) ++static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) + { + brcmf_dbg(TIMER, "Enter\n"); + +@@ -3627,22 +3606,21 @@ static bool brcmf_sdio_bus_watchdog(stru + #endif /* DEBUG */ + + /* On idle timeout clear activity flag and/or turn off clock */ +- if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { +- if (++bus->idlecount >= bus->idletime) { ++ if ((atomic_read(&bus->dpc_tskcnt) == 0) && ++ (atomic_read(&bus->dpc_running) == 0) && ++ (bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { ++ bus->idlecount++; ++ if (bus->idlecount > bus->idletime) { ++ brcmf_dbg(SDIO, "idle\n"); ++ sdio_claim_host(bus->sdiodev->func[1]); ++ brcmf_sdio_wd_timer(bus, 0); + bus->idlecount = 0; +- if (bus->activity) { +- bus->activity = false; +- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); +- } else { +- brcmf_dbg(SDIO, "idle\n"); +- sdio_claim_host(bus->sdiodev->func[1]); +- brcmf_sdio_bus_sleep(bus, true, false); +- sdio_release_host(bus->sdiodev->func[1]); +- } ++ brcmf_sdio_bus_sleep(bus, true, false); ++ sdio_release_host(bus->sdiodev->func[1]); + } ++ } else { ++ bus->idlecount = 0; + } +- +- return (atomic_read(&bus->ipend) > 0); + } + + static void brcmf_sdio_dataworker(struct work_struct *work) +@@ -3651,8 +3629,11 @@ static void brcmf_sdio_dataworker(struct + datawork); + + while (atomic_read(&bus->dpc_tskcnt)) { ++ atomic_set(&bus->dpc_running, 1); + atomic_set(&bus->dpc_tskcnt, 0); + brcmf_sdio_dpc(bus); ++ bus->idlecount = 0; ++ atomic_set(&bus->dpc_running, 0); + } + if (brcmf_sdiod_freezing(bus->sdiodev)) { + brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN); +@@ -4154,6 +4135,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru + } + /* Initialize DPC thread */ + atomic_set(&bus->dpc_tskcnt, 0); ++ atomic_set(&bus->dpc_running, 0); + + /* Assign bus interface call back */ + bus->sdiodev->bus_if->dev = bus->sdiodev->dev; diff --git a/package/kernel/mac80211/patches/337-brcmfmac-Fix-possible-race-condition.patch b/package/kernel/mac80211/patches/337-brcmfmac-Fix-possible-race-condition.patch new file mode 100644 index 0000000000..3a2de7a944 --- /dev/null +++ b/package/kernel/mac80211/patches/337-brcmfmac-Fix-possible-race-condition.patch @@ -0,0 +1,83 @@ +From: Hante Meuleman <meuleman@broadcom.com> +Date: Fri, 6 Mar 2015 18:40:40 +0100 +Subject: [PATCH] brcmfmac: Fix possible race-condition. + +SDIO is using a "shared" variable to handoff ctl frames to DPC +and to see when they are done. In a timeout situation this can +lead to erroneous situation where DPC started to handle the ctl +frame while the timeout expired. This patch will fix this by +adding locking around the shared variable. + +Reviewed-by: Arend Van Spriel <arend@broadcom.com> +Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> +Signed-off-by: Hante Meuleman <meuleman@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -2700,11 +2700,13 @@ static void brcmf_sdio_dpc(struct brcmf_ + if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && + data_ok(bus)) { + sdio_claim_host(bus->sdiodev->func[1]); +- err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, +- bus->ctrl_frame_len); ++ if (bus->ctrl_frame_stat) { ++ err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, ++ bus->ctrl_frame_len); ++ bus->ctrl_frame_err = err; ++ bus->ctrl_frame_stat = false; ++ } + sdio_release_host(bus->sdiodev->func[1]); +- bus->ctrl_frame_err = err; +- bus->ctrl_frame_stat = false; + brcmf_sdio_wait_event_wakeup(bus); + } + /* Send queued frames (limit 1 if rx may still be pending) */ +@@ -2720,9 +2722,13 @@ static void brcmf_sdio_dpc(struct brcmf_ + brcmf_err("failed backplane access over SDIO, halting operation\n"); + atomic_set(&bus->intstatus, 0); + if (bus->ctrl_frame_stat) { +- bus->ctrl_frame_err = -ENODEV; +- bus->ctrl_frame_stat = false; +- brcmf_sdio_wait_event_wakeup(bus); ++ sdio_claim_host(bus->sdiodev->func[1]); ++ if (bus->ctrl_frame_stat) { ++ bus->ctrl_frame_err = -ENODEV; ++ bus->ctrl_frame_stat = false; ++ brcmf_sdio_wait_event_wakeup(bus); ++ } ++ sdio_release_host(bus->sdiodev->func[1]); + } + } else if (atomic_read(&bus->intstatus) || + atomic_read(&bus->ipend) > 0 || +@@ -2930,15 +2936,20 @@ brcmf_sdio_bus_txctl(struct device *dev, + brcmf_sdio_trigger_dpc(bus); + wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat, + msecs_to_jiffies(CTL_DONE_TIMEOUT)); +- +- if (!bus->ctrl_frame_stat) { ++ ret = 0; ++ if (bus->ctrl_frame_stat) { ++ sdio_claim_host(bus->sdiodev->func[1]); ++ if (bus->ctrl_frame_stat) { ++ brcmf_dbg(SDIO, "ctrl_frame timeout\n"); ++ bus->ctrl_frame_stat = false; ++ ret = -ETIMEDOUT; ++ } ++ sdio_release_host(bus->sdiodev->func[1]); ++ } ++ if (!ret) { + brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n", + bus->ctrl_frame_err); + ret = bus->ctrl_frame_err; +- } else { +- brcmf_dbg(SDIO, "ctrl_frame timeout\n"); +- bus->ctrl_frame_stat = false; +- ret = -ETIMEDOUT; + } + + if (ret) diff --git a/package/kernel/mac80211/patches/338-brcmfmac-Add-support-for-BCM4345-SDIO-chipset.patch b/package/kernel/mac80211/patches/338-brcmfmac-Add-support-for-BCM4345-SDIO-chipset.patch new file mode 100644 index 0000000000..c9eb9008a6 --- /dev/null +++ b/package/kernel/mac80211/patches/338-brcmfmac-Add-support-for-BCM4345-SDIO-chipset.patch @@ -0,0 +1,86 @@ +From: Syed Asifful Dayyan <syedd@broadcom.com> +Date: Fri, 6 Mar 2015 18:40:42 +0100 +Subject: [PATCH] brcmfmac: Add support for BCM4345 SDIO chipset. + +These changes add support for BCM4345 SDIO chipset. + +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Reviewed-by: Arend Van Spriel <arend@broadcom.com> +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> +Signed-off-by: Syed Asifful Dayyan <syedd@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +@@ -1096,6 +1096,7 @@ static const struct sdio_device_id brcmf + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339), ++ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354), + { /* end: all zeroes */ } + }; +--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +@@ -491,6 +491,10 @@ static void brcmf_chip_get_raminfo(struc + case BRCM_CC_43362_CHIP_ID: + ci->pub.ramsize = 0x3c000; + break; ++ case BRCM_CC_4345_CHIP_ID: ++ ci->pub.ramsize = 0xc8000; ++ ci->pub.rambase = 0x198000; ++ break; + case BRCM_CC_4339_CHIP_ID: + case BRCM_CC_4354_CHIP_ID: + case BRCM_CC_4356_CHIP_ID: +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -617,6 +617,8 @@ static const struct sdiod_drive_str sdio + #define BCM43362_NVRAM_NAME "brcm/brcmfmac43362-sdio.txt" + #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" + #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" ++#define BCM4345_FIRMWARE_NAME "brcm/brcmfmac4345-sdio.bin" ++#define BCM4345_NVRAM_NAME "brcm/brcmfmac4345-sdio.txt" + #define BCM4354_FIRMWARE_NAME "brcm/brcmfmac4354-sdio.bin" + #define BCM4354_NVRAM_NAME "brcm/brcmfmac4354-sdio.txt" + +@@ -640,6 +642,8 @@ MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME); + MODULE_FIRMWARE(BCM43362_NVRAM_NAME); + MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); + MODULE_FIRMWARE(BCM4339_NVRAM_NAME); ++MODULE_FIRMWARE(BCM4345_FIRMWARE_NAME); ++MODULE_FIRMWARE(BCM4345_NVRAM_NAME); + MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME); + MODULE_FIRMWARE(BCM4354_NVRAM_NAME); + +@@ -669,6 +673,7 @@ static const struct brcmf_firmware_names + { BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, + { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, + { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, ++ { BRCM_CC_4345_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4345) }, + { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } + }; + +--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +@@ -37,6 +37,7 @@ + #define BRCM_CC_43362_CHIP_ID 43362 + #define BRCM_CC_4335_CHIP_ID 0x4335 + #define BRCM_CC_4339_CHIP_ID 0x4339 ++#define BRCM_CC_4345_CHIP_ID 0x4345 + #define BRCM_CC_4354_CHIP_ID 0x4354 + #define BRCM_CC_4356_CHIP_ID 0x4356 + #define BRCM_CC_43566_CHIP_ID 43566 +--- a/include/linux/mmc/sdio_ids.h ++++ b/include/linux/mmc/sdio_ids.h +@@ -33,6 +33,7 @@ + #define SDIO_DEVICE_ID_BROADCOM_43341 0xa94d + #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335 + #define SDIO_DEVICE_ID_BROADCOM_43362 0xa962 ++#define SDIO_DEVICE_ID_BROADCOM_4345 0x4345 + #define SDIO_DEVICE_ID_BROADCOM_4354 0x4354 + + #define SDIO_VENDOR_ID_INTEL 0x0089 diff --git a/package/kernel/mac80211/patches/339-brcmfmac-remove-duplication-of-ramsize-info.patch b/package/kernel/mac80211/patches/339-brcmfmac-remove-duplication-of-ramsize-info.patch new file mode 100644 index 0000000000..7a688c4be6 --- /dev/null +++ b/package/kernel/mac80211/patches/339-brcmfmac-remove-duplication-of-ramsize-info.patch @@ -0,0 +1,48 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 11 Mar 2015 16:11:27 +0100 +Subject: [PATCH] brcmfmac: remove duplication of ramsize info + +Removing the ramsize from the brcmf_sdio structure to avoid +duplication. The information is available in brcmf_chip +structure. + +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -432,8 +432,6 @@ struct brcmf_sdio { + struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ + struct brcmf_chip *ci; /* Chip info struct */ + +- u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ +- + u32 hostintmask; /* Copy of Host Interrupt Mask */ + atomic_t intstatus; /* Intstatus bits (events) pending */ + atomic_t fcstate; /* State of dongle flow-control */ +@@ -1075,7 +1073,7 @@ static int brcmf_sdio_readshared(struct + struct sdpcm_shared_le sh_le; + __le32 addr_le; + +- shaddr = bus->ci->rambase + bus->ramsize - 4; ++ shaddr = bus->ci->rambase + bus->ci->ramsize - 4; + + /* + * Read last word in socram to determine +@@ -3871,13 +3869,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdi + drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH; + brcmf_sdio_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength); + +- /* Get info on the SOCRAM cores... */ +- bus->ramsize = bus->ci->ramsize; +- if (!(bus->ramsize)) { +- brcmf_err("failed to find SOCRAM memory!\n"); +- goto fail; +- } +- + /* Set card control so an SDIO card reset does a WLAN backplane reset */ + reg_val = brcmf_sdiod_regrb(bus->sdiodev, + SDIO_CCCR_BRCM_CARDCTRL, &err); diff --git a/package/kernel/mac80211/patches/340-brcmfmac-always-perform-cores-checks.patch b/package/kernel/mac80211/patches/340-brcmfmac-always-perform-cores-checks.patch new file mode 100644 index 0000000000..e2a2074247 --- /dev/null +++ b/package/kernel/mac80211/patches/340-brcmfmac-always-perform-cores-checks.patch @@ -0,0 +1,74 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 11 Mar 2015 16:11:28 +0100 +Subject: [PATCH] brcmfmac: always perform cores checks + +Instead of checking the cores in the chip only if CONFIG_BRCMDBG +is selected perform the check always and extend it with more sanity +checking. + +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +@@ -419,13 +419,13 @@ static struct brcmf_core *brcmf_chip_add + return &core->pub; + } + +-#ifdef DEBUG + /* safety check for chipinfo */ + static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) + { + struct brcmf_core_priv *core; + bool need_socram = false; + bool has_socram = false; ++ bool cpu_found = false; + int idx = 1; + + list_for_each_entry(core, &ci->cores, list) { +@@ -435,12 +435,14 @@ static int brcmf_chip_cores_check(struct + + switch (core->pub.id) { + case BCMA_CORE_ARM_CM3: ++ cpu_found = true; + need_socram = true; + break; + case BCMA_CORE_INTERNAL_MEM: + has_socram = true; + break; + case BCMA_CORE_ARM_CR4: ++ cpu_found = true; + if (ci->pub.rambase == 0) { + brcmf_err("RAM base not provided with ARM CR4 core\n"); + return -ENOMEM; +@@ -451,19 +453,21 @@ static int brcmf_chip_cores_check(struct + } + } + ++ if (!cpu_found) { ++ brcmf_err("CPU core not detected\n"); ++ return -ENXIO; ++ } + /* check RAM core presence for ARM CM3 core */ + if (need_socram && !has_socram) { + brcmf_err("RAM core not provided with ARM CM3 core\n"); + return -ENODEV; + } ++ if (!ci->pub.ramsize) { ++ brcmf_err("RAM size is undetermined\n"); ++ return -ENOMEM; ++ } + return 0; + } +-#else /* DEBUG */ +-static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) +-{ +- return 0; +-} +-#endif + + static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) + { diff --git a/package/kernel/mac80211/patches/341-brcmfmac-rename-chip-download-functions.patch b/package/kernel/mac80211/patches/341-brcmfmac-rename-chip-download-functions.patch new file mode 100644 index 0000000000..a272800577 --- /dev/null +++ b/package/kernel/mac80211/patches/341-brcmfmac-rename-chip-download-functions.patch @@ -0,0 +1,240 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 11 Mar 2015 16:11:29 +0100 +Subject: [PATCH] brcmfmac: rename chip download functions + +The functions brcmf_chip_[enter/exit]_download() are not exclusively +used for firmware download so rename these more appropriate. + +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +@@ -807,7 +807,7 @@ struct brcmf_chip *brcmf_chip_attach(voi + err = -EINVAL; + if (WARN_ON(!ops->prepare)) + err = -EINVAL; +- if (WARN_ON(!ops->exit_dl)) ++ if (WARN_ON(!ops->activate)) + err = -EINVAL; + if (err < 0) + return ERR_PTR(-EINVAL); +@@ -905,7 +905,7 @@ void brcmf_chip_resetcore(struct brcmf_c + } + + static void +-brcmf_chip_cm3_enterdl(struct brcmf_chip_priv *chip) ++brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip) + { + struct brcmf_core *core; + +@@ -919,7 +919,7 @@ brcmf_chip_cm3_enterdl(struct brcmf_chip + brcmf_chip_resetcore(core, 0, 0, 0); + } + +-static bool brcmf_chip_cm3_exitdl(struct brcmf_chip_priv *chip) ++static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip) + { + struct brcmf_core *core; + +@@ -929,7 +929,7 @@ static bool brcmf_chip_cm3_exitdl(struct + return false; + } + +- chip->ops->exit_dl(chip->ctx, &chip->pub, 0); ++ chip->ops->activate(chip->ctx, &chip->pub, 0); + + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3); + brcmf_chip_resetcore(core, 0, 0, 0); +@@ -938,7 +938,7 @@ static bool brcmf_chip_cm3_exitdl(struct + } + + static inline void +-brcmf_chip_cr4_enterdl(struct brcmf_chip_priv *chip) ++brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip) + { + struct brcmf_core *core; + +@@ -951,11 +951,11 @@ brcmf_chip_cr4_enterdl(struct brcmf_chip + D11_BCMA_IOCTL_PHYCLOCKEN); + } + +-static bool brcmf_chip_cr4_exitdl(struct brcmf_chip_priv *chip, u32 rstvec) ++static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec) + { + struct brcmf_core *core; + +- chip->ops->exit_dl(chip->ctx, &chip->pub, rstvec); ++ chip->ops->activate(chip->ctx, &chip->pub, rstvec); + + /* restore ARM */ + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4); +@@ -964,7 +964,7 @@ static bool brcmf_chip_cr4_exitdl(struct + return true; + } + +-void brcmf_chip_enter_download(struct brcmf_chip *pub) ++void brcmf_chip_set_passive(struct brcmf_chip *pub) + { + struct brcmf_chip_priv *chip; + struct brcmf_core *arm; +@@ -974,14 +974,14 @@ void brcmf_chip_enter_download(struct br + chip = container_of(pub, struct brcmf_chip_priv, pub); + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); + if (arm) { +- brcmf_chip_cr4_enterdl(chip); ++ brcmf_chip_cr4_set_passive(chip); + return; + } + +- brcmf_chip_cm3_enterdl(chip); ++ brcmf_chip_cm3_set_passive(chip); + } + +-bool brcmf_chip_exit_download(struct brcmf_chip *pub, u32 rstvec) ++bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec) + { + struct brcmf_chip_priv *chip; + struct brcmf_core *arm; +@@ -991,9 +991,9 @@ bool brcmf_chip_exit_download(struct brc + chip = container_of(pub, struct brcmf_chip_priv, pub); + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); + if (arm) +- return brcmf_chip_cr4_exitdl(chip, rstvec); ++ return brcmf_chip_cr4_set_active(chip, rstvec); + +- return brcmf_chip_cm3_exitdl(chip); ++ return brcmf_chip_cm3_set_active(chip); + } + + bool brcmf_chip_sr_capable(struct brcmf_chip *pub) +--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h ++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h +@@ -64,7 +64,7 @@ struct brcmf_core { + * @write32: write 32-bit value over bus. + * @prepare: prepare bus for core configuration. + * @setup: bus-specific core setup. +- * @exit_dl: exit download state. ++ * @active: chip becomes active. + * The callback should use the provided @rstvec when non-zero. + */ + struct brcmf_buscore_ops { +@@ -72,7 +72,7 @@ struct brcmf_buscore_ops { + void (*write32)(void *ctx, u32 addr, u32 value); + int (*prepare)(void *ctx); + int (*setup)(void *ctx, struct brcmf_chip *chip); +- void (*exit_dl)(void *ctx, struct brcmf_chip *chip, u32 rstvec); ++ void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec); + }; + + struct brcmf_chip *brcmf_chip_attach(void *ctx, +@@ -84,8 +84,8 @@ bool brcmf_chip_iscoreup(struct brcmf_co + void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset); + void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset, + u32 postreset); +-void brcmf_chip_enter_download(struct brcmf_chip *ci); +-bool brcmf_chip_exit_download(struct brcmf_chip *ci, u32 rstvec); ++void brcmf_chip_set_passive(struct brcmf_chip *ci); ++bool brcmf_chip_set_active(struct brcmf_chip *ci, u32 rstvec); + bool brcmf_chip_sr_capable(struct brcmf_chip *pub); + + #endif /* BRCMF_AXIDMP_H */ +--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +@@ -509,7 +509,7 @@ static void brcmf_pcie_attach(struct brc + + static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo) + { +- brcmf_chip_enter_download(devinfo->ci); ++ brcmf_chip_set_passive(devinfo->ci); + + if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) { + brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4); +@@ -536,7 +536,7 @@ static int brcmf_pcie_exit_download_stat + brcmf_chip_resetcore(core, 0, 0, 0); + } + +- return !brcmf_chip_exit_download(devinfo->ci, resetintr); ++ return !brcmf_chip_set_active(devinfo->ci, resetintr); + } + + +@@ -1566,8 +1566,8 @@ static int brcmf_pcie_buscoreprep(void * + } + + +-static void brcmf_pcie_buscore_exitdl(void *ctx, struct brcmf_chip *chip, +- u32 rstvec) ++static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip, ++ u32 rstvec) + { + struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; + +@@ -1577,7 +1577,7 @@ static void brcmf_pcie_buscore_exitdl(vo + + static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { + .prepare = brcmf_pcie_buscoreprep, +- .exit_dl = brcmf_pcie_buscore_exitdl, ++ .activate = brcmf_pcie_buscore_activate, + .read32 = brcmf_pcie_buscore_read32, + .write32 = brcmf_pcie_buscore_write32, + }; +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -3357,7 +3357,7 @@ static int brcmf_sdio_download_firmware( + brcmf_sdio_clkctl(bus, CLK_AVAIL, false); + + /* Keep arm in reset */ +- brcmf_chip_enter_download(bus->ci); ++ brcmf_chip_set_passive(bus->ci); + + rstvec = get_unaligned_le32(fw->data); + brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec); +@@ -3378,7 +3378,7 @@ static int brcmf_sdio_download_firmware( + } + + /* Take arm out of reset */ +- if (!brcmf_chip_exit_download(bus->ci, rstvec)) { ++ if (!brcmf_chip_set_active(bus->ci, rstvec)) { + brcmf_err("error getting out of ARM core reset\n"); + goto err; + } +@@ -3771,8 +3771,8 @@ static int brcmf_sdio_buscoreprep(void * + return 0; + } + +-static void brcmf_sdio_buscore_exitdl(void *ctx, struct brcmf_chip *chip, +- u32 rstvec) ++static void brcmf_sdio_buscore_activate(void *ctx, struct brcmf_chip *chip, ++ u32 rstvec) + { + struct brcmf_sdio_dev *sdiodev = ctx; + struct brcmf_core *core; +@@ -3815,7 +3815,7 @@ static void brcmf_sdio_buscore_write32(v + + static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = { + .prepare = brcmf_sdio_buscoreprep, +- .exit_dl = brcmf_sdio_buscore_exitdl, ++ .activate = brcmf_sdio_buscore_activate, + .read32 = brcmf_sdio_buscore_read32, + .write32 = brcmf_sdio_buscore_write32, + }; +@@ -4239,12 +4239,11 @@ void brcmf_sdio_remove(struct brcmf_sdio + sdio_claim_host(bus->sdiodev->func[1]); + brcmf_sdio_clkctl(bus, CLK_AVAIL, false); + /* Leave the device in state where it is +- * 'quiet'. This is done by putting it in +- * download_state which essentially resets +- * all necessary cores. ++ * 'passive'. This is done by resetting all ++ * necessary cores. + */ + msleep(20); +- brcmf_chip_enter_download(bus->ci); ++ brcmf_chip_set_passive(bus->ci); + brcmf_sdio_clkctl(bus, CLK_NONE, false); + sdio_release_host(bus->sdiodev->func[1]); + } diff --git a/package/kernel/mac80211/patches/342-brcmfmac-assure-device-is-ready-for-download-after-b.patch b/package/kernel/mac80211/patches/342-brcmfmac-assure-device-is-ready-for-download-after-b.patch new file mode 100644 index 0000000000..6b1dd8144f --- /dev/null +++ b/package/kernel/mac80211/patches/342-brcmfmac-assure-device-is-ready-for-download-after-b.patch @@ -0,0 +1,61 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 11 Mar 2015 16:11:30 +0100 +Subject: [PATCH] brcmfmac: assure device is ready for download after + brcmf_chip_attach() + +Make the brcmf_chip_attach() function responsible for putting the +device in a state where it is accessible for firmware download. + +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +@@ -786,12 +786,6 @@ static int brcmf_chip_setup(struct brcmf + if (chip->ops->setup) + ret = chip->ops->setup(chip->ctx, pub); + +- /* +- * Make sure any on-chip ARM is off (in case strapping is wrong), +- * or downloaded code was already running. +- */ +- brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3); +- brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4); + return ret; + } + +@@ -833,6 +827,8 @@ struct brcmf_chip *brcmf_chip_attach(voi + if (err < 0) + goto fail; + ++ /* assure chip is passive for download */ ++ brcmf_chip_set_passive(&chip->pub); + return &chip->pub; + + fail: +--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +@@ -509,8 +509,6 @@ static void brcmf_pcie_attach(struct brc + + static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo) + { +- brcmf_chip_set_passive(devinfo->ci); +- + if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) { + brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4); + brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX, +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -3356,9 +3356,6 @@ static int brcmf_sdio_download_firmware( + sdio_claim_host(bus->sdiodev->func[1]); + brcmf_sdio_clkctl(bus, CLK_AVAIL, false); + +- /* Keep arm in reset */ +- brcmf_chip_set_passive(bus->ci); +- + rstvec = get_unaligned_le32(fw->data); + brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec); + diff --git a/package/kernel/mac80211/patches/343-brcmfmac-extract-ram-size-info-from-internal-memory-.patch b/package/kernel/mac80211/patches/343-brcmfmac-extract-ram-size-info-from-internal-memory-.patch new file mode 100644 index 0000000000..bcc2ed4868 --- /dev/null +++ b/package/kernel/mac80211/patches/343-brcmfmac-extract-ram-size-info-from-internal-memory-.patch @@ -0,0 +1,367 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 11 Mar 2015 16:11:31 +0100 +Subject: [PATCH] brcmfmac: extract ram size info from internal memory + registers + +Instead of hard-coded memory sizes it is possible to obtain that +information from the internal memory registers. + +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +@@ -100,9 +100,6 @@ + #define BCM4329_CORE_SOCRAM_BASE 0x18003000 + /* ARM Cortex M3 core, ID 0x82a */ + #define BCM4329_CORE_ARM_BASE 0x18002000 +-#define BCM4329_RAMSIZE 0x48000 +-/* bcm43143 */ +-#define BCM43143_RAMSIZE 0x70000 + + #define CORE_SB(base, field) \ + (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) +@@ -150,6 +147,78 @@ struct sbconfig { + u32 sbidhigh; /* identification */ + }; + ++/* bankidx and bankinfo reg defines corerev >= 8 */ ++#define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000 ++#define SOCRAM_BANKINFO_SZMASK 0x0000007f ++#define SOCRAM_BANKIDX_ROM_MASK 0x00000100 ++ ++#define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8 ++/* socram bankinfo memtype */ ++#define SOCRAM_MEMTYPE_RAM 0 ++#define SOCRAM_MEMTYPE_R0M 1 ++#define SOCRAM_MEMTYPE_DEVRAM 2 ++ ++#define SOCRAM_BANKINFO_SZBASE 8192 ++#define SRCI_LSS_MASK 0x00f00000 ++#define SRCI_LSS_SHIFT 20 ++#define SRCI_SRNB_MASK 0xf0 ++#define SRCI_SRNB_SHIFT 4 ++#define SRCI_SRBSZ_MASK 0xf ++#define SRCI_SRBSZ_SHIFT 0 ++#define SR_BSZ_BASE 14 ++ ++struct sbsocramregs { ++ u32 coreinfo; ++ u32 bwalloc; ++ u32 extracoreinfo; ++ u32 biststat; ++ u32 bankidx; ++ u32 standbyctrl; ++ ++ u32 errlogstatus; /* rev 6 */ ++ u32 errlogaddr; /* rev 6 */ ++ /* used for patching rev 3 & 5 */ ++ u32 cambankidx; ++ u32 cambankstandbyctrl; ++ u32 cambankpatchctrl; ++ u32 cambankpatchtblbaseaddr; ++ u32 cambankcmdreg; ++ u32 cambankdatareg; ++ u32 cambankmaskreg; ++ u32 PAD[1]; ++ u32 bankinfo; /* corev 8 */ ++ u32 bankpda; ++ u32 PAD[14]; ++ u32 extmemconfig; ++ u32 extmemparitycsr; ++ u32 extmemparityerrdata; ++ u32 extmemparityerrcnt; ++ u32 extmemwrctrlandsize; ++ u32 PAD[84]; ++ u32 workaround; ++ u32 pwrctl; /* corerev >= 2 */ ++ u32 PAD[133]; ++ u32 sr_control; /* corerev >= 15 */ ++ u32 sr_status; /* corerev >= 15 */ ++ u32 sr_address; /* corerev >= 15 */ ++ u32 sr_data; /* corerev >= 15 */ ++}; ++ ++#define SOCRAMREGOFFS(_f) offsetof(struct sbsocramregs, _f) ++ ++#define ARMCR4_CAP (0x04) ++#define ARMCR4_BANKIDX (0x40) ++#define ARMCR4_BANKINFO (0x44) ++#define ARMCR4_BANKPDA (0x4C) ++ ++#define ARMCR4_TCBBNB_MASK 0xf0 ++#define ARMCR4_TCBBNB_SHIFT 4 ++#define ARMCR4_TCBANB_MASK 0xf ++#define ARMCR4_TCBANB_SHIFT 0 ++ ++#define ARMCR4_BSZ_MASK 0x3f ++#define ARMCR4_BSZ_MULT 8192 ++ + struct brcmf_core_priv { + struct brcmf_core pub; + u32 wrapbase; +@@ -443,10 +512,6 @@ static int brcmf_chip_cores_check(struct + break; + case BCMA_CORE_ARM_CR4: + cpu_found = true; +- if (ci->pub.rambase == 0) { +- brcmf_err("RAM base not provided with ARM CR4 core\n"); +- return -ENOMEM; +- } + break; + default: + break; +@@ -462,60 +527,160 @@ static int brcmf_chip_cores_check(struct + brcmf_err("RAM core not provided with ARM CM3 core\n"); + return -ENODEV; + } +- if (!ci->pub.ramsize) { +- brcmf_err("RAM size is undetermined\n"); +- return -ENOMEM; +- } + return 0; + } + +-static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) ++static u32 brcmf_chip_core_read32(struct brcmf_core_priv *core, u16 reg) + { +- switch (ci->pub.chip) { +- case BRCM_CC_4329_CHIP_ID: +- ci->pub.ramsize = BCM4329_RAMSIZE; +- break; +- case BRCM_CC_43143_CHIP_ID: +- ci->pub.ramsize = BCM43143_RAMSIZE; +- break; +- case BRCM_CC_43241_CHIP_ID: +- ci->pub.ramsize = 0x90000; +- break; +- case BRCM_CC_4330_CHIP_ID: +- ci->pub.ramsize = 0x48000; +- break; ++ return core->chip->ops->read32(core->chip->ctx, core->pub.base + reg); ++} ++ ++static void brcmf_chip_core_write32(struct brcmf_core_priv *core, ++ u16 reg, u32 val) ++{ ++ core->chip->ops->write32(core->chip->ctx, core->pub.base + reg, val); ++} ++ ++static bool brcmf_chip_socram_banksize(struct brcmf_core_priv *core, u8 idx, ++ u32 *banksize) ++{ ++ u32 bankinfo; ++ u32 bankidx = (SOCRAM_MEMTYPE_RAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); ++ ++ bankidx |= idx; ++ brcmf_chip_core_write32(core, SOCRAMREGOFFS(bankidx), bankidx); ++ bankinfo = brcmf_chip_core_read32(core, SOCRAMREGOFFS(bankinfo)); ++ *banksize = (bankinfo & SOCRAM_BANKINFO_SZMASK) + 1; ++ *banksize *= SOCRAM_BANKINFO_SZBASE; ++ return !!(bankinfo & SOCRAM_BANKINFO_RETNTRAM_MASK); ++} ++ ++static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize, ++ u32 *srsize) ++{ ++ u32 coreinfo; ++ uint nb, banksize, lss; ++ bool retent; ++ int i; ++ ++ *ramsize = 0; ++ *srsize = 0; ++ ++ if (WARN_ON(sr->pub.rev < 4)) ++ return; ++ ++ if (!brcmf_chip_iscoreup(&sr->pub)) ++ brcmf_chip_resetcore(&sr->pub, 0, 0, 0); ++ ++ /* Get info for determining size */ ++ coreinfo = brcmf_chip_core_read32(sr, SOCRAMREGOFFS(coreinfo)); ++ nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; ++ ++ if ((sr->pub.rev <= 7) || (sr->pub.rev == 12)) { ++ banksize = (coreinfo & SRCI_SRBSZ_MASK); ++ lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; ++ if (lss != 0) ++ nb--; ++ *ramsize = nb * (1 << (banksize + SR_BSZ_BASE)); ++ if (lss != 0) ++ *ramsize += (1 << ((lss - 1) + SR_BSZ_BASE)); ++ } else { ++ nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; ++ for (i = 0; i < nb; i++) { ++ retent = brcmf_chip_socram_banksize(sr, i, &banksize); ++ *ramsize += banksize; ++ if (retent) ++ *srsize += banksize; ++ } ++ } ++ ++ /* hardcoded save&restore memory sizes */ ++ switch (sr->chip->pub.chip) { + case BRCM_CC_4334_CHIP_ID: +- case BRCM_CC_43340_CHIP_ID: +- ci->pub.ramsize = 0x80000; ++ if (sr->chip->pub.chiprev < 2) ++ *srsize = (32 * 1024); + break; +- case BRCM_CC_4335_CHIP_ID: +- ci->pub.ramsize = 0xc0000; +- ci->pub.rambase = 0x180000; +- break; +- case BRCM_CC_43362_CHIP_ID: +- ci->pub.ramsize = 0x3c000; ++ default: + break; ++ } ++} ++ ++/** Return the TCM-RAM size of the ARMCR4 core. */ ++static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4) ++{ ++ u32 corecap; ++ u32 memsize = 0; ++ u32 nab; ++ u32 nbb; ++ u32 totb; ++ u32 bxinfo; ++ u32 idx; ++ ++ corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP); ++ ++ nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT; ++ nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT; ++ totb = nab + nbb; ++ ++ for (idx = 0; idx < totb; idx++) { ++ brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx); ++ bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO); ++ memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT; ++ } ++ ++ return memsize; ++} ++ ++static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) ++{ ++ switch (ci->pub.chip) { + case BRCM_CC_4345_CHIP_ID: +- ci->pub.ramsize = 0xc8000; +- ci->pub.rambase = 0x198000; +- break; ++ return 0x198000; ++ case BRCM_CC_4335_CHIP_ID: + case BRCM_CC_4339_CHIP_ID: + case BRCM_CC_4354_CHIP_ID: + case BRCM_CC_4356_CHIP_ID: + case BRCM_CC_43567_CHIP_ID: + case BRCM_CC_43569_CHIP_ID: + case BRCM_CC_43570_CHIP_ID: +- ci->pub.ramsize = 0xc0000; +- ci->pub.rambase = 0x180000; +- break; + case BRCM_CC_43602_CHIP_ID: +- ci->pub.ramsize = 0xf0000; +- ci->pub.rambase = 0x180000; +- break; ++ return 0x180000; + default: + brcmf_err("unknown chip: %s\n", ci->pub.name); + break; + } ++ return 0; ++} ++ ++static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) ++{ ++ struct brcmf_core_priv *mem_core; ++ struct brcmf_core *mem; ++ ++ mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_ARM_CR4); ++ if (mem) { ++ mem_core = container_of(mem, struct brcmf_core_priv, pub); ++ ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core); ++ ci->pub.rambase = brcmf_chip_tcm_rambase(ci); ++ if (!ci->pub.rambase) { ++ brcmf_err("RAM base not provided with ARM CR4 core\n"); ++ return -EINVAL; ++ } ++ } else { ++ mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_INTERNAL_MEM); ++ mem_core = container_of(mem, struct brcmf_core_priv, pub); ++ brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize, ++ &ci->pub.srsize); ++ } ++ brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n", ++ ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize, ++ ci->pub.srsize, ci->pub.srsize); ++ ++ if (!ci->pub.ramsize) { ++ brcmf_err("RAM size is undetermined\n"); ++ return -ENOMEM; ++ } ++ return 0; + } + + static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr, +@@ -668,6 +833,7 @@ static int brcmf_chip_recognition(struct + struct brcmf_core *core; + u32 regdata; + u32 socitype; ++ int ret; + + /* Get CC core rev + * Chipid is assume to be at offset 0 from SI_ENUM_BASE +@@ -720,9 +886,13 @@ static int brcmf_chip_recognition(struct + return -ENODEV; + } + +- brcmf_chip_get_raminfo(ci); +- +- return brcmf_chip_cores_check(ci); ++ ret = brcmf_chip_cores_check(ci); ++ if (ret) ++ return ret; ++ ++ /* assure chip is passive for core access */ ++ brcmf_chip_set_passive(&ci->pub); ++ return brcmf_chip_get_raminfo(ci); + } + + static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id) +@@ -827,8 +997,6 @@ struct brcmf_chip *brcmf_chip_attach(voi + if (err < 0) + goto fail; + +- /* assure chip is passive for download */ +- brcmf_chip_set_passive(&chip->pub); + return &chip->pub; + + fail: +--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h ++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h +@@ -30,7 +30,8 @@ + * @pmucaps: PMU capabilities. + * @pmurev: PMU revision. + * @rambase: RAM base address (only applicable for ARM CR4 chips). +- * @ramsize: amount of RAM on chip. ++ * @ramsize: amount of RAM on chip including retention. ++ * @srsize: amount of retention RAM on chip. + * @name: string representation of the chip identifier. + */ + struct brcmf_chip { +@@ -41,6 +42,7 @@ struct brcmf_chip { + u32 pmurev; + u32 rambase; + u32 ramsize; ++ u32 srsize; + char name[8]; + }; + diff --git a/package/kernel/mac80211/patches/344-brcmfmac-take-save-restore-memory-into-account-for-S.patch b/package/kernel/mac80211/patches/344-brcmfmac-take-save-restore-memory-into-account-for-S.patch new file mode 100644 index 0000000000..69618a7aa7 --- /dev/null +++ b/package/kernel/mac80211/patches/344-brcmfmac-take-save-restore-memory-into-account-for-S.patch @@ -0,0 +1,96 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 11 Mar 2015 16:11:32 +0100 +Subject: [PATCH] brcmfmac: take save&restore memory into account for SDIO + shared info + +The firmware provides pointer to SDIO shared information at end of +RAM during firmware initialization. End of RAM is obviously determined +by the actual ram size, but part of that may be used for save&restore +memory. In that case another location in RAM will hold the pointer. + +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -1067,44 +1067,47 @@ static inline bool brcmf_sdio_valid_shar + static int brcmf_sdio_readshared(struct brcmf_sdio *bus, + struct sdpcm_shared *sh) + { +- u32 addr; ++ u32 addr = 0; + int rv; + u32 shaddr = 0; + struct sdpcm_shared_le sh_le; + __le32 addr_le; + +- shaddr = bus->ci->rambase + bus->ci->ramsize - 4; ++ sdio_claim_host(bus->sdiodev->func[1]); ++ brcmf_sdio_bus_sleep(bus, false, false); + + /* + * Read last word in socram to determine + * address of sdpcm_shared structure + */ +- sdio_claim_host(bus->sdiodev->func[1]); +- brcmf_sdio_bus_sleep(bus, false, false); +- rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4); +- sdio_release_host(bus->sdiodev->func[1]); ++ shaddr = bus->ci->rambase + bus->ci->ramsize - 4; ++ if (!bus->ci->rambase && brcmf_chip_sr_capable(bus->ci)) ++ shaddr -= bus->ci->srsize; ++ rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, ++ (u8 *)&addr_le, 4); + if (rv < 0) +- return rv; +- +- addr = le32_to_cpu(addr_le); +- +- brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr); ++ goto fail; + + /* + * Check if addr is valid. + * NVRAM length at the end of memory should have been overwritten. + */ ++ addr = le32_to_cpu(addr_le); + if (!brcmf_sdio_valid_shared_address(addr)) { +- brcmf_err("invalid sdpcm_shared address 0x%08X\n", +- addr); +- return -EINVAL; ++ brcmf_err("invalid sdpcm_shared address 0x%08X\n", addr); ++ rv = -EINVAL; ++ goto fail; + } + ++ brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr); ++ + /* Read hndrte_shared structure */ + rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le, + sizeof(struct sdpcm_shared_le)); + if (rv < 0) +- return rv; ++ goto fail; ++ ++ sdio_release_host(bus->sdiodev->func[1]); + + /* Endianness */ + sh->flags = le32_to_cpu(sh_le.flags); +@@ -1121,8 +1124,13 @@ static int brcmf_sdio_readshared(struct + sh->flags & SDPCM_SHARED_VERSION_MASK); + return -EPROTO; + } +- + return 0; ++ ++fail: ++ brcmf_err("unable to obtain sdpcm_shared info: rv=%d (addr=0x%x)\n", ++ rv, addr); ++ sdio_release_host(bus->sdiodev->func[1]); ++ return rv; + } + + static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus) diff --git a/package/kernel/mac80211/patches/345-brcmfmac-fix-watchdog-timer-regression.patch b/package/kernel/mac80211/patches/345-brcmfmac-fix-watchdog-timer-regression.patch new file mode 100644 index 0000000000..1b10dbb800 --- /dev/null +++ b/package/kernel/mac80211/patches/345-brcmfmac-fix-watchdog-timer-regression.patch @@ -0,0 +1,59 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 11 Mar 2015 16:11:33 +0100 +Subject: [PATCH] brcmfmac: fix watchdog timer regression + +The watchdog timer is used to put the device in a low-power mode when +it is idle for some time. This timer is stopped during that mode and +should be restarted upon activity. This has been broken by commit +d4150fced0365 ("brcmfmac: Simplify watchdog sleep."). This patch +restores the behaviour as it was before that commit. + +Reported-by: Pontus Fuchs <pontusf@broadcom.com> +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -972,7 +972,6 @@ static int brcmf_sdio_clkctl(struct brcm + brcmf_sdio_sdclk(bus, true); + /* Now request HT Avail on the backplane */ + brcmf_sdio_htclk(bus, true, pendok); +- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); + break; + + case CLK_SDONLY: +@@ -984,7 +983,6 @@ static int brcmf_sdio_clkctl(struct brcm + else + brcmf_err("request for %d -> %d\n", + bus->clkstate, target); +- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); + break; + + case CLK_NONE: +@@ -993,7 +991,6 @@ static int brcmf_sdio_clkctl(struct brcm + brcmf_sdio_htclk(bus, false, false); + /* Now remove the SD clock */ + brcmf_sdio_sdclk(bus, false); +- brcmf_sdio_wd_timer(bus, 0); + break; + } + #ifdef DEBUG +@@ -1048,6 +1045,7 @@ end: + brcmf_sdio_clkctl(bus, CLK_NONE, pendok); + } else { + brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); ++ brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); + } + bus->sleeping = sleep; + brcmf_dbg(SDIO, "new state %s\n", +@@ -4242,6 +4240,7 @@ void brcmf_sdio_remove(struct brcmf_sdio + if (bus->ci) { + if (bus->sdiodev->state != BRCMF_SDIOD_NOMEDIUM) { + sdio_claim_host(bus->sdiodev->func[1]); ++ brcmf_sdio_wd_timer(bus, 0); + brcmf_sdio_clkctl(bus, CLK_AVAIL, false); + /* Leave the device in state where it is + * 'passive'. This is done by resetting all diff --git a/package/kernel/mac80211/patches/346-brcmfmac-avoid-runtime-pm-for-sdio-host-controller.patch b/package/kernel/mac80211/patches/346-brcmfmac-avoid-runtime-pm-for-sdio-host-controller.patch new file mode 100644 index 0000000000..af76f13ecd --- /dev/null +++ b/package/kernel/mac80211/patches/346-brcmfmac-avoid-runtime-pm-for-sdio-host-controller.patch @@ -0,0 +1,44 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 18 Mar 2015 13:25:21 +0100 +Subject: [PATCH] brcmfmac: avoid runtime-pm for sdio host controller + +Several host controllers supporting runtime-pm are causing issues +with our sdio wireless cards because they disable the sdio interrupt +upon going into runtime suspend. This patch avoids that by doing +a pm_runtime_forbid() call during the probe. Tested with Sony Vaio +Duo 13 which uses sdhci-acpi host controller. + +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +@@ -29,6 +29,7 @@ + #include <linux/mmc/host.h> + #include <linux/platform_device.h> + #include <linux/platform_data/brcmfmac-sdio.h> ++#include <linux/pm_runtime.h> + #include <linux/suspend.h> + #include <linux/errno.h> + #include <linux/module.h> +@@ -1006,6 +1007,7 @@ static int brcmf_sdiod_remove(struct brc + sg_free_table(&sdiodev->sgtable); + sdiodev->sbwad = 0; + ++ pm_runtime_allow(sdiodev->func[1]->card->host->parent); + return 0; + } + +@@ -1074,7 +1076,7 @@ static int brcmf_sdiod_probe(struct brcm + ret = -ENODEV; + goto out; + } +- ++ pm_runtime_forbid(host->parent); + out: + if (ret) + brcmf_sdiod_remove(sdiodev); diff --git a/package/kernel/mac80211/patches/347-brcmfmac-Add-necessary-memory-barriers-for-SDIO.patch b/package/kernel/mac80211/patches/347-brcmfmac-Add-necessary-memory-barriers-for-SDIO.patch new file mode 100644 index 0000000000..c419cc68f5 --- /dev/null +++ b/package/kernel/mac80211/patches/347-brcmfmac-Add-necessary-memory-barriers-for-SDIO.patch @@ -0,0 +1,171 @@ +From: Hante Meuleman <meuleman@broadcom.com> +Date: Wed, 18 Mar 2015 13:25:22 +0100 +Subject: [PATCH] brcmfmac: Add necessary memory barriers for SDIO. + +SDIO uses a thread to handle all communication with the device, +for this data is exchanged between threads. This data needs proper +memory barriers to make sure that data "exchange" is going correct. + +Reviewed-by: Arend Van Spriel <arend@broadcom.com> +Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> +Signed-off-by: Hante Meuleman <meuleman@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -507,8 +507,8 @@ struct brcmf_sdio { + + struct workqueue_struct *brcmf_wq; + struct work_struct datawork; +- atomic_t dpc_tskcnt; +- atomic_t dpc_running; ++ bool dpc_triggered; ++ bool dpc_running; + + bool txoff; /* Transmit flow-controlled */ + struct brcmf_sdio_count sdcnt; +@@ -2713,6 +2713,7 @@ static void brcmf_sdio_dpc(struct brcmf_ + err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, + bus->ctrl_frame_len); + bus->ctrl_frame_err = err; ++ wmb(); + bus->ctrl_frame_stat = false; + } + sdio_release_host(bus->sdiodev->func[1]); +@@ -2734,6 +2735,7 @@ static void brcmf_sdio_dpc(struct brcmf_ + sdio_claim_host(bus->sdiodev->func[1]); + if (bus->ctrl_frame_stat) { + bus->ctrl_frame_err = -ENODEV; ++ wmb(); + bus->ctrl_frame_stat = false; + brcmf_sdio_wait_event_wakeup(bus); + } +@@ -2744,7 +2746,7 @@ static void brcmf_sdio_dpc(struct brcmf_ + (!atomic_read(&bus->fcstate) && + brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && + data_ok(bus))) { +- atomic_inc(&bus->dpc_tskcnt); ++ bus->dpc_triggered = true; + } + } + +@@ -2940,6 +2942,7 @@ brcmf_sdio_bus_txctl(struct device *dev, + /* Send from dpc */ + bus->ctrl_frame_buf = msg; + bus->ctrl_frame_len = msglen; ++ wmb(); + bus->ctrl_frame_stat = true; + + brcmf_sdio_trigger_dpc(bus); +@@ -2958,6 +2961,7 @@ brcmf_sdio_bus_txctl(struct device *dev, + if (!ret) { + brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n", + bus->ctrl_frame_err); ++ rmb(); + ret = bus->ctrl_frame_err; + } + +@@ -3526,8 +3530,8 @@ done: + + void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus) + { +- if (atomic_read(&bus->dpc_tskcnt) == 0) { +- atomic_inc(&bus->dpc_tskcnt); ++ if (!bus->dpc_triggered) { ++ bus->dpc_triggered = true; + queue_work(bus->brcmf_wq, &bus->datawork); + } + } +@@ -3558,7 +3562,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b + if (!bus->intr) + brcmf_err("isr w/o interrupt configured!\n"); + +- atomic_inc(&bus->dpc_tskcnt); ++ bus->dpc_triggered = true; + queue_work(bus->brcmf_wq, &bus->datawork); + } + +@@ -3578,7 +3582,7 @@ static void brcmf_sdio_bus_watchdog(stru + if (!bus->intr || + (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { + +- if (atomic_read(&bus->dpc_tskcnt) == 0) { ++ if (!bus->dpc_triggered) { + u8 devpend; + + sdio_claim_host(bus->sdiodev->func[1]); +@@ -3596,7 +3600,7 @@ static void brcmf_sdio_bus_watchdog(stru + bus->sdcnt.pollcnt++; + atomic_set(&bus->ipend, 1); + +- atomic_inc(&bus->dpc_tskcnt); ++ bus->dpc_triggered = true; + queue_work(bus->brcmf_wq, &bus->datawork); + } + } +@@ -3623,17 +3627,21 @@ static void brcmf_sdio_bus_watchdog(stru + #endif /* DEBUG */ + + /* On idle timeout clear activity flag and/or turn off clock */ +- if ((atomic_read(&bus->dpc_tskcnt) == 0) && +- (atomic_read(&bus->dpc_running) == 0) && +- (bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { +- bus->idlecount++; +- if (bus->idlecount > bus->idletime) { +- brcmf_dbg(SDIO, "idle\n"); +- sdio_claim_host(bus->sdiodev->func[1]); +- brcmf_sdio_wd_timer(bus, 0); ++ if (!bus->dpc_triggered) { ++ rmb(); ++ if ((!bus->dpc_running) && (bus->idletime > 0) && ++ (bus->clkstate == CLK_AVAIL)) { ++ bus->idlecount++; ++ if (bus->idlecount > bus->idletime) { ++ brcmf_dbg(SDIO, "idle\n"); ++ sdio_claim_host(bus->sdiodev->func[1]); ++ brcmf_sdio_wd_timer(bus, 0); ++ bus->idlecount = 0; ++ brcmf_sdio_bus_sleep(bus, true, false); ++ sdio_release_host(bus->sdiodev->func[1]); ++ } ++ } else { + bus->idlecount = 0; +- brcmf_sdio_bus_sleep(bus, true, false); +- sdio_release_host(bus->sdiodev->func[1]); + } + } else { + bus->idlecount = 0; +@@ -3645,13 +3653,14 @@ static void brcmf_sdio_dataworker(struct + struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, + datawork); + +- while (atomic_read(&bus->dpc_tskcnt)) { +- atomic_set(&bus->dpc_running, 1); +- atomic_set(&bus->dpc_tskcnt, 0); ++ bus->dpc_running = true; ++ wmb(); ++ while (ACCESS_ONCE(bus->dpc_triggered)) { ++ bus->dpc_triggered = false; + brcmf_sdio_dpc(bus); + bus->idlecount = 0; +- atomic_set(&bus->dpc_running, 0); + } ++ bus->dpc_running = false; + if (brcmf_sdiod_freezing(bus->sdiodev)) { + brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN); + brcmf_sdiod_try_freeze(bus->sdiodev); +@@ -4144,8 +4153,8 @@ struct brcmf_sdio *brcmf_sdio_probe(stru + bus->watchdog_tsk = NULL; + } + /* Initialize DPC thread */ +- atomic_set(&bus->dpc_tskcnt, 0); +- atomic_set(&bus->dpc_running, 0); ++ bus->dpc_triggered = false; ++ bus->dpc_running = false; + + /* Assign bus interface call back */ + bus->sdiodev->bus_if->dev = bus->sdiodev->dev; diff --git a/package/kernel/mac80211/patches/348-brcmfmac-Remove-unnecessary-new-line-in-pcie-console.patch b/package/kernel/mac80211/patches/348-brcmfmac-Remove-unnecessary-new-line-in-pcie-console.patch new file mode 100644 index 0000000000..1bc98a053e --- /dev/null +++ b/package/kernel/mac80211/patches/348-brcmfmac-Remove-unnecessary-new-line-in-pcie-console.patch @@ -0,0 +1,26 @@ +From: Hante Meuleman <meuleman@broadcom.com> +Date: Wed, 18 Mar 2015 13:25:24 +0100 +Subject: [PATCH] brcmfmac: Remove unnecessary new-line in pcie console + logging. + +Reviewed-by: Arend Van Spriel <arend@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Hante Meuleman <meuleman@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +@@ -651,10 +651,9 @@ static void brcmf_pcie_bus_console_read( + console->log_str[console->log_idx] = ch; + console->log_idx++; + } +- + if (ch == '\n') { + console->log_str[console->log_idx] = 0; +- brcmf_dbg(PCIE, "CONSOLE: %s\n", console->log_str); ++ brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str); + console->log_idx = 0; + } + } diff --git a/package/kernel/mac80211/patches/349-brcmfmac-add-MODULE_FIRMWARE-macros-for-bcm4356-PCIe.patch b/package/kernel/mac80211/patches/349-brcmfmac-add-MODULE_FIRMWARE-macros-for-bcm4356-PCIe.patch new file mode 100644 index 0000000000..fcf0bf34f0 --- /dev/null +++ b/package/kernel/mac80211/patches/349-brcmfmac-add-MODULE_FIRMWARE-macros-for-bcm4356-PCIe.patch @@ -0,0 +1,26 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 18 Mar 2015 13:25:25 +0100 +Subject: [PATCH] brcmfmac: add MODULE_FIRMWARE() macros for bcm4356 PCIe + device + +The BCM4356 PCIe wireless device was added recently but overlooked +the fact that the MODULE_FIRMWARE() macros were missing for the +firmwares needed by this device. + +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +@@ -189,6 +189,8 @@ MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME + MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME); + MODULE_FIRMWARE(BRCMF_PCIE_4354_FW_NAME); + MODULE_FIRMWARE(BRCMF_PCIE_4354_NVRAM_NAME); ++MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME); ++MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME); + MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME); + MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME); + diff --git a/package/kernel/mac80211/patches/350-brcmfmac-add-support-for-BCM43430-SDIO-chipset.patch b/package/kernel/mac80211/patches/350-brcmfmac-add-support-for-BCM43430-SDIO-chipset.patch new file mode 100644 index 0000000000..b3e9bc9a07 --- /dev/null +++ b/package/kernel/mac80211/patches/350-brcmfmac-add-support-for-BCM43430-SDIO-chipset.patch @@ -0,0 +1,138 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 18 Mar 2015 13:25:26 +0100 +Subject: [PATCH] brcmfmac: add support for BCM43430 SDIO chipset + +This patch added support for the BCM43430 802.11n SDIO chipset. + +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> +Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +@@ -1098,6 +1098,7 @@ static const struct sdio_device_id brcmf + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339), ++ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354), + { /* end: all zeroes */ } +--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +@@ -600,6 +600,12 @@ static void brcmf_chip_socram_ramsize(st + if (sr->chip->pub.chiprev < 2) + *srsize = (32 * 1024); + break; ++ case BRCM_CC_43430_CHIP_ID: ++ /* assume sr for now as we can not check ++ * firmware sr capability at this point. ++ */ ++ *srsize = (64 * 1024); ++ break; + default: + break; + } +@@ -1072,6 +1078,7 @@ static void + brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip) + { + struct brcmf_core *core; ++ struct brcmf_core_priv *sr; + + brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3); + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); +@@ -1081,6 +1088,13 @@ brcmf_chip_cm3_set_passive(struct brcmf_ + D11_BCMA_IOCTL_PHYCLOCKEN); + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM); + brcmf_chip_resetcore(core, 0, 0, 0); ++ ++ /* disable bank #3 remap for this device */ ++ if (chip->pub.chip == BRCM_CC_43430_CHIP_ID) { ++ sr = container_of(core, struct brcmf_core_priv, pub); ++ brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankidx), 3); ++ brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankpda), 0); ++ } + } + + static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip) +@@ -1188,6 +1202,10 @@ bool brcmf_chip_sr_capable(struct brcmf_ + addr = CORE_CC_REG(base, chipcontrol_data); + reg = chip->ops->read32(chip->ctx, addr); + return (reg & pmu_cc3_mask) != 0; ++ case BRCM_CC_43430_CHIP_ID: ++ addr = CORE_CC_REG(base, sr_control1); ++ reg = chip->ops->read32(chip->ctx, addr); ++ return reg != 0; + default: + addr = CORE_CC_REG(base, pmucapabilities_ext); + reg = chip->ops->read32(chip->ctx, addr); +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -615,6 +615,8 @@ static const struct sdiod_drive_str sdio + #define BCM43362_NVRAM_NAME "brcm/brcmfmac43362-sdio.txt" + #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" + #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" ++#define BCM43430_FIRMWARE_NAME "brcm/brcmfmac43430-sdio.bin" ++#define BCM43430_NVRAM_NAME "brcm/brcmfmac43430-sdio.txt" + #define BCM4345_FIRMWARE_NAME "brcm/brcmfmac4345-sdio.bin" + #define BCM4345_NVRAM_NAME "brcm/brcmfmac4345-sdio.txt" + #define BCM4354_FIRMWARE_NAME "brcm/brcmfmac4354-sdio.bin" +@@ -640,6 +642,8 @@ MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME); + MODULE_FIRMWARE(BCM43362_NVRAM_NAME); + MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); + MODULE_FIRMWARE(BCM4339_NVRAM_NAME); ++MODULE_FIRMWARE(BCM43430_FIRMWARE_NAME); ++MODULE_FIRMWARE(BCM43430_NVRAM_NAME); + MODULE_FIRMWARE(BCM4345_FIRMWARE_NAME); + MODULE_FIRMWARE(BCM4345_NVRAM_NAME); + MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME); +@@ -671,6 +675,7 @@ static const struct brcmf_firmware_names + { BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, + { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, + { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, ++ { BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43430) }, + { BRCM_CC_4345_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4345) }, + { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } + }; +--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +@@ -37,6 +37,7 @@ + #define BRCM_CC_43362_CHIP_ID 43362 + #define BRCM_CC_4335_CHIP_ID 0x4335 + #define BRCM_CC_4339_CHIP_ID 0x4339 ++#define BRCM_CC_43430_CHIP_ID 43430 + #define BRCM_CC_4345_CHIP_ID 0x4345 + #define BRCM_CC_4354_CHIP_ID 0x4354 + #define BRCM_CC_4356_CHIP_ID 0x4356 +--- a/drivers/net/wireless/brcm80211/include/chipcommon.h ++++ b/drivers/net/wireless/brcm80211/include/chipcommon.h +@@ -183,7 +183,14 @@ struct chipcregs { + u8 uart1lsr; + u8 uart1msr; + u8 uart1scratch; +- u32 PAD[126]; ++ u32 PAD[62]; ++ ++ /* save/restore, corerev >= 48 */ ++ u32 sr_capability; /* 0x500 */ ++ u32 sr_control0; /* 0x504 */ ++ u32 sr_control1; /* 0x508 */ ++ u32 gpio_control; /* 0x50C */ ++ u32 PAD[60]; + + /* PMU registers (corerev >= 20) */ + u32 pmucontrol; /* 0x600 */ +--- a/include/linux/mmc/sdio_ids.h ++++ b/include/linux/mmc/sdio_ids.h +@@ -33,6 +33,7 @@ + #define SDIO_DEVICE_ID_BROADCOM_43341 0xa94d + #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335 + #define SDIO_DEVICE_ID_BROADCOM_43362 0xa962 ++#define SDIO_DEVICE_ID_BROADCOM_43430 0xa9a6 + #define SDIO_DEVICE_ID_BROADCOM_4345 0x4345 + #define SDIO_DEVICE_ID_BROADCOM_4354 0x4354 + diff --git a/package/kernel/mac80211/patches/351-brcmfmac-only-support-the-BCM43455-7-device.patch b/package/kernel/mac80211/patches/351-brcmfmac-only-support-the-BCM43455-7-device.patch new file mode 100644 index 0000000000..c3d7bc2cbf --- /dev/null +++ b/package/kernel/mac80211/patches/351-brcmfmac-only-support-the-BCM43455-7-device.patch @@ -0,0 +1,50 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 18 Mar 2015 13:25:27 +0100 +Subject: [PATCH] brcmfmac: only support the BCM43455/7 device + +Recently support was added for the BCM4345 SDIO chipset by +commit 9c51026509d7 ("brcmfmac: Add support for BCM4345 SDIO chipset") +however this was verified using a BCM43455 device, which is +a more recent revision of the chip. This patch assure that +older revisions are not probed as they would fail. + +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Syed Asifful Dayyan <syedd@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -617,8 +617,8 @@ static const struct sdiod_drive_str sdio + #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" + #define BCM43430_FIRMWARE_NAME "brcm/brcmfmac43430-sdio.bin" + #define BCM43430_NVRAM_NAME "brcm/brcmfmac43430-sdio.txt" +-#define BCM4345_FIRMWARE_NAME "brcm/brcmfmac4345-sdio.bin" +-#define BCM4345_NVRAM_NAME "brcm/brcmfmac4345-sdio.txt" ++#define BCM43455_FIRMWARE_NAME "brcm/brcmfmac43455-sdio.bin" ++#define BCM43455_NVRAM_NAME "brcm/brcmfmac43455-sdio.txt" + #define BCM4354_FIRMWARE_NAME "brcm/brcmfmac4354-sdio.bin" + #define BCM4354_NVRAM_NAME "brcm/brcmfmac4354-sdio.txt" + +@@ -644,8 +644,8 @@ MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); + MODULE_FIRMWARE(BCM4339_NVRAM_NAME); + MODULE_FIRMWARE(BCM43430_FIRMWARE_NAME); + MODULE_FIRMWARE(BCM43430_NVRAM_NAME); +-MODULE_FIRMWARE(BCM4345_FIRMWARE_NAME); +-MODULE_FIRMWARE(BCM4345_NVRAM_NAME); ++MODULE_FIRMWARE(BCM43455_FIRMWARE_NAME); ++MODULE_FIRMWARE(BCM43455_NVRAM_NAME); + MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME); + MODULE_FIRMWARE(BCM4354_NVRAM_NAME); + +@@ -676,7 +676,7 @@ static const struct brcmf_firmware_names + { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, + { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, + { BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43430) }, +- { BRCM_CC_4345_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4345) }, ++ { BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, BRCMF_FIRMWARE_NVRAM(BCM43455) }, + { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } + }; + diff --git a/package/kernel/mac80211/patches/352-brcmfmac-remove-support-for-unreleased-BCM4354-PCIe.patch b/package/kernel/mac80211/patches/352-brcmfmac-remove-support-for-unreleased-BCM4354-PCIe.patch new file mode 100644 index 0000000000..a62cfdfc4c --- /dev/null +++ b/package/kernel/mac80211/patches/352-brcmfmac-remove-support-for-unreleased-BCM4354-PCIe.patch @@ -0,0 +1,52 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Wed, 18 Mar 2015 13:25:28 +0100 +Subject: [PATCH] brcmfmac: remove support for unreleased BCM4354 PCIe + +There are no known BCM4354 PCIe devices released so removing +support from the driver until proven otherwise. + +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +@@ -47,8 +47,6 @@ enum brcmf_pcie_state { + + #define BRCMF_PCIE_43602_FW_NAME "brcm/brcmfmac43602-pcie.bin" + #define BRCMF_PCIE_43602_NVRAM_NAME "brcm/brcmfmac43602-pcie.txt" +-#define BRCMF_PCIE_4354_FW_NAME "brcm/brcmfmac4354-pcie.bin" +-#define BRCMF_PCIE_4354_NVRAM_NAME "brcm/brcmfmac4354-pcie.txt" + #define BRCMF_PCIE_4356_FW_NAME "brcm/brcmfmac4356-pcie.bin" + #define BRCMF_PCIE_4356_NVRAM_NAME "brcm/brcmfmac4356-pcie.txt" + #define BRCMF_PCIE_43570_FW_NAME "brcm/brcmfmac43570-pcie.bin" +@@ -187,8 +185,6 @@ enum brcmf_pcie_state { + + MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME); + MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME); +-MODULE_FIRMWARE(BRCMF_PCIE_4354_FW_NAME); +-MODULE_FIRMWARE(BRCMF_PCIE_4354_NVRAM_NAME); + MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME); + MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME); + MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME); +@@ -1327,10 +1323,6 @@ static int brcmf_pcie_get_fwnames(struct + fw_name = BRCMF_PCIE_43602_FW_NAME; + nvram_name = BRCMF_PCIE_43602_NVRAM_NAME; + break; +- case BRCM_CC_4354_CHIP_ID: +- fw_name = BRCMF_PCIE_4354_FW_NAME; +- nvram_name = BRCMF_PCIE_4354_NVRAM_NAME; +- break; + case BRCM_CC_4356_CHIP_ID: + fw_name = BRCMF_PCIE_4356_FW_NAME; + nvram_name = BRCMF_PCIE_4356_NVRAM_NAME; +@@ -1855,7 +1847,6 @@ cleanup: + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 } + + static struct pci_device_id brcmf_pcie_devid_table[] = { +- BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID), diff --git a/package/kernel/mac80211/patches/353-brcmfmac-disable-MBSS-feature-for-BCM43362.patch b/package/kernel/mac80211/patches/353-brcmfmac-disable-MBSS-feature-for-BCM43362.patch new file mode 100644 index 0000000000..366ff85d03 --- /dev/null +++ b/package/kernel/mac80211/patches/353-brcmfmac-disable-MBSS-feature-for-BCM43362.patch @@ -0,0 +1,28 @@ +From: Arend van Spriel <arend@broadcom.com> +Date: Fri, 20 Mar 2015 22:18:17 +0100 +Subject: [PATCH] brcmfmac: disable MBSS feature for BCM43362 + +The BCM43362 firmware falsely reports it is capable of providing +MBSS. As a result AP mode no longer works for this device. Therefor +disable MBSS in the driver for this chipset. + +Cc: stable@vger.kernel.org # 3.19.y +Reported-by: Jorg Krause <jkrause@posteo.de> +Reviewed-by: Hante Meuleman <meuleman@broadcom.com> +Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> +Signed-off-by: Arend van Spriel <arend@broadcom.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c +@@ -126,7 +126,8 @@ void brcmf_feat_attach(struct brcmf_pub + brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan"); + if (drvr->bus_if->wowl_supported) + brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl"); +- brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0); ++ if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID) ++ brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0); + + /* set chip related quirks */ + switch (drvr->bus_if->chip) { |