mac80211: brcmfmac: backport patches that were skipped previously #1
[openwrt/svn-archive/archive.git] / package / kernel / mac80211 / patches / 344-0018-brcmfmac-merge-platform-data-and-module-paramaters.patch
diff --git a/package/kernel/mac80211/patches/344-0018-brcmfmac-merge-platform-data-and-module-paramaters.patch b/package/kernel/mac80211/patches/344-0018-brcmfmac-merge-platform-data-and-module-paramaters.patch
new file mode 100644 (file)
index 0000000..34341d7
--- /dev/null
@@ -0,0 +1,607 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:27:08 +0100
+Subject: [PATCH] brcmfmac: merge platform data and module paramaters
+
+Merge module parameters and platform data in one struct. This is the
+last step to move to the new platform data per device. Now parameters
+of platform data will be merged with module parameters per device.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@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/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -109,8 +109,8 @@ int brcmf_sdiod_intr_register(struct brc
+       u32 addr, gpiocontrol;
+       unsigned long flags;
+-      pdata = sdiodev->pdata;
+-      if ((pdata) && (pdata->oob_irq_supported)) {
++      pdata = &sdiodev->settings->bus.sdio;
++      if (pdata->oob_irq_supported) {
+               brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
+                         pdata->oob_irq_nr);
+               ret = request_irq(pdata->oob_irq_nr, brcmf_sdiod_oob_irqhandler,
+@@ -177,8 +177,8 @@ int brcmf_sdiod_intr_unregister(struct b
+       brcmf_dbg(SDIO, "Entering\n");
+-      pdata = sdiodev->pdata;
+-      if ((pdata) && (pdata->oob_irq_supported)) {
++      pdata = &sdiodev->settings->bus.sdio;
++      if (pdata->oob_irq_supported) {
+               sdio_claim_host(sdiodev->func[1]);
+               brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
+               brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+@@ -522,7 +522,7 @@ static int brcmf_sdiod_sglist_rw(struct
+       target_list = pktlist;
+       /* for host with broken sg support, prepare a page aligned list */
+       __skb_queue_head_init(&local_list);
+-      if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
++      if (!write && sdiodev->settings->bus.sdio.broken_sg_support) {
+               req_sz = 0;
+               skb_queue_walk(pktlist, pkt_next)
+                       req_sz += pkt_next->len;
+@@ -629,7 +629,7 @@ static int brcmf_sdiod_sglist_rw(struct
+               }
+       }
+-      if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
++      if (!write && sdiodev->settings->bus.sdio.broken_sg_support) {
+               local_pkt_next = local_list.next;
+               orig_offset = 0;
+               skb_queue_walk(pktlist, pkt_next) {
+@@ -900,7 +900,7 @@ void brcmf_sdiod_sgtable_alloc(struct br
+               return;
+       nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE,
+-                    sdiodev->bus_if->drvr->settings->sdiod_txglomsz);
++                    sdiodev->settings->bus.sdio.txglomsz);
+       nents += (nents >> 4) + 1;
+       WARN_ON(nents > sdiodev->max_segment_count);
+@@ -912,7 +912,7 @@ void brcmf_sdiod_sgtable_alloc(struct br
+               sdiodev->sg_support = false;
+       }
+-      sdiodev->txglomsz = sdiodev->bus_if->drvr->settings->sdiod_txglomsz;
++      sdiodev->txglomsz = sdiodev->settings->bus.sdio.txglomsz;
+ }
+ #ifdef CONFIG_PM_SLEEP
+@@ -1246,8 +1246,8 @@ static int brcmf_ops_sdio_suspend(struct
+       sdio_flags = MMC_PM_KEEP_POWER;
+       if (sdiodev->wowl_enabled) {
+-              if (sdiodev->pdata->oob_irq_supported)
+-                      enable_irq_wake(sdiodev->pdata->oob_irq_nr);
++              if (sdiodev->settings->bus.sdio.oob_irq_supported)
++                      enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
+               else
+                       sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
+       }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+@@ -43,6 +43,8 @@ enum brcmf_bus_protocol_type {
+       BRCMF_PROTO_MSGBUF
+ };
++struct brcmf_mp_device;
++
+ struct brcmf_bus_dcmd {
+       char *name;
+       char *param;
+@@ -217,7 +219,7 @@ bool brcmf_c_prec_enq(struct device *dev
+ void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp);
+ /* Indication from bus module regarding presence/insertion of dongle. */
+-int brcmf_attach(struct device *dev);
++int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings);
+ /* Indication from bus module regarding removal/absence of dongle */
+ void brcmf_detach(struct device *dev);
+ /* Indication from bus module that dongle should be reset */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+@@ -243,14 +243,35 @@ static void brcmf_mp_attach(void)
+       }
+ }
+-struct brcmfmac_sdio_pd *brcmf_get_module_param(struct device *dev,
+-                                              enum brcmf_bus_type bus_type,
+-                                              u32 chip, u32 chiprev)
++struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
++                                             enum brcmf_bus_type bus_type,
++                                             u32 chip, u32 chiprev)
+ {
+-      struct brcmfmac_sdio_pd *pdata;
++      struct brcmf_mp_device *settings;
+       struct brcmfmac_pd_device *device_pd;
++      bool found;
+       int i;
++      brcmf_dbg(INFO, "Enter, bus=%d, chip=%d, rev=%d\n", bus_type, chip,
++                chiprev);
++      settings = kzalloc(sizeof(*settings), GFP_ATOMIC);
++      if (!settings)
++              return NULL;
++
++      /* start by using the module paramaters */
++      settings->p2p_enable = !!brcmf_p2p_enable;
++      settings->feature_disable = brcmf_feature_disable;
++      settings->fcmode = brcmf_fcmode;
++      settings->roamoff = !!brcmf_roamoff;
++#ifdef DEBUG
++      settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
++#endif
++
++      if (bus_type == BRCMF_BUSTYPE_SDIO)
++              settings->bus.sdio.txglomsz = brcmf_sdiod_txglomsz;
++
++      /* See if there is any device specific platform data configured */
++      found = false;
+       if (brcmfmac_pdata) {
+               for (i = 0; i < brcmfmac_pdata->device_count; i++) {
+                       device_pd = &brcmfmac_pdata->devices[i];
+@@ -259,38 +280,29 @@ struct brcmfmac_sdio_pd *brcmf_get_modul
+                           ((device_pd->rev == chiprev) ||
+                            (device_pd->rev == -1))) {
+                               brcmf_dbg(INFO, "Platform data for device found\n");
++                              settings->country_codes =
++                                              device_pd->country_codes;
+                               if (device_pd->bus_type == BRCMF_BUSTYPE_SDIO)
+-                                      return &device_pd->bus.sdio;
++                                      memcpy(&settings->bus.sdio,
++                                             &device_pd->bus.sdio,
++                                             sizeof(settings->bus.sdio));
++                              found = true;
+                               break;
+                       }
+               }
+       }
+-      pdata = NULL;
+-      brcmf_of_probe(dev, &pdata);
+-
+-      return pdata;
+-}
+-
+-int brcmf_mp_device_attach(struct brcmf_pub *drvr)
+-{
+-      drvr->settings = kzalloc(sizeof(*drvr->settings), GFP_ATOMIC);
+-      if (!drvr->settings)
+-              return -ENOMEM;
+-
+-      drvr->settings->sdiod_txglomsz = brcmf_sdiod_txglomsz;
+-      drvr->settings->p2p_enable = !!brcmf_p2p_enable;
+-      drvr->settings->feature_disable = brcmf_feature_disable;
+-      drvr->settings->fcmode = brcmf_fcmode;
+-      drvr->settings->roamoff = !!brcmf_roamoff;
+-#ifdef DEBUG
+-      drvr->settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
+-#endif
+-      return 0;
++      if ((bus_type == BRCMF_BUSTYPE_SDIO) && (!found)) {
++              /* No platform data for this device. In case of SDIO try OF
++               * (Open Firwmare) Device Tree.
++               */
++              brcmf_of_probe(dev, &settings->bus.sdio);
++      }
++      return settings;
+ }
+-void brcmf_mp_device_detach(struct brcmf_pub *drvr)
++void brcmf_release_module_param(struct brcmf_mp_device *module_param)
+ {
+-      kfree(drvr->settings);
++      kfree(module_param);
+ }
+ static int __init brcmf_common_pd_probe(struct platform_device *pdev)
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+@@ -45,41 +45,30 @@ extern struct brcmf_mp_global_t brcmf_mp
+ /**
+  * struct brcmf_mp_device - Device module paramaters.
+  *
+- * @sdiod_txglomsz: SDIO txglom size.
+- * @joinboost_5g_rssi: 5g rssi booost for preferred join selection.
+  * @p2p_enable: Legacy P2P0 enable (old wpa_supplicant).
+  * @feature_disable: Feature_disable bitmask.
+  * @fcmode: FWS flow control.
+  * @roamoff: Firmware roaming off?
++ * @ignore_probe_fail: Ignore probe failure.
+  * @country_codes: If available, pointer to struct for translating country codes
++ * @bus: Bus specific platform data. Only SDIO at the mmoment.
+  */
+ struct brcmf_mp_device {
+-      int     sdiod_txglomsz;
+-      int     joinboost_5g_rssi;
+-      bool    p2p_enable;
+-      int     feature_disable;
+-      int     fcmode;
+-      bool    roamoff;
+-      bool    ignore_probe_fail;
++      bool            p2p_enable;
++      unsigned int    feature_disable;
++      int             fcmode;
++      bool            roamoff;
++      bool            ignore_probe_fail;
+       struct brcmfmac_pd_cc *country_codes;
++      union {
++              struct brcmfmac_sdio_pd sdio;
++      } bus;
+ };
+-struct brcmfmac_sdio_pd *brcmf_get_module_param(struct device *dev,
+-                                              enum brcmf_bus_type bus_type,
+-                                              u32 chip, u32 chiprev);
+-int brcmf_mp_device_attach(struct brcmf_pub *drvr);
+-void brcmf_mp_device_detach(struct brcmf_pub *drvr);
+-#ifdef DEBUG
+-static inline bool brcmf_ignoring_probe_fail(struct brcmf_pub *drvr)
+-{
+-      return drvr->settings->ignore_probe_fail;
+-}
+-#else
+-static inline bool brcmf_ignoring_probe_fail(struct brcmf_pub *drvr)
+-{
+-      return false;
+-}
+-#endif
++struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
++                                             enum brcmf_bus_type bus_type,
++                                             u32 chip, u32 chiprev);
++void brcmf_release_module_param(struct brcmf_mp_device *module_param);
+ /* Sets dongle media info (drv_version, mac address). */
+ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -1104,7 +1104,7 @@ static int brcmf_inet6addr_changed(struc
+ }
+ #endif
+-int brcmf_attach(struct device *dev)
++int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
+ {
+       struct brcmf_pub *drvr = NULL;
+       int ret = 0;
+@@ -1126,10 +1126,7 @@ int brcmf_attach(struct device *dev)
+       drvr->hdrlen = 0;
+       drvr->bus_if = dev_get_drvdata(dev);
+       drvr->bus_if->drvr = drvr;
+-
+-      /* Initialize device specific settings */
+-      if (brcmf_mp_device_attach(drvr))
+-              goto fail;
++      drvr->settings = settings;
+       /* attach debug facilities */
+       brcmf_debug_attach(drvr);
+@@ -1274,7 +1271,7 @@ fail:
+               brcmf_net_detach(p2p_ifp->ndev);
+       drvr->iflist[0] = NULL;
+       drvr->iflist[1] = NULL;
+-      if (brcmf_ignoring_probe_fail(drvr))
++      if (drvr->settings->ignore_probe_fail)
+               ret = 0;
+       return ret;
+@@ -1350,8 +1347,6 @@ void brcmf_detach(struct device *dev)
+       brcmf_proto_detach(drvr);
+-      brcmf_mp_device_detach(drvr);
+-
+       brcmf_debug_detach(drvr);
+       bus_if->drvr = NULL;
+       kfree(drvr);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+@@ -23,7 +23,7 @@
+ #include "common.h"
+ #include "of.h"
+-void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio)
++void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio)
+ {
+       struct device_node *np = dev->of_node;
+       int irq;
+@@ -33,12 +33,8 @@ void brcmf_of_probe(struct device *dev,
+       if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
+               return;
+-      *sdio = devm_kzalloc(dev, sizeof(*sdio), GFP_KERNEL);
+-      if (!(*sdio))
+-              return;
+-
+       if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
+-              (*sdio)->drive_strength = val;
++              sdio->drive_strength = val;
+       /* make sure there are interrupts defined in the node */
+       if (!of_find_property(np, "interrupts", NULL))
+@@ -51,7 +47,7 @@ void brcmf_of_probe(struct device *dev,
+       }
+       irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
+-      (*sdio)->oob_irq_supported = true;
+-      (*sdio)->oob_irq_nr = irq;
+-      (*sdio)->oob_irq_flags = irqf;
++      sdio->oob_irq_supported = true;
++      sdio->oob_irq_nr = irq;
++      sdio->oob_irq_flags = irqf;
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
+@@ -14,10 +14,9 @@
+  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  */
+ #ifdef CONFIG_OF
+-void
+-brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio);
++void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio);
+ #else
+-static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio)
++static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio)
+ {
+ }
+ #endif /* CONFIG_OF */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+@@ -37,6 +37,8 @@
+ #include "pcie.h"
+ #include "firmware.h"
+ #include "chip.h"
++#include "core.h"
++#include "common.h"
+ enum brcmf_pcie_state {
+@@ -266,6 +268,7 @@ struct brcmf_pciedev_info {
+       u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset);
+       void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+                         u16 value);
++      struct brcmf_mp_device *settings;
+ };
+ struct brcmf_pcie_ringbuf {
+@@ -1525,16 +1528,16 @@ static void brcmf_pcie_release_resource(
+ }
+-static int brcmf_pcie_attach_bus(struct device *dev)
++static int brcmf_pcie_attach_bus(struct brcmf_pciedev_info *devinfo)
+ {
+       int ret;
+       /* Attach to the common driver interface */
+-      ret = brcmf_attach(dev);
++      ret = brcmf_attach(&devinfo->pdev->dev, devinfo->settings);
+       if (ret) {
+               brcmf_err("brcmf_attach failed\n");
+       } else {
+-              ret = brcmf_bus_start(dev);
++              ret = brcmf_bus_start(&devinfo->pdev->dev);
+               if (ret)
+                       brcmf_err("dongle is not responding\n");
+       }
+@@ -1672,7 +1675,7 @@ static void brcmf_pcie_setup(struct devi
+       init_waitqueue_head(&devinfo->mbdata_resp_wait);
+       brcmf_pcie_intr_enable(devinfo);
+-      if (brcmf_pcie_attach_bus(bus->dev) == 0)
++      if (brcmf_pcie_attach_bus(devinfo) == 0)
+               return;
+       brcmf_pcie_bus_console_read(devinfo);
+@@ -1716,6 +1719,15 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
+               goto fail;
+       }
++      devinfo->settings = brcmf_get_module_param(&devinfo->pdev->dev,
++                                                 BRCMF_BUSTYPE_PCIE,
++                                                 devinfo->ci->chip,
++                                                 devinfo->ci->chiprev);
++      if (!devinfo->settings) {
++              ret = -ENOMEM;
++              goto fail;
++      }
++
+       bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+       if (!bus) {
+               ret = -ENOMEM;
+@@ -1760,6 +1772,8 @@ fail:
+       brcmf_pcie_release_resource(devinfo);
+       if (devinfo->ci)
+               brcmf_chip_detach(devinfo->ci);
++      if (devinfo->settings)
++              brcmf_release_module_param(devinfo->settings);
+       kfree(pcie_bus_dev);
+       kfree(devinfo);
+       return ret;
+@@ -1799,6 +1813,8 @@ brcmf_pcie_remove(struct pci_dev *pdev)
+       if (devinfo->ci)
+               brcmf_chip_detach(devinfo->ci);
++      if (devinfo->settings)
++              brcmf_release_module_param(devinfo->settings);
+       kfree(devinfo);
+       dev_set_drvdata(&pdev->dev, NULL);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -2442,15 +2442,17 @@ static void brcmf_sdio_bus_stop(struct d
+ static inline void brcmf_sdio_clrintr(struct brcmf_sdio *bus)
+ {
++      struct brcmf_sdio_dev *sdiodev;
+       unsigned long flags;
+-      if (bus->sdiodev->oob_irq_requested) {
+-              spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
+-              if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
+-                      enable_irq(bus->sdiodev->pdata->oob_irq_nr);
+-                      bus->sdiodev->irq_en = true;
++      sdiodev = bus->sdiodev;
++      if (sdiodev->oob_irq_requested) {
++              spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
++              if (!sdiodev->irq_en && !atomic_read(&bus->ipend)) {
++                      enable_irq(sdiodev->settings->bus.sdio.oob_irq_nr);
++                      sdiodev->irq_en = true;
+               }
+-              spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
++              spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
+       }
+ }
+@@ -3394,9 +3396,7 @@ static int brcmf_sdio_bus_preinit(struct
+                                          sizeof(u32));
+       } else {
+               /* otherwise, set txglomalign */
+-              value = 4;
+-              if (sdiodev->pdata)
+-                      value = sdiodev->pdata->sd_sgentry_align;
++              value = sdiodev->settings->bus.sdio.sd_sgentry_align;
+               /* SDIO ADMA requires at least 32 bit alignment */
+               value = max_t(u32, value, 4);
+               err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value,
+@@ -3811,21 +3811,25 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
+               bus->ci = NULL;
+               goto fail;
+       }
+-      sdiodev->pdata = brcmf_get_module_param(sdiodev->dev,
++      sdiodev->settings = brcmf_get_module_param(sdiodev->dev,
+                                                  BRCMF_BUSTYPE_SDIO,
+                                                  bus->ci->chip,
+                                                  bus->ci->chiprev);
++      if (!sdiodev->settings) {
++              brcmf_err("Failed to get device parameters\n");
++              goto fail;
++      }
+       /* platform specific configuration:
+        *   alignments must be at least 4 bytes for ADMA
+        */
+       bus->head_align = ALIGNMENT;
+       bus->sgentry_align = ALIGNMENT;
+-      if (sdiodev->pdata) {
+-              if (sdiodev->pdata->sd_head_align > ALIGNMENT)
+-                      bus->head_align = sdiodev->pdata->sd_head_align;
+-              if (sdiodev->pdata->sd_sgentry_align > ALIGNMENT)
+-                      bus->sgentry_align = sdiodev->pdata->sd_sgentry_align;
+-      }
++      if (sdiodev->settings->bus.sdio.sd_head_align > ALIGNMENT)
++              bus->head_align = sdiodev->settings->bus.sdio.sd_head_align;
++      if (sdiodev->settings->bus.sdio.sd_sgentry_align > ALIGNMENT)
++              bus->sgentry_align =
++                              sdiodev->settings->bus.sdio.sd_sgentry_align;
++
+       /* allocate scatter-gather table. sg support
+        * will be disabled upon allocation failure.
+        */
+@@ -3837,7 +3841,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
+        */
+       if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) &&
+           ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) ||
+-           (sdiodev->pdata && sdiodev->pdata->oob_irq_supported)))
++           (sdiodev->settings->bus.sdio.oob_irq_supported)))
+               sdiodev->bus_if->wowl_supported = true;
+ #endif
+@@ -3846,8 +3850,8 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
+               goto fail;
+       }
+-      if ((sdiodev->pdata) && (sdiodev->pdata->drive_strength))
+-              drivestrength = sdiodev->pdata->drive_strength;
++      if (sdiodev->settings->bus.sdio.drive_strength)
++              drivestrength = sdiodev->settings->bus.sdio.drive_strength;
+       else
+               drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
+       brcmf_sdio_drivestrengthinit(sdiodev, bus->ci, drivestrength);
+@@ -4124,7 +4128,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
+       bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN;
+       /* Attach to the common layer, reserve hdr space */
+-      ret = brcmf_attach(bus->sdiodev->dev);
++      ret = brcmf_attach(bus->sdiodev->dev, bus->sdiodev->settings);
+       if (ret != 0) {
+               brcmf_err("brcmf_attach failed\n");
+               goto fail;
+@@ -4228,6 +4232,8 @@ void brcmf_sdio_remove(struct brcmf_sdio
+                       }
+                       brcmf_chip_detach(bus->ci);
+               }
++              if (bus->sdiodev->settings)
++                      brcmf_release_module_param(bus->sdiodev->settings);
+               kfree(bus->rxbuf);
+               kfree(bus->hdrbuf);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+@@ -184,7 +184,7 @@ struct brcmf_sdio_dev {
+       struct brcmf_sdio *bus;
+       struct device *dev;
+       struct brcmf_bus *bus_if;
+-      struct brcmfmac_sdio_pd *pdata;
++      struct brcmf_mp_device *settings;
+       bool oob_irq_requested;
+       bool irq_en;                    /* irq enable flags */
+       spinlock_t irq_en_lock;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+@@ -27,6 +27,8 @@
+ #include "debug.h"
+ #include "firmware.h"
+ #include "usb.h"
++#include "core.h"
++#include "common.h"
+ #define IOCTL_RESP_TIMEOUT            msecs_to_jiffies(2000)
+@@ -171,6 +173,7 @@ struct brcmf_usbdev_info {
+       struct urb *bulk_urb; /* used for FW download */
+       bool wowl_enabled;
++      struct brcmf_mp_device *settings;
+ };
+ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
+@@ -1027,6 +1030,9 @@ static void brcmf_usb_detach(struct brcm
+       kfree(devinfo->tx_reqs);
+       kfree(devinfo->rx_reqs);
++
++      if (devinfo->settings)
++              brcmf_release_module_param(devinfo->settings);
+ }
+@@ -1136,7 +1142,7 @@ static int brcmf_usb_bus_setup(struct br
+       int ret;
+       /* Attach to the common driver interface */
+-      ret = brcmf_attach(devinfo->dev);
++      ret = brcmf_attach(devinfo->dev, devinfo->settings);
+       if (ret) {
+               brcmf_err("brcmf_attach failed\n");
+               return ret;
+@@ -1223,6 +1229,14 @@ static int brcmf_usb_probe_cb(struct brc
+       bus->wowl_supported = true;
+ #endif
++      devinfo->settings = brcmf_get_module_param(bus->dev, BRCMF_BUSTYPE_USB,
++                                                 bus_pub->devid,
++                                                 bus_pub->chiprev);
++      if (!devinfo->settings) {
++              ret = -ENOMEM;
++              goto fail;
++      }
++
+       if (!brcmf_usb_dlneeded(devinfo)) {
+               ret = brcmf_usb_bus_setup(devinfo);
+               if (ret)