#include "debug.h"
 #include "sdio.h"
 #include "of.h"
+#include "core.h"
+#include "common.h"
 
 #define SDIOH_API_ACCESS_RETRY_LIMIT   2
 
 /* Maximum milliseconds to wait for F2 to come up */
 #define SDIO_WAIT_F2RDY        3000
 
-#define BRCMF_DEFAULT_TXGLOM_SIZE      32  /* max tx frames in glom chain */
 #define BRCMF_DEFAULT_RXGLOM_SIZE      32  /* max rx frames in glom chain */
 
 struct brcmf_sdiod_freezer {
        struct completion resumed;
 };
 
-static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE;
-module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0);
-MODULE_PARM_DESC(txglomsz, "maximum tx packet chain size [SDIO]");
-
 static irqreturn_t brcmf_sdiod_oob_irqhandler(int irq, void *dev_id)
 {
        struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
        if (!sdiodev->sg_support)
                return;
 
-       nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE, brcmf_sdiod_txglomsz);
+       nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE,
+                     sdiodev->bus_if->drvr->settings->sdiod_txglomsz);
        nents += (nents >> 4) + 1;
 
        WARN_ON(nents > sdiodev->max_segment_count);
                sdiodev->sg_support = false;
        }
 
-       sdiodev->txglomsz = brcmf_sdiod_txglomsz;
+       sdiodev->txglomsz = sdiodev->bus_if->drvr->settings->sdiod_txglomsz;
 }
 
 #ifdef CONFIG_PM_SLEEP
 
        struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT];
 };
 
-static int brcmf_roamoff;
-module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
-MODULE_PARM_DESC(roamoff, "do not use internal roaming engine");
-
 
 static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
                               struct cfg80211_chan_def *ch)
        __le32 roam_delta[2];
 
        /* Configure beacon timeout value based upon roaming setting */
-       if (brcmf_roamoff)
+       if (ifp->drvr->settings->roamoff)
                bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_OFF;
        else
                bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON;
         * roaming.
         */
        brcmf_dbg(INFO, "Internal Roaming = %s\n",
-                 brcmf_roamoff ? "Off" : "On");
-       err = brcmf_fil_iovar_int_set(ifp, "roam_off", !!(brcmf_roamoff));
+                 ifp->drvr->settings->roamoff ? "Off" : "On");
+       err = brcmf_fil_iovar_int_set(ifp, "roam_off",
+                                     ifp->drvr->settings->roamoff);
        if (err) {
                brcmf_err("roam_off error (%d)\n", err);
                goto roam_setup_done;
                        WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
        if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS))
                wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
-       if (!brcmf_roamoff)
+       if (!ifp->drvr->settings->roamoff)
                wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
        wiphy->mgmt_stypes = brcmf_txrx_stypes;
        wiphy->max_remain_on_channel_duration = 5000;
 
 /* boost value for RSSI_DELTA in preferred join selection */
 #define BRCMF_JOIN_PREF_RSSI_BOOST     8
 
+#define BRCMF_DEFAULT_TXGLOM_SIZE      32  /* max tx frames in glom chain */
+
+static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE;
+module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0);
+MODULE_PARM_DESC(txglomsz, "Maximum tx packet chain size [SDIO]");
+
+/* Debug level configuration. See debug.h for bits, sysfs modifiable */
+int brcmf_msg_level;
+module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(debug, "Level of debug output");
+
+static int brcmf_p2p_enable;
+module_param_named(p2pon, brcmf_p2p_enable, int, 0);
+MODULE_PARM_DESC(p2pon, "Enable legacy p2p management functionality");
+
+static int brcmf_feature_disable;
+module_param_named(feature_disable, brcmf_feature_disable, int, 0);
+MODULE_PARM_DESC(feature_disable, "Disable features");
+
+static char brcmf_firmware_path[BRCMF_FW_ALTPATH_LEN];
+module_param_string(alternative_fw_path, brcmf_firmware_path,
+                   BRCMF_FW_ALTPATH_LEN, S_IRUSR);
+MODULE_PARM_DESC(alternative_fw_path, "Alternative firmware path");
+
+static int brcmf_fcmode;
+module_param_named(fcmode, brcmf_fcmode, int, 0);
+MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control");
+
+static int brcmf_roamoff;
+module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
+MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
+
+struct brcmf_mp_global_t brcmf_mp_global;
+
 int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 {
        s8 eventmask[BRCMF_EVENTING_MASK_LEN];
        va_end(args);
 }
 #endif
+
+void brcmf_mp_attach(void)
+{
+       strlcpy(brcmf_mp_global.firmware_path, brcmf_firmware_path,
+               BRCMF_FW_ALTPATH_LEN);
+}
+
+int brcmf_mp_device_attach(struct brcmf_pub *drvr)
+{
+       drvr->settings = kzalloc(sizeof(*drvr->settings), GFP_ATOMIC);
+       if (!drvr->settings) {
+               brcmf_err("Failed to alloca storage space for settings\n");
+               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;
+
+       return 0;
+}
+
+void brcmf_mp_device_detach(struct brcmf_pub *drvr)
+{
+       kfree(drvr->settings);
+}
+
 
 
 extern const u8 ALLFFMAC[ETH_ALEN];
 
+#define BRCMF_FW_ALTPATH_LEN                   256
+
+/* Definitions for the module global and device specific settings are defined
+ * here. Two structs are used for them. brcmf_mp_global_t and brcmf_mp_device.
+ * The mp_global is instantiated once in a global struct and gets initialized
+ * by the common_attach function which should be called before any other
+ * (module) initiliazation takes place. The device specific settings is part
+ * of the drvr struct and should be initialized on every brcmf_attach.
+ */
+
+/**
+ * struct brcmf_mp_global_t - Global module paramaters.
+ *
+ * @firmware_path: Alternative firmware path.
+ */
+struct brcmf_mp_global_t {
+       char    firmware_path[BRCMF_FW_ALTPATH_LEN];
+};
+
+extern struct brcmf_mp_global_t brcmf_mp_global;
+
+/**
+ * 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?
+ */
+struct brcmf_mp_device {
+       int     sdiod_txglomsz;
+       int     joinboost_5g_rssi;
+       bool    p2p_enable;
+       int     feature_disable;
+       int     fcmode;
+       bool    roamoff;
+};
+
+void brcmf_mp_attach(void);
+int brcmf_mp_device_attach(struct brcmf_pub *drvr);
+void brcmf_mp_device_detach(struct brcmf_pub *drvr);
 /* Sets dongle media info (drv_version, mac address). */
 int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
 
 
 
 #define BRCMF_BSSIDX_INVALID                   -1
 
-/* Error bits */
-int brcmf_msg_level;
-module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR);
-MODULE_PARM_DESC(debug, "level of debug output");
-
-/* P2P0 enable */
-static int brcmf_p2p_enable;
-module_param_named(p2pon, brcmf_p2p_enable, int, 0);
-MODULE_PARM_DESC(p2pon, "enable legacy p2p management functionality");
-
 char *brcmf_ifname(struct brcmf_if *ifp)
 {
        if (!ifp)
                }
        }
 
-       if (!brcmf_p2p_enable && is_p2pdev) {
+       if (!drvr->settings->p2p_enable && is_p2pdev) {
                /* this is P2P_DEVICE interface */
                brcmf_dbg(INFO, "allocate non-netdev interface\n");
                ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
        drvr->bus_if = dev_get_drvdata(dev);
        drvr->bus_if->drvr = drvr;
 
+       /* Initialize device specific settings */
+       if (brcmf_mp_device_attach(drvr))
+               goto fail;
+
        /* attach debug facilities */
        brcmf_debug_attach(drvr);
 
        brcmf_fws_add_interface(ifp);
 
        drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev,
-                                            brcmf_p2p_enable);
+                                            drvr->settings->p2p_enable);
        if (drvr->config == NULL) {
                ret = -ENOMEM;
                goto fail;
 
        ret = brcmf_net_attach(ifp, false);
 
-       if ((!ret) && (brcmf_p2p_enable)) {
+       if ((!ret) && (drvr->settings->p2p_enable)) {
                p2p_ifp = drvr->iflist[1];
                if (p2p_ifp)
                        ret = brcmf_net_p2p_attach(p2p_ifp);
 
        brcmf_proto_detach(drvr);
 
+       brcmf_mp_device_detach(drvr);
+
        brcmf_debug_detach(drvr);
        bus_if->drvr = NULL;
        kfree(drvr);
 
 
 /* Forward decls for struct brcmf_pub (see below) */
 struct brcmf_proto;    /* device communication protocol info */
-struct brcmf_cfg80211_dev; /* cfg80211 device info */
-struct brcmf_fws_info; /* firmware signalling info */
+struct brcmf_fws_info; /* firmware signalling info */
+struct brcmf_mp_device;        /* module paramateres, device specific */
 
 /*
  * struct brcmf_rev_info
 #endif
 
        struct notifier_block inetaddr_notifier;
+       struct brcmf_mp_device *settings;
 };
 
 /* forward declarations */
 
 #include "fwil.h"
 #include "fwil_types.h"
 #include "feature.h"
+#include "common.h"
 
 
-/* Module param feature_disable (global for all devices) */
-static int brcmf_feature_disable;
-module_param_named(feature_disable, brcmf_feature_disable, int, 0);
-MODULE_PARM_DESC(feature_disable, "Disable features");
-
 /*
  * expand feature list to array of feature strings.
  */
        if (!err)
                ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_SCAN_RANDOM_MAC);
 
-       if (brcmf_feature_disable) {
+       if (drvr->settings->feature_disable) {
                brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
-                         ifp->drvr->feat_flags, brcmf_feature_disable);
-               ifp->drvr->feat_flags &= ~brcmf_feature_disable;
+                         ifp->drvr->feat_flags,
+                         drvr->settings->feature_disable);
+               ifp->drvr->feat_flags &= ~drvr->settings->feature_disable;
        }
 
        /* set chip related quirks */
 
 
 #include "debug.h"
 #include "firmware.h"
+#include "core.h"
+#include "common.h"
 
 #define BRCMF_FW_MAX_NVRAM_SIZE                        64000
 #define BRCMF_FW_NVRAM_DEVPATH_LEN             19      /* devpath0=pcie/1/4/ */
 #define BRCMF_FW_NVRAM_PCIEDEV_LEN             10      /* pcie/1/4/ + \0 */
 
-static char brcmf_firmware_path[BRCMF_FW_NAME_LEN];
-module_param_string(alternative_fw_path, brcmf_firmware_path,
-                   BRCMF_FW_NAME_LEN, 0440);
-
 enum nvram_parser_state {
        IDLE,
        KEY,
        }
 
        /* check if firmware path is provided by module parameter */
-       if (brcmf_firmware_path[0] != '\0') {
-               strlcpy(fw_name, brcmf_firmware_path, BRCMF_FW_NAME_LEN);
+       if (brcmf_mp_global.firmware_path[0] != '\0') {
+               strlcpy(fw_name, brcmf_mp_global.firmware_path,
+                       BRCMF_FW_NAME_LEN);
                if ((nvram_name) && (mapping_table[i].nvram))
-                       strlcpy(nvram_name, brcmf_firmware_path,
+                       strlcpy(nvram_name, brcmf_mp_global.firmware_path,
                                BRCMF_FW_NAME_LEN);
 
-               end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
+               end = brcmf_mp_global.firmware_path[
+                               strlen(brcmf_mp_global.firmware_path) - 1];
                if (end != '/') {
                        strlcat(fw_name, "/", BRCMF_FW_NAME_LEN);
                        if ((nvram_name) && (mapping_table[i].nvram))
 
 #include "p2p.h"
 #include "cfg80211.h"
 #include "proto.h"
+#include "common.h"
 
 /**
  * DOC: Firmware Signalling
        BRCMF_FWS_FIFO_AC_VO
 };
 
-static int fcmode;
-module_param(fcmode, int, S_IRUSR);
-MODULE_PARM_DESC(fcmode, "mode of firmware signalled flow control");
-
 #define BRCMF_FWS_TLV_DEF(name, id, len) \
        case BRCMF_FWS_TYPE_ ## name: \
                return len;
 
        /* set linkage back */
        fws->drvr = drvr;
-       fws->fcmode = fcmode;
+       fws->fcmode = drvr->settings->fcmode;
 
        if ((drvr->bus_if->always_use_fws_queue == false) &&
-           (fcmode == BRCMF_FWS_FCMODE_NONE)) {
+           (fws->fcmode == BRCMF_FWS_FCMODE_NONE)) {
                fws->avoid_queueing = true;
                brcmf_dbg(INFO, "FWS queueing will be avoided\n");
                return 0;