qcacld-3.0: Add support for multiple instances of the host driver

Propagation from qcacld-2.0 to qcacld-3.0.

If the module name is changed to something other than wlan in
Makefile or Kbuild, then MULTI_IF_NAME is defined to be the module name.
When MULTI_IF_NAME is defined, the names for the config files, log files,
and firmware files are prepended or appended with MULTI_IF_NAME. This
prevents file name collisions allowing multiple instances of this driver
to be loaded with different module names.

Change-Id: Id880c5fe423eb0b2a2c01677d8fa7c4a784c74df
CRs-Fixed: 946520
diff --git a/Kbuild b/Kbuild
index ebdbbf1..68ce38d 100644
--- a/Kbuild
+++ b/Kbuild
@@ -1670,6 +1670,23 @@
 ifeq ($(call cc-option-yn, -Wheader-guard),y)
 EXTRA_CFLAGS += -Wheader-guard
 endif
+# If the module name is not "wlan", then the define MULTI_IF_NAME to be the
+# same a the module name. The host driver will then append MULTI_IF_NAME to
+# any string that must be unique for all instances of the driver on the system.
+# This allows multiple instances of the driver with different module names.
+# If the module name is wlan, leave MULTI_IF_NAME undefined and the code will
+# treat the driver as the primary driver.
+ifneq ($(MODNAME), wlan)
+CDEFINES += -DMULTI_IF_NAME=\"$(MODNAME)\"
+endif
+
+# WLAN_HDD_ADAPTER_MAGIC must be unique for all instances of the driver on the
+# system. If it is not defined, then the host driver will use the first 4
+# characters (including NULL) of MULTI_IF_NAME to construct
+# WLAN_HDD_ADAPTER_MAGIC.
+ifdef WLAN_HDD_ADAPTER_MAGIC
+CDEFINES += -DWLAN_HDD_ADAPTER_MAGIC=$(WLAN_HDD_ADAPTER_MAGIC)
+endif
 
 # Module information used by KBuild framework
 obj-$(CONFIG_QCA_CLD_WLAN) += $(MODNAME).o
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index bc0665c..ef8d6c6 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -871,7 +871,28 @@
 	qdf_runtime_lock_t connect;
 };
 
+/*
+ * WLAN_HDD_ADAPTER_MAGIC is a magic number used to identify net devices
+ * belonging to this driver from net devices belonging to other devices.
+ * Therefore, the magic number must be unique relative to the numbers for
+ * other drivers in the system. If WLAN_HDD_ADAPTER_MAGIC is already defined
+ * (e.g. by compiler argument), then use that. If it's not already defined,
+ * then use the first 4 characters of MULTI_IF_NAME to construct the magic
+ * number. If MULTI_IF_NAME is not defined, then use a default magic number.
+ */
+#ifndef WLAN_HDD_ADAPTER_MAGIC
+#ifdef MULTI_IF_NAME
+#define WLAN_HDD_ADAPTER_MAGIC                                          \
+	(MULTI_IF_NAME[0] == 0 ? 0x574c414e :                           \
+	(MULTI_IF_NAME[1] == 0 ? (MULTI_IF_NAME[0] << 24) :             \
+	(MULTI_IF_NAME[2] == 0 ? (MULTI_IF_NAME[0] << 24) |             \
+		(MULTI_IF_NAME[1] << 16) :                              \
+	(MULTI_IF_NAME[0] << 24) | (MULTI_IF_NAME[1] << 16) |           \
+	(MULTI_IF_NAME[2] << 8) | MULTI_IF_NAME[3])))
+#else
 #define WLAN_HDD_ADAPTER_MAGIC 0x574c414e       /* ASCII "WLAN" */
+#endif
+#endif
 
 struct hdd_adapter_s {
 	/* Magic cookie for adapter sanity verification.  Note that this
diff --git a/core/hdd/inc/wlan_hdd_misc.h b/core/hdd/inc/wlan_hdd_misc.h
index e0a0db2..82e1b2b 100644
--- a/core/hdd/inc/wlan_hdd_misc.h
+++ b/core/hdd/inc/wlan_hdd_misc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014,2016 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -27,13 +27,22 @@
 
 #ifndef WLAN_HDD_MISC_H
 #define WLAN_HDD_MISC_H
+/*
+ * If MULTI_IF_NAME is defined, then prepend MULTI_IF_NAME to the filename
+ * to prevent name conflicts when loading multiple instances of the driver.
+ */
+#ifdef MULTI_IF_NAME
+#define PREFIX MULTI_IF_NAME
+#else
+#define PREFIX ""
+#endif
 
 #ifdef MSM_PLATFORM
-#define WLAN_INI_FILE              "wlan/qca_cld/WCNSS_qcom_cfg.ini"
-#define WLAN_MAC_FILE              "wlan/qca_cld/wlan_mac.bin"
+#define WLAN_INI_FILE              "wlan/qca_cld/" PREFIX "WCNSS_qcom_cfg.ini"
+#define WLAN_MAC_FILE              "wlan/qca_cld/" PREFIX "wlan_mac.bin"
 #else
-#define WLAN_INI_FILE              "wlan/qcom_cfg.ini"
-#define WLAN_MAC_FILE              "wlan/wlan_mac.bin"
+#define WLAN_INI_FILE              "wlan/" PREFIX "qcom_cfg.ini"
+#define WLAN_MAC_FILE              "wlan/" PREFIX "wlan_mac.bin"
 #endif /* MSM_PLATFORM */
 
 #endif /* WLAN_HDD_MISC_H */
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 4cc6296..5c1bd12 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -368,7 +368,7 @@
 	if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
 		return NOTIFY_DONE;
 
-	if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) &&
+	if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
 	    (adapter->dev != dev)) {
 		hdd_err("device adapter is not matching!!!");
 		return NOTIFY_DONE;
diff --git a/core/pld/src/pld_sdio.h b/core/pld/src/pld_sdio.h
index c0d4647..2ac4cea 100644
--- a/core/pld/src/pld_sdio.h
+++ b/core/pld/src/pld_sdio.h
@@ -33,21 +33,32 @@
 #define PLD_AR6320_DEV_VERSION              0x1000000
 #define PLD_QCA9377_REV1_1_VERSION          0x5020001
 
+#ifdef MULTI_IF_NAME
+#define PREFIX MULTI_IF_NAME
+#else
+#define PREFIX ""
+#endif
+
 struct pld_fw_files fw_files_qca6174_fw_1_1 = {
-	"qwlan11.bin", "bdwlan11.bin", "otp11.bin", "utf11.bin",
-	"utfbd11.bin", "qsetup11.bin", "epping11.bin", ""};
+	PREFIX "qwlan11.bin", PREFIX  "bdwlan11.bin", PREFIX "otp11.bin",
+	PREFIX  "utf11.bin", PREFIX "utfbd11.bin", PREFIX "qsetup11.bin",
+	PREFIX "epping11.bin", ""};
 struct pld_fw_files fw_files_qca6174_fw_2_0 = {
-	"qwlan20.bin", "bdwlan20.bin", "otp20.bin", "utf20.bin",
-	"utfbd20.bin", "qsetup20.bin", "epping20.bin", ""};
+	PREFIX "qwlan20.bin", PREFIX "bdwlan20.bin", PREFIX "otp20.bin",
+	PREFIX "utf20.bin", PREFIX "utfbd20.bin", PREFIX "qsetup20.bin",
+	PREFIX "epping20.bin", ""};
 struct pld_fw_files fw_files_qca6174_fw_1_3 = {
-	"qwlan13.bin", "bdwlan13.bin", "otp13.bin", "utf13.bin",
-	"utfbd13.bin", "qsetup13.bin", "epping13.bin", ""};
+	PREFIX "qwlan13.bin", PREFIX "bdwlan13.bin", PREFIX "otp13.bin",
+	PREFIX "utf13.bin", PREFIX "utfbd13.bin", PREFIX "qsetup13.bin",
+	PREFIX "epping13.bin", ""};
 struct pld_fw_files fw_files_qca6174_fw_3_0 = {
-	"qwlan30.bin", "bdwlan30.bin", "otp30.bin", "utf30.bin",
-	"utfbd30.bin", "qsetup30.bin", "epping30.bin", "qwlan30i.bin"};
+	PREFIX "qwlan30.bin", PREFIX "bdwlan30.bin", PREFIX "otp30.bin",
+	PREFIX "utf30.bin", PREFIX "utfbd30.bin", PREFIX "qsetup30.bin",
+	PREFIX "epping30.bin", PREFIX "qwlan30i.bin"};
 struct pld_fw_files fw_files_default = {
-	"qwlan.bin", "bdwlan.bin", "otp.bin", "utf.bin",
-	"utfbd.bin", "qsetup.bin", "epping.bin", ""};
+	PREFIX "qwlan.bin", PREFIX "bdwlan.bin", PREFIX "otp.bin",
+	PREFIX "utf.bin", PREFIX "utfbd.bin", PREFIX "qsetup.bin",
+	PREFIX "epping.bin", ""};
 #endif
 
 #ifndef CONFIG_SDIO
diff --git a/core/utils/fwlog/dbglog_host.c b/core/utils/fwlog/dbglog_host.c
index d8cb332..a719e45 100644
--- a/core/utils/fwlog/dbglog_host.c
+++ b/core/utils/fwlog/dbglog_host.c
@@ -46,7 +46,12 @@
 #endif /* WLAN_OPEN_SOURCE */
 #include "wmi_unified_priv.h"
 
+#ifdef MULTI_IF_NAME
+#define CLD_DEBUGFS_DIR          "cld" MULTI_IF_NAME
+#else
+
 #define CLD_DEBUGFS_DIR          "cld"
+#endif
 #define DEBUGFS_BLOCK_NAME       "dbglog_block"
 
 #define ATH_MODULE_NAME fwlog
diff --git a/core/utils/nlink/src/wlan_nlink_srv.c b/core/utils/nlink/src/wlan_nlink_srv.c
index cc55b53..312640e 100644
--- a/core/utils/nlink/src/wlan_nlink_srv.c
+++ b/core/utils/nlink/src/wlan_nlink_srv.c
@@ -31,6 +31,14 @@
 * This file contains the definitions specific to the wlan_nlink_srv
 *
 ******************************************************************************/
+/*
+ * If MULTI_IF_NAME is not defined, then this is the primary instance of the
+ * driver and the diagnostics netlink socket will be available. If
+ * MULTI_IF_NAME is defined then this is not the primary instance of the driver
+ * and the diagnotics netlink socket will not be available since this
+ * diagnostics netlink socket can only be exposed by one instance of the driver.
+ */
+#ifndef MULTI_IF_NAME
 
 #include <linux/version.h>
 #include <linux/kernel.h>
@@ -490,5 +498,42 @@
 
 	return -EPERM;
 }
+#endif
+#else /* ifndef MULTI_IF_NAME */
 
+#include <wlan_nlink_srv.h>
+
+int nl_srv_init(void)
+{
+	return 0;
+}
+
+void nl_srv_exit(int dst_pid)
+{
+}
+
+int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
+{
+	return 0;
+}
+
+int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
+{
+	return 0;
+}
+
+int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
+{
+	return 0;
+}
+
+int nl_srv_bcast(struct sk_buff *skb)
+{
+	return 0;
+}
+
+int nl_srv_is_initialized(void)
+{
+	return 0;
+}
 #endif
diff --git a/core/utils/pktlog/linux_ac.c b/core/utils/pktlog/linux_ac.c
index 68c9962..fdc645b 100644
--- a/core/utils/pktlog/linux_ac.c
+++ b/core/utils/pktlog/linux_ac.c
@@ -51,7 +51,11 @@
 #define PKTLOG_DEVNAME_SIZE     32
 #define MAX_WLANDEV             1
 
+#ifdef MULTI_IF_NAME
+#define PKTLOG_PROC_DIR         "ath_pktlog" MULTI_IF_NAME
+#else
 #define PKTLOG_PROC_DIR         "ath_pktlog"
+#endif
 
 /* Permissions for creating proc entries */
 #define PKTLOG_PROC_PERM        0444
diff --git a/uapi/linux/pktlog_ac_fmt.h b/uapi/linux/pktlog_ac_fmt.h
index ff73647..ee5b4ab 100644
--- a/uapi/linux/pktlog_ac_fmt.h
+++ b/uapi/linux/pktlog_ac_fmt.h
@@ -33,11 +33,15 @@
 #define PKTLOG_MAGIC_NUM        7735225
 
 #ifdef __linux__
+#ifdef MULTI_IF_NAME
+#define PKTLOG_PROC_DIR "ath_pktlog" MULTI_IF_NAME
+#define WLANDEV_BASENAME "cld" MULTI_IF_NAME
+#else
 #define PKTLOG_PROC_DIR "ath_pktlog"
-#define PKTLOG_PROC_SYSTEM "system"
 #define WLANDEV_BASENAME "cld"
 #endif
-
+#endif
+#define PKTLOG_PROC_SYSTEM "system"
 #ifdef WIN32
 #pragma pack(push, pktlog_fmt, 1)
 #define __ATTRIB_PACK