[9610] wlbt: SCSC Driver version 10.9.1.0
authorTarun Karela <t.karela@samsung.com>
Wed, 13 Nov 2019 16:04:35 +0000 (16:04 +0000)
committerlingsen1 <lingsen1@lenovo.com>
Tue, 26 Nov 2019 04:20:56 +0000 (12:20 +0800)
SCSC WLBT Driver version 10.9.1.0

[9610] wlbt: Remove SCSC drivers before update

Remove SCSC WLBT drivers before update

Change-Id: I6cd0641767c4bb2834e748a488512e0730a21abe
SCSC-Bug-Id: Rels-3182
Signed-off-by: Tarun Karela <t.karela@samsung.com>
44 files changed:
drivers/misc/samsung/scsc/Kconfig
drivers/misc/samsung/scsc/mif_reg_S5E3830.h
drivers/misc/samsung/scsc/mif_reg_S5E9630.h
drivers/misc/samsung/scsc/mxman.c
drivers/misc/samsung/scsc/platform_mif_3830.c [changed mode: 0644->0755]
drivers/misc/samsung/scsc/platform_mif_9610.c
drivers/misc/samsung/scsc/platform_mif_9630.c
drivers/misc/samsung/scsc/scsc_wifilogger_core.c
drivers/misc/samsung/scsc_bt/scsc_ant.c
drivers/misc/samsung/scsc_bt/scsc_bt_module.c
drivers/misc/samsung/scsc_bt/scsc_bt_priv.h
drivers/misc/samsung/scsc_bt/scsc_shm.c
drivers/net/wireless/scsc/Kconfig
drivers/net/wireless/scsc/Makefile
drivers/net/wireless/scsc/cac.c
drivers/net/wireless/scsc/cfg80211_ops.c
drivers/net/wireless/scsc/cm_if.c
drivers/net/wireless/scsc/dev.c
drivers/net/wireless/scsc/dev.h
drivers/net/wireless/scsc/fapi.h
drivers/net/wireless/scsc/hip4.c
drivers/net/wireless/scsc/ioctl.c
drivers/net/wireless/scsc/mgt.c
drivers/net/wireless/scsc/mgt.h
drivers/net/wireless/scsc/mlme.c
drivers/net/wireless/scsc/mlme.h
drivers/net/wireless/scsc/mlme_nan.c
drivers/net/wireless/scsc/netif.c
drivers/net/wireless/scsc/netif.h
drivers/net/wireless/scsc/nl80211_vendor.c
drivers/net/wireless/scsc/nl80211_vendor.h
drivers/net/wireless/scsc/nl80211_vendor_nan.c
drivers/net/wireless/scsc/nl80211_vendor_nan.h
drivers/net/wireless/scsc/procfs.c
drivers/net/wireless/scsc/reg_info.c [new file with mode: 0755]
drivers/net/wireless/scsc/reg_info.h [new file with mode: 0755]
drivers/net/wireless/scsc/rx.c
drivers/net/wireless/scsc/sap_ma.c
drivers/net/wireless/scsc/sap_mlme.c
drivers/net/wireless/scsc/scsc_wifi_cm_if.h
drivers/net/wireless/scsc/tx.c
drivers/net/wireless/scsc/utils.h
include/scsc/api/bsmhcp.h
include/scsc/scsc_release.h

index 260c600460748c9020f37450a817656821408fa5..f9090c5f00e6c217322d32b32db7cf0fc5742984 100644 (file)
@@ -170,7 +170,7 @@ config SCSC_LOG_COLLECTION
 config SCSC_COMMON_HCF
        bool "Enable Common HCF loader"
        depends on SCSC_CORE
-       default n
+       default y
        ---help---
          Enable Common HCF loader
 
index 0b12dbe65ed58903da116a37e5a54b4b1440758a..912cfe6085907ff123716fdf0f9d649185a45699 100644 (file)
 
 /* Exynos 3830 UM - TODO */
 #define TOP_OUT                        0x3920
-#define PWRRGTON_CP            BIT(1) /* XPWRRTON_CP control 0: Disable 1: Enable */
+#define PWRRGTON_CP            BIT(1) /* XPWRRTON_CP contr */
+
+#define WAKEUP_INT_TYPE 0x3948
+#define RESETREQ_WLBT   BIT(25) /* Interrupt type 0:Edge, 1:Level */
 
 /* Exynos 3830 UM - TODO */
 #define TCXO_BUF_CTRL          0x3B78
index eb525861029865c83e72eb1a86fd6f07bb5e8b19..0fdbe5867437eb422d4151b7680ca279fad2eaa5 100644 (file)
 #define CLEANY_BUS_WLBT_STATUS 0x3B24
 #define CLEANY_STATUS_MASK     (BIT(17)|BIT(16))
 
+/* Exynos9630 UM_REV0.31 - 9.7.1.748 */
+#define WAKEUP_INT_TYPE 0x3948
+#define RESETREQ_WLBT   BIT(18) /* Interrupt type 0:Edge, 1:Level */
+
 /* Exynos 9630 UM - 9.8.763 */
 #define SYSTEM_OUT             0x3A20
 #define PWRRGTON_CON           BIT(9) /* XPWRRTON_CON control 0: Disable 1: Enable */
index dcd3567e8f193e9ccb6b403b5966f3fc3340a70b..8bfc90c9379457f52e3c330dfe85aa8e7a468436 100755 (executable)
@@ -1347,7 +1347,7 @@ static bool is_bug_on_enabled(struct scsc_mx *mx)
        const struct firmware *firm;
        int r;
 
-       if (memdump == 3)
+       if ((memdump == 3) && (disable_recovery_handling == MEMDUMP_FILE_FOR_RECOVERY))
                bug_on_enabled = true;
        else
                bug_on_enabled = false;
old mode 100644 (file)
new mode 100755 (executable)
index f2199c4..2b5008b
@@ -583,7 +583,7 @@ irqreturn_t platform_alive_isr(int irq, void *data)
 
 irqreturn_t platform_wdog_isr(int irq, void *data)
 {
-       //int ret = 0;
+       int ret = 0;
        struct platform_mif *platform = (struct platform_mif *)data;
 
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n");
@@ -597,15 +597,14 @@ irqreturn_t platform_wdog_isr(int irq, void *data)
                atomic_inc(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt);
        }
 
-       /* TODO: need to find correct register to set here */
-#if 0
-       ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS,
-                                WLBT_RESET_REQ_CLR, WLBT_RESET_REQ_CLR);
-       SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Clearing WLBT_RESET_REQ\n");
-       if (ret < 0)
-               SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
-                                "Failed to Set WLBT_CTRL_NS[WLBT_RESET_REQ_CLR]: %d\n", ret);
-#endif
+       /* The wakeup source isn't cleared until WLBT is reset, so change the interrupt type to suppress this */
+       if (mxman_recovery_disabled()) {
+               ret = regmap_update_bits(platform->pmureg, WAKEUP_INT_TYPE,
+                               RESETREQ_WLBT, 0);
+               SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Set RESETREQ_WLBT wakeup interrput type to EDGE.\n");
+               if (ret < 0)
+                       SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Failed to Set WAKEUP_INT_TYPE[RESETREQ_WLBT]: %d\n", ret);
+       }
 
        return IRQ_HANDLED;
 }
@@ -688,7 +687,7 @@ irqreturn_t platform_cfg_req_isr(int irq, void *data)
        /*s32 ret = 0;*/
        unsigned int ka_addr = 0x1000;
        uint32_t *ka_patch_addr = ka_patch;
-       //u32 id;
+       //unsigned int id;
 
 #define CHECK(x) do { \
        int retval = (x); \
@@ -820,7 +819,7 @@ irqreturn_t platform_cfg_req_isr(int irq, void *data)
 
        while (ka_patch_addr < (ka_patch + ARRAY_SIZE(ka_patch))) {
                CHECK(regmap_write(platform->boot_cfg, ka_addr, *ka_patch_addr));
-               ka_addr += sizeof(ka_patch[0]);
+               ka_addr += (unsigned int)sizeof(ka_patch[0]);
                ka_patch_addr++;
        }
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "KA patch done\n");
@@ -841,9 +840,6 @@ irqreturn_t platform_cfg_req_isr(int irq, void *data)
        /* Signal triggering function that the IRQ arrived and CFG was done */
        complete(&platform->cfg_ack);
 
-       /* Re-enable IRQ here to allow spurious interrupt to be tracked */
-       enable_irq(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num);
-
        /* as per wlbt_if_S5E3830.c - end */
 
        return IRQ_HANDLED;
@@ -1011,7 +1007,6 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
        struct platform_mif *platform = platform_mif_from_mif_abs(interface);
        int             ret = 0;
        u32             val = 0;
-       u32             v = 0;
        unsigned long   timeout;
        static bool     init_done;
 
@@ -1025,25 +1020,26 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
         * Cold reset wrt. AP power sequencer, cold reset for WLBT
         */
        if (!init_done) {
-               /* init sequence from excite - PMUCAL
-                * SetBits((uinteger)REG_WLBT_CTRL_S, WLBT_CTRL_S_START_POS, 0x1, 0x1);
-                * SetBits((uinteger)REG_WLBT_OPTION, 3, 0x1, 0x1);
-                * udelay(1000);
-                * SetBits((uinteger)REG_TOP_OUT, 1, 0x1, 0x1);
-                * while (GetBits((uinteger)REG_VGPIO_TX_MONITOR, 29, 0x1) != 1)
-                * ;
-                * SetBits((uinteger)REG_WLBT_CONFIGURATION, WLBT_CONFIGURATION_LOCAL_PWR_CFG_POS, 0x1, 0x1);
-                * while (GetBits((uinteger)REG_WLBT_STATUS, 0, 0x1) != WLBT_STATUS_STATUS_POWERON)
-                *      ;
-                * SetBits((uinteger)REG_WLBT_CTRL_NS, WLBT_CTRL_NS_ACTIVE_CLR_POS, 0x1, 0x0);
-                * SetBits((uinteger)REG_WLBT_CTRL_NS, WLBT_CTRL_NS_ACTIVE_EN_POS, 0x1, 0x1);
+               /* init sequence from excite/email - PMUCAL v2
+                *
+                * access type  SFR Name                Address         Field   value
+                * write        WLBT_CTRL_S             0x####_3114     [3]     0x1
+                * write        WLBT_OPTION             0x####_310C     [3]     0x1
+                * delay        delay   ã€€     ã€€     0x3
+                * write        TOP_OUT                 0x####_3920     [1]     0x1
+                * read-till    VGPIO_TX_MONITOR        0x####_1700     [29]    0x1
+                * delay        delay   ã€€     ã€€     0x3E8
+                * write        WLBT_CONFIGURATION      0x####_3100     [0]     0x1
+                * read-till    WLBT_STATUS             0x####_3104     [0]     0x1
+                * write        WLBT_CTRL_NS            0x####_3110     [6]     0x0
+                * write        WLBT_CTRL_NS            0x####_3110     [5]     0x1
                 *
                 */
                SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "init\n");
 
                /* WLBT_CTRL_S[WLBT_START] = 1 enable */
                ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_S,
-                               WLBT_START, WLBT_START);
+                               BIT(3), BIT(3)); /* WLBT_START */
                if (ret < 0) {
                        SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                                        "Failed to update WLBT_CTRL_S[WLBT_START]: %d\n", ret);
@@ -1055,7 +1051,7 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
 
                /* WLBT_OPTION[WLBT_OPTION_DATA] = 1 Power On */
                ret = regmap_update_bits(platform->pmureg, WLBT_OPTION,
-                               WLBT_OPTION_DATA, WLBT_OPTION_DATA);
+                               BIT(3), BIT(3)); /* WLBT_OPTION_DATA */
                if (ret < 0) {
                        SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                                "Failed to update WLBT_OPTION[WLBT_OPTION_DATA]: %d\n", ret);
@@ -1067,7 +1063,7 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
 
                /* TOP_OUT[PWRRGTON_CP] = 1 Power On */
                ret = regmap_update_bits(platform->pmureg, TOP_OUT,
-                               PWRRGTON_CP, PWRRGTON_CP);
+                               BIT(1), BIT(1)); /* PWRRGTON_CP */
                if (ret < 0) {
                        SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                                "Failed to update TOP_OUT[PWRRGTON_CP]: %d\n", ret);
@@ -1081,7 +1077,7 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
                timeout = jiffies + msecs_to_jiffies(500);
                do {
                        regmap_read(platform->i3c_apm_pmic, VGPIO_TX_MONITOR, &val);
-                       val &= (u32)VGPIO_TX_MON_BIT29;
+                       val &= (u32)BIT(29); /* VGPIO_TX_MON_BIT29 */
                        if (val) {
                                SCSC_TAG_INFO(PLAT_MIF, "VGPIO_TX_MONITOR 0x%x\n", val);
                                break;
@@ -1096,7 +1092,7 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
 
                /* WLBT_CONFIGURATION[LOCAL_PWR_CFG] = 1 Power On */
                ret = regmap_update_bits(platform->pmureg, WLBT_CONFIGURATION,
-                               LOCAL_PWR_CFG, 0x1);
+                               BIT(0), BIT(0)); /* LOCAL_PWR_CFG */
                if (ret < 0) {
                        SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                                "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret);
@@ -1110,14 +1106,10 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
                timeout = jiffies + msecs_to_jiffies(500);
                do {
                        regmap_read(platform->pmureg, WLBT_STATUS, &val);
-                       val &= (u32)WLBT_STATUS_BIT0;
+                       val &= (u32)BIT(0); /* WLBT_STATUS_BIT0 */
                        if (val) {
                                /* Power On complete */
                                SCSC_TAG_INFO(PLAT_MIF, "Power On complete: WLBT_STATUS 0x%x\n", val);
-                               /* re affirming power on by reading WLBT_STATES */
-                               /* STATES[7:0] = 0x10 for Power Up */
-                               regmap_read(platform->pmureg, WLBT_STATES, &v);
-                               SCSC_TAG_INFO(PLAT_MIF, "Power On complete: WLBT_STATES 0x%x\n", v);
                                break;
                        }
                } while (time_before(jiffies, timeout));
@@ -1125,12 +1117,12 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
                if (!val) {
                        regmap_read(platform->pmureg, WLBT_STATUS, &val);
                        SCSC_TAG_INFO(PLAT_MIF, "timeout waiting for power on time-out: "
-                                               "WLBT_STATUS 0x%x, WLBT_STATES 0x%x\n", val, v);
+                                       "WLBT_STATUS 0x%x\n", val);
                }
 
                /* WLBT_CTRL_NS[WLBT_ACTIVE_CLR] = 0 Active interrupt clear */
                ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS,
-                               WLBT_ACTIVE_CLR, 0x0);
+                               BIT(6), 0x0); /* WLBT_ACTIVE_CLR */
                if (ret < 0) {
                        SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                                "Failed to update WLBT_CTRL_NS[WLBT_ACTIVE_CLR]: %d\n", ret);
@@ -1142,7 +1134,7 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
 
                /* WLBT_CTRL_NS[WLBT_ACTIVE_EN] = 1 Active interrupt enable */
                ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS,
-                               WLBT_ACTIVE_EN, WLBT_ACTIVE_EN);
+                               BIT(5), BIT(5)); /* WLBT_ACTIVE_EN */
                if (ret < 0) {
                        SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                                "Failed to update WLBT_CTRL_NS[WLBT_ACTIVE_EN]: %d\n", ret);
@@ -1158,133 +1150,51 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
        }
 
        /* RESET RELEASE - Subsequent WLBT reboots */
-       /* wlbt_if_reset_release - from excite code
-        * SetBits((uinteger)REG_WLBT_CONFIGURATION, WLBT_CONFIGURATION_LOCAL_PWR_CFG_POS, 0x1, 0x1);
-        * while (GetBits((uinteger)REG_WLBT_STATUS, WLBT_STATUS_STATUS_POS, 0x1) != WLBT_STATUS_STATUS_POWERON)
-        *      ;
-        * SetBits((uinteger)REG_WLBT_INT_EN, WLBT_INT_EN_PWR_REQ__F_POS, 0x1, 0x1);
-        * SetBits((uinteger)REG_WLBT_INT_EN, WLBT_INT_EN_TCXO_REQ__F_POS, 0x1, 0x1);
-        * udelay(2000);
+       /* wlbt_if_reset_release - from excite/email code PMUCAL v2
+        * access type  SFR Name                Address         Field   value
+        *
+        * write        WLBT_OPTION             0x####_310C     [3]     0x1
+        * write        MIF_CTRL                0x####_3810     [0]     0x1
+        * write        TCXO_BUF_CTRL           0x####_3b78     [0]     0x1
+        * write        TOP_OUT                 0x####_3920     [1]     0x1
+        * read-till    VGPIO_TX_MONITOR        0x####_1700     [29]    0x1
+        * delay        delay   ã€€     ã€€     0x3e8
+        * write        WLBT_CONFIGURATION      0x####_3100     [0]     0x1
+        * read-till    WLBT_STATUS             0x####_3104     [0]     0x1
+        * write        WLBT_INT_EN             0x####_3144     [3]     0x1
+        * write        WLBT_INT_EN             0x####_3144     [5]     0x1
+        * write        WLBT_CTRL_NS            0x####_3110     [6]     0x0
+        * write        WLBT_CTRL_NS            0x####_3110     [5]     0x1
+        *
         * */
 
        /* Warm reset wrt. AP power sequencer, but cold reset for WLBT */
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "release\n");
 
-       /* Power Up */
-       ret = regmap_update_bits(platform->pmureg, WLBT_CONFIGURATION,
-                       LOCAL_PWR_CFG, 0x1);
-       if (ret < 0) {
-               SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
-                       "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret);
-               return ret;
-       }
-       regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val);
-       SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
-               "updated successfully WLBT_CONFIGURATION[LOCAL_PWR_CFG]: 0x%x\n", val);
-
-       /* wait for power up complete WLBT_STATUS[0] = 0 for power down */
-       timeout = jiffies + msecs_to_jiffies(500);
-       do {
-               regmap_read(platform->pmureg, WLBT_STATUS, &val);
-               val &= (u32)WLBT_STATUS_BIT0;
-               if (val) {
-                       /* Power up complete */
-                       SCSC_TAG_INFO(PLAT_MIF, "Power up complete: WLBT_STATUS 0x%x\n", val);
-                       /* re affirming power down by reading WLBT_STATES */
-                       /* STATES[7:0] = 0x10 for Power Up */
-                       regmap_read(platform->pmureg, WLBT_STATES, &v);
-                       SCSC_TAG_INFO(PLAT_MIF, "Power up complete: WLBT_STATES 0x%x\n", v);
-                       break;
-               }
-       } while (time_before(jiffies, timeout));
-
-       if (!val) {
-               regmap_read(platform->pmureg, WLBT_STATUS, &val);
-               SCSC_TAG_INFO(PLAT_MIF, "Timeout waiting for Power up complete: "
-                                       "WLBT_STATUS 0x%x, WLBT_STATES 0x%x\n", val, v);
-       }
-
-       /* enable PWR_REQ_F and TCXO_REQ_F interrupts */
-       ret = regmap_update_bits(platform->pmureg, WLBT_INT_EN,
-                       PWR_REQ_F, PWR_REQ_F);
-       if (ret < 0) {
-               SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
-                       "Failed to update WLBT_INT_EN[PWR_REQ_F]: %d\n", ret);
-               return ret;
-       }
-       regmap_read(platform->pmureg, WLBT_INT_EN, &val);
-       SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
-               "updated successfully WLBT_INT_EN[PWR_REQ_F]: 0x%x\n", val);
-
-       ret = regmap_update_bits(platform->pmureg, WLBT_INT_EN,
-                       TCXO_REQ_F, TCXO_REQ_F);
-       if (ret < 0) {
-               SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
-                       "Failed to update WLBT_INT_EN[TCXO_REQ_F]: %d\n", ret);
-               return ret;
-       }
-       regmap_read(platform->pmureg, WLBT_INT_EN, &val);
-       SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
-               "updated successfully WLBT_INT_EN[TCXO_REQ_F]: 0x%x\n", val);
-
-init_code_done:
-       /* Now handle the CFG_REQ IRQ */
-       enable_irq(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num);
-
-       ret = platform_mif_start(interface, true);
-       if (ret)
-               return ret;
-
-       return ret;
-}
-
-static int platform_mif_pmu_reset_assert(struct scsc_mif_abs *interface)
-{
-       struct platform_mif *platform = platform_mif_from_mif_abs(interface);
-       unsigned long       timeout;
-       int                 ret;
-       u32                 val;
-
-       /* wlbt_if_reset_assertion() - from wlbt_if_S5E3830.c - PMUCAL
-        * SetBits((uinteger)REG_WLBT_OPTION, 3, 0x1, 0x1);
-        * SetBits((uinteger)REG_MIF_CTRL, MIF_CTRL_TCXO_EN_POS, 0x1, 0x1);
-        * SetBits((uinteger)REG_TCXO_BUF_CTRL, TCXO_BUF_CTRL_BIAS_EN_POS, 0x1, 0x1);
-        * SetBits((uinteger)REG_TOP_OUT, TOP_OUT_PWRRGTON_CP_POS, 0x1, 0x1);
-        * while (GetBits((uinteger)REG_VGPIO_TX_MONITOR, 29, 0x1) != 1)
-        *      ;
-        * udelay(1000);        //1 msec wait???
-        * SetBits((uinteger)REG_WLBT_INT_EN, WLBT_INT_EN_PWR_REQ__F_POS, 0x00000001, 0x00000000);
-        * SetBits((uinteger)REG_WLBT_INT_EN, WLBT_INT_EN_TCXO_REQ__F_POS, 0x00000001, 0x00000000);
-        * SetBits((uinteger)REG_WLBT_CTRL_NS, WLBT_CTRL_NS_ACTIVE_EN_POS, 0x1, 0x0);
-        * SetBits((uinteger)REG_WLBT_CONFIGURATION, WLBT_CONFIGURATION_LOCAL_PWR_CFG_POS, 0x1, 0x0);
-        * while (GetBits((uinteger)REG_WLBT_STATUS, WLBT_STATUS_STATUS_POS, 0x1) != WLBT_STATUS_STATUS_POWERDOWN)
-        */
-
-       /* WLBT_OPTION[WLBT_OPTION_DATA] = 1 Power On */
        ret = regmap_update_bits(platform->pmureg, WLBT_OPTION,
-                       WLBT_OPTION_DATA, WLBT_OPTION_DATA);
+                       BIT(3), BIT(3)); /* WLBT_OPTION_DATA */
        if (ret < 0) {
                SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
-                               "Failed to update WLBT_OPTION[WLBT_OPTION_DATA]: %d\n", ret);
+                       "Failed to update WLBT_OPTION[WLBT_OPTION_DATA]: %d\n", ret);
                return ret;
        }
        regmap_read(platform->pmureg, WLBT_OPTION, &val);
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
-                       "updated successfully WLBT_OPTION[WLBT_OPTION_DATA]: 0x%x\n", val);
+               "updated successfully WLBT_OPTION[WLBT_OPTION_DATA]: 0x%x\n", val);
 
        ret = regmap_update_bits(platform->pmureg, MIF_CTRL,
-                       TCXO_EN, TCXO_EN);
+                       BIT(0), BIT(0)); /* TCXO_EN */
        if (ret < 0) {
                SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                        "Failed to update MIF_CTRL[TCXO_EN]: %d\n", ret);
                return ret;
        }
-       regmap_read(platform->pmureg, TCXO_BUF_CTRL, &val);
+       regmap_read(platform->pmureg, MIF_CTRL, &val);
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
                "updated successfully MIF_CTRL[TCXO_EN]: 0x%x\n", val & TCXO_EN);
 
        ret = regmap_update_bits(platform->pmureg, TCXO_BUF_CTRL,
-                       TCXO_BUF_BIAS_EN_WLBT, TCXO_BUF_BIAS_EN_WLBT);
+                       BIT(0), BIT(0)); /* TCXO_BUF_BIAS_EN_WLBT */
        if (ret < 0) {
                SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                        "Failed to update TCXO_BUF_CTRL[TCXO_BUF_BIAS_EN_WLBT]: %d\n", ret);
@@ -1295,7 +1205,7 @@ static int platform_mif_pmu_reset_assert(struct scsc_mif_abs *interface)
                "updated successfully TCXO_BUF_CTRL[TCXO_BUF_BIAS_EN_WLBT]: 0x%x\n", val & TCXO_BUF_BIAS_EN_WLBT);
 
        ret = regmap_update_bits(platform->pmureg, TOP_OUT,
-                       PWRRGTON_CP, PWRRGTON_CP);
+                       BIT(1), BIT(1)); /* PWRRGTON_CP */
 
        if (ret < 0) {
                SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
@@ -1306,7 +1216,7 @@ static int platform_mif_pmu_reset_assert(struct scsc_mif_abs *interface)
        timeout = jiffies + msecs_to_jiffies(500);
        do {
                regmap_read(platform->i3c_apm_pmic, VGPIO_TX_MONITOR, &val);
-               val &= (u32)VGPIO_TX_MON_BIT29;
+               val &= (u32)BIT(29); /* VGPIO_TX_MON_BIT29 */
                if (val) {
                        SCSC_TAG_INFO(PLAT_MIF, "VGPIO_TX_MONITOR 0x%x\n", val);
                        break;
@@ -1319,15 +1229,39 @@ static int platform_mif_pmu_reset_assert(struct scsc_mif_abs *interface)
                                "VGPIO_TX_MONITOR 0x%x\n", val);
        }
 
-       regmap_read(platform->pmureg, TCXO_BUF_CTRL, &val);
+       /* Power Up */
+       ret = regmap_update_bits(platform->pmureg, WLBT_CONFIGURATION,
+                       BIT(0), BIT(0)); /* LOCAL_PWR_CFG */
+       if (ret < 0) {
+               SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
+                       "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret);
+               return ret;
+       }
+       regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val);
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
-               "updated successfully TOP_OUT[PWRRGTON_CP]: 0x%x\n", val & PWRRGTON_CP);
+               "updated successfully WLBT_CONFIGURATION[LOCAL_PWR_CFG]: 0x%x\n", val);
 
-       udelay(1000);
+       /* wait for power up complete WLBT_STATUS[0] = 0 for power down */
+       timeout = jiffies + msecs_to_jiffies(500);
+       do {
+               regmap_read(platform->pmureg, WLBT_STATUS, &val);
+               val &= (u32)BIT(0); /* WLBT_STATUS_BIT0 */
+               if (val) {
+                       /* Power up complete */
+                       SCSC_TAG_INFO(PLAT_MIF, "Power up complete: WLBT_STATUS 0x%x\n", val);
+                       break;
+               }
+       } while (time_before(jiffies, timeout));
+
+       if (!val) {
+               regmap_read(platform->pmureg, WLBT_STATUS, &val);
+               SCSC_TAG_INFO(PLAT_MIF, "Timeout waiting for Power up complete: "
+                       "WLBT_STATUS 0x%x\n", val);
+       }
 
-       /* disable PWR_REQ_F and TCXO_REQ_F interrupts */
+       /* enable PWR_REQ_F and TCXO_REQ_F interrupts */
        ret = regmap_update_bits(platform->pmureg, WLBT_INT_EN,
-                       PWR_REQ_F, 0x0);
+                       BIT(3), BIT(3)); /* PWR_REQ_F */
        if (ret < 0) {
                SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                        "Failed to update WLBT_INT_EN[PWR_REQ_F]: %d\n", ret);
@@ -1338,7 +1272,7 @@ static int platform_mif_pmu_reset_assert(struct scsc_mif_abs *interface)
                "updated successfully WLBT_INT_EN[PWR_REQ_F]: 0x%x\n", val);
 
        ret = regmap_update_bits(platform->pmureg, WLBT_INT_EN,
-                       TCXO_REQ_F, 0x0);
+                       BIT(5), BIT(5)); /* TCXO_REQ_F */
        if (ret < 0) {
                SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                        "Failed to update WLBT_INT_EN[TCXO_REQ_F]: %d\n", ret);
@@ -1348,9 +1282,60 @@ static int platform_mif_pmu_reset_assert(struct scsc_mif_abs *interface)
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
                "updated successfully WLBT_INT_EN[TCXO_REQ_F]: 0x%x\n", val);
 
+       /* WLBT_CTRL_NS[WLBT_ACTIVE_CLR] = 0 Active interrupt clear */
+       ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS,
+                       BIT(6), 0x0);
+       if (ret < 0) {
+               SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
+                       "Failed to update WLBT_CTRL_NS[WLBT_ACTIVE_CLR]: %d\n", ret);
+               return ret;
+       }
+       regmap_read(platform->pmureg, WLBT_CTRL_NS, &val);
+       SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
+               "updated successfully WLBT_CTRL_NS[WLBT_ACTIVE_CLR]: 0x%x\n", val);
+
+       /* WLBT_CTRL_NS[WLBT_ACTIVE_EN] = 1 Active interrupt enable */
+       ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS,
+                       BIT(5), BIT(5)); /* WLBT_ACTIVE_EN */
+       if (ret < 0) {
+               SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
+                       "Failed to update WLBT_CTRL_NS[WLBT_ACTIVE_EN]: %d\n", ret);
+               return ret;
+       }
+       regmap_read(platform->pmureg, WLBT_CTRL_NS, &val);
+       SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
+               "updated successfully WLBT_CTRL_NS[WLBT_ACTIVE_EN]: 0x%x\n", val);
+
+init_code_done:
+       /* Now handle the CFG_REQ IRQ */
+       enable_irq(platform->wlbt_irq[PLATFORM_MIF_CFG_REQ].irq_num);
+
+       ret = platform_mif_start(interface, true);
+       if (ret)
+               return ret;
+
+       return ret;
+}
+
+static int platform_mif_pmu_reset_assert(struct scsc_mif_abs *interface)
+{
+       struct platform_mif *platform = platform_mif_from_mif_abs(interface);
+       unsigned long       timeout;
+       int                 ret;
+       u32                 val;
+
+       /* wlbt_if_reset_assertion - from excite/email PMUCAL v2
+        *
+        * access type  SFR Name                Address         Field   value
+        * write        WLBT_CTRL_NS            0x####_3110     [5]     0x0
+        * write        WLBT_CONFIGURATION      0x####_3100     [0]     0x0
+        * read-till    WLBT_STATUS             0x####_3104     [0]     0x0
+        *
+        */
+
        /* Active interrupt disable */
        ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS,
-               WLBT_ACTIVE_EN, 0x0);
+                       BIT(5), 0x0); /* WLBT_ACTIVE_EN */
        if (ret < 0) {
                SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                        "Failed to update WLBT_CTRL_NS[WLBT_ACTIVE_EN]: %d\n", ret);
@@ -1361,8 +1346,8 @@ static int platform_mif_pmu_reset_assert(struct scsc_mif_abs *interface)
                "updated successfully WLBT_CTRL_NS[WLBT_ACTIVE_EN]: 0x%x\n", val);
 
        /* Power Down */
-       ret = regmap_write_bits(platform->pmureg, WLBT_CONFIGURATION,
-               LOCAL_PWR_CFG, 0x0);
+       ret = regmap_update_bits(platform->pmureg, WLBT_CONFIGURATION,
+                       BIT(0), 0x0); /* LOCAL_PWR_CFG */
        if (ret < 0) {
                SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                        "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret);
@@ -1376,14 +1361,9 @@ static int platform_mif_pmu_reset_assert(struct scsc_mif_abs *interface)
        timeout = jiffies + msecs_to_jiffies(500);
        do {
                regmap_read(platform->pmureg, WLBT_STATUS, &val);
-               val &= (u32)WLBT_STATUS_BIT0;
+               val &= (u32)BIT(0); /* WLBT_STATUS_BIT0 */
                if (val == 0) {
                        SCSC_TAG_INFO(PLAT_MIF, "WLBT_STATUS 0x%x\n", val);
-                       /* re affirming power down by reading WLBT_STATES */
-                       /* STATES[7:0] = 0x80 for Power Down */
-                       regmap_read(platform->pmureg, WLBT_STATES, &val);
-                       SCSC_TAG_INFO(PLAT_MIF, "Power down complete: WLBT_STATES 0x%x\n", val);
-
                        return 0; /* OK - return */
                }
        } while (time_before(jiffies, timeout));
@@ -1431,7 +1411,7 @@ static int platform_mif_reset(struct scsc_mif_abs *interface, bool reset)
 
 static void __iomem *platform_mif_map_region(unsigned long phys_addr, size_t size)
 {
-       int         i;
+       size_t      i;
        struct page **pages;
        void        *vmem;
 
@@ -2188,7 +2168,8 @@ void platform_mif_resume(struct scsc_mif_abs *interface)
 
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Clear WLBT_ACTIVE_CLR flag\n");
        /* Clear WLBT_ACTIVE_CLR flag in WLBT_CTRL_NS */
-       ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS, WLBT_ACTIVE_CLR, 1);
+       ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_NS,
+                       BIT(6), BIT(6)); /* WLBT_ACTIVE_CLR*/
        if (ret < 0) {
                SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
                        "Failed to Set WLBT_CTRL_NS[WLBT_ACTIVE_CLR]: %d\n", ret);
index ff37b6706222bb9e79ff2bcc6bb6d13da19d8d7f..d072417e243a888b6054ec7bbcc373b09cf72890 100644 (file)
@@ -685,7 +685,7 @@ irqreturn_t platform_cfg_req_isr(int irq, void *data)
        s32 ret = 0;
        unsigned int ka_addr = 0x1000;
        uint32_t *ka_patch_addr = ka_patch;
-       u32 id;
+       unsigned int id;
 
 #define CHECK(x) do { \
        int retval = (x); \
@@ -799,7 +799,7 @@ irqreturn_t platform_cfg_req_isr(int irq, void *data)
 
        while (ka_patch_addr < (ka_patch + ARRAY_SIZE(ka_patch))) {
                CHECK(regmap_write(platform->boot_cfg, ka_addr, *ka_patch_addr));
-               ka_addr += sizeof(ka_patch[0]);
+               ka_addr += (unsigned int)sizeof(ka_patch[0]);
                ka_patch_addr++;
        }
 
@@ -1196,7 +1196,7 @@ static int platform_mif_reset(struct scsc_mif_abs *interface, bool reset)
 
 static void __iomem *platform_mif_map_region(unsigned long phys_addr, size_t size)
 {
-       int         i;
+       size_t      i;
        struct page **pages;
        void        *vmem;
 
index 5f31b1ae30480f57ab23a42110a81a36a7fec97f..60b46984d011d363b79b24353866aa4da67bf91e 100644 (file)
@@ -31,6 +31,7 @@
 #include <scsc/scsc_logring.h>
 #include "mif_reg_S5E9630.h"
 #include "platform_mif_module.h"
+#include "mxman.h"
 #ifdef CONFIG_ARCH_EXYNOS
 #include <linux/soc/samsung/exynos-soc.h>
 #endif
@@ -72,10 +73,12 @@ static bool enable_platform_mif_arm_reset = true;
 module_param(enable_platform_mif_arm_reset, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(enable_platform_mif_arm_reset, "Enables WIFIBT ARM cores reset");
 
-static bool disable_apm_setup;
+static bool disable_apm_setup = true;
 module_param(disable_apm_setup, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(disable_apm_setup, "Disable host APM setup");
 
+static bool init_done;
+
 #ifdef CONFIG_SCSC_QOS
 struct qos_table {
        unsigned int freq_mif;
@@ -587,6 +590,7 @@ irqreturn_t platform_alive_isr(int irq, void *data)
 
 irqreturn_t platform_wdog_isr(int irq, void *data)
 {
+       int ret = 0;
        struct platform_mif *platform = (struct platform_mif *)data;
 
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "INT received\n");
@@ -600,6 +604,15 @@ irqreturn_t platform_wdog_isr(int irq, void *data)
                atomic_inc(&platform->wlbt_irq[PLATFORM_MIF_WDOG].irq_disabled_cnt);
        }
 
+       /* The wakeup source isn't cleared until WLBT is reset, so change the interrupt type to suppress this */
+       if (mxman_recovery_disabled()) {
+               ret = regmap_update_bits(platform->pmureg, WAKEUP_INT_TYPE,
+                               RESETREQ_WLBT, 0);
+               SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "Set RESETREQ_WLBT wakeup interrput type to EDGE.\n");
+               if (ret < 0)
+                       SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev, "Failed to Set WAKEUP_INT_TYPE[RESETREQ_WLBT]: %d\n", ret);
+       }
+
        return IRQ_HANDLED;
 }
 
@@ -672,7 +685,7 @@ irqreturn_t platform_cfg_req_isr(int irq, void *data)
        /*s32 ret = 0;*/
        unsigned int ka_addr = 0x1000;
        uint32_t *ka_patch_addr = ka_patch;
-       u32 id;
+       unsigned int id;
 
 #define CHECK(x) do { \
        int retval = (x); \
@@ -814,7 +827,7 @@ irqreturn_t platform_cfg_req_isr(int irq, void *data)
 
        while (ka_patch_addr < (ka_patch + ARRAY_SIZE(ka_patch))) {
                CHECK(regmap_write(platform->boot_cfg, ka_addr, *ka_patch_addr));
-               ka_addr += sizeof(ka_patch[0]);
+               ka_addr += (unsigned int)sizeof(ka_patch[0]);
                ka_patch_addr++;
        }
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "KA patch done\n");
@@ -1083,17 +1096,20 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
         */
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev, "init\n");
 
-       /* WLBT_CTRL_S[WLBT_START] = 1 enable */
-       ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_S,
-                       WLBT_START, WLBT_START);
-       if (ret < 0) {
-               SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
-                               "Failed to update WLBT_CTRL_S[WLBT_START]: %d\n", ret);
-               return ret;
+       if (!init_done) {
+               /* WLBT_CTRL_S[WLBT_START] = 1 enable */
+               ret = regmap_update_bits(platform->pmureg, WLBT_CTRL_S,
+                               WLBT_START, WLBT_START);
+               if (ret < 0) {
+                       SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
+                                       "Failed to update WLBT_CTRL_S[WLBT_START]: %d\n", ret);
+                       return ret;
+               }
+               regmap_read(platform->pmureg, WLBT_CTRL_S, &val);
+               SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
+                       "updated successfully WLBT_CTRL_S[WLBT_START]: 0x%x\n", val);
+               init_done = true;
        }
-       regmap_read(platform->pmureg, WLBT_CTRL_S, &val);
-       SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
-               "updated successfully WLBT_CTRL_S[WLBT_START]: 0x%x\n", val);
 
        /* WLBT_OPTION[WLBT_OPTION_DATA] = 1 Power On */
        ret = regmap_update_bits(platform->pmureg, WLBT_OPTION,
@@ -1119,25 +1135,13 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
        SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
                "updated successfully SYSTEM_OUT[PWRRGTON_CON]: 0x%x\n", val);
 
-       /* WLBT_CONFIGURATION[LOCAL_PWR_CFG] = 1 Power On */
-       ret = regmap_update_bits(platform->pmureg, WLBT_CONFIGURATION,
-                       LOCAL_PWR_CFG, LOCAL_PWR_CFG);
-       if (ret < 0) {
-               SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
-                       "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret);
-               return ret;
-       }
-       regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val);
-       SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
-               "updated successfully WLBT_CONFIGURATION[PWRRGTON_CON]: 0x%x\n", val);
-
        /* VGPIO_TX_MONITOR[VGPIO_TX_MON_BIT29] = 0x1 */
        timeout = jiffies + msecs_to_jiffies(500);
        do {
                regmap_read(platform->i3c_apm_pmic, VGPIO_TX_MONITOR, &val);
                val &= (u32)VGPIO_TX_MON_BIT29;
                if (val) {
-                       SCSC_TAG_INFO(PLAT_MIF, "VGPIO_TX_MONITOR 0x%x\n", val);
+                       SCSC_TAG_INFO(PLAT_MIF, "read VGPIO_TX_MONITOR 0x%x\n", val);
                        break;
                }
        } while (time_before(jiffies, timeout));
@@ -1148,6 +1152,20 @@ static int platform_mif_pmu_reset_release(struct scsc_mif_abs *interface)
                                        "VGPIO_TX_MONITOR 0x%x\n", val);
        }
 
+       udelay(1000);
+
+       /* WLBT_CONFIGURATION[LOCAL_PWR_CFG] = 1 Power On */
+       ret = regmap_update_bits(platform->pmureg, WLBT_CONFIGURATION,
+                       LOCAL_PWR_CFG, LOCAL_PWR_CFG);
+       if (ret < 0) {
+               SCSC_TAG_ERR_DEV(PLAT_MIF, platform->dev,
+                       "Failed to update WLBT_CONFIGURATION[LOCAL_PWR_CFG]: %d\n", ret);
+               return ret;
+       }
+       regmap_read(platform->pmureg, WLBT_CONFIGURATION, &val);
+       SCSC_TAG_INFO_DEV(PLAT_MIF, platform->dev,
+               "updated successfully WLBT_CONFIGURATION[PWRRGTON_CON]: 0x%x\n", val);
+
        /* wait for power up complete WLBT_STATUS[WLBT_STATUS_BIT0] = 1 for Power On */
        timeout = jiffies + msecs_to_jiffies(500);
        do {
@@ -1317,7 +1335,7 @@ static int platform_mif_reset(struct scsc_mif_abs *interface, bool reset)
 
 static void __iomem *platform_mif_map_region(unsigned long phys_addr, size_t size)
 {
-       int         i;
+       size_t      i;
        struct page **pages;
        void        *vmem;
 
index 24afb406ea7806e33de2ccac8698ed32c4250b35..4e64899c5b8d0318ac66eb73147eb6328249e552 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/workqueue.h>
 #include <linux/spinlock.h>
 #include <scsc/scsc_logring.h>
+#include <linux/timer.h>
 
 /* Implements */
 #include "scsc_wifilogger_core.h"
@@ -29,10 +30,17 @@ static void wlog_drain_worker(struct work_struct *work)
                r->ops.drain_ring(r, r->flushing ? r->st.rb_byte_size : DEFAULT_DRAIN_CHUNK_SZ(r));
 }
 
+#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE
+static void drain_timer_callback(struct timer_list *t)
+#else
 static void drain_timer_callback(unsigned long data)
+#endif
 {
+#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE
+       struct scsc_wlog_ring *r = from_timer(r, t, drain_timer);
+#else
        struct scsc_wlog_ring *r = (struct scsc_wlog_ring *)data;
-
+#endif
        SCSC_TAG_DBG4(WLOG, "TIMER DRAIN : %p\n", r);
        /* we should kick the workqueue here...no sleep */
        queue_work(r->drain_workq, &r->drain_work);
@@ -60,8 +68,11 @@ static int wlog_ring_init(struct scsc_wlog_ring *r)
 
        r->drain_workq = create_workqueue("wifilogger");
        INIT_WORK(&r->drain_work, wlog_drain_worker);
-       setup_timer(&r->drain_timer, drain_timer_callback, (unsigned long)r);
-
+#if KERNEL_VERSION(4,19,0) <= LINUX_VERSION_CODE
+       timer_setup(&r->drain_timer, drain_timer_callback, 0);
+#else
+       setup_timer(&r->drain_timer, drain_timer_callback, (unsigned long)r);
+#endif
        r->st.ring_id = atomic_read(&next_ring_id);
        atomic_inc(&next_ring_id);
 
index 6b10c57e26fb5471b17a972026affeab710ea6f8..9e21151a6f77f7cdbe1da3c786119db77a54f194 100644 (file)
@@ -33,6 +33,7 @@
 #include "scsc_bt_hci.h"
 
 static u8   ant_write_buffer[ASMHCP_BUFFER_SIZE];
+static u16  ant_irq_mask;
 
 static void scsc_ant_shm_irq_handler(int irqbit, void *data)
 {
@@ -68,19 +69,34 @@ static void scsc_ant_shm_irq_handler(int irqbit, void *data)
 }
 
 /* Assign firmware/host interrupts */
-static void scsc_ant_shm_init_interrupt(void)
+static int scsc_ant_shm_init_interrupt(void)
 {
+       int irq_ret = 0;
+       u16 irq_num = 0;
+
        /* To-host f/w IRQ allocations and ISR registrations */
-       ant_service.asmhcp_protocol->header.bg_to_ap_int_src =
-           scsc_service_mifintrbit_register_tohost(ant_service.service, scsc_ant_shm_irq_handler, NULL);
+       irq_ret = scsc_service_mifintrbit_register_tohost(
+           ant_service.service, scsc_ant_shm_irq_handler, NULL);
+       if (irq_ret < 0)
+               return irq_ret;
+
+       ant_service.asmhcp_protocol->header.bg_to_ap_int_src = irq_ret;
+       ant_irq_mask |= 1 << irq_num++;
 
        /* From-host f/w IRQ allocations */
-       ant_service.asmhcp_protocol->header.ap_to_bg_int_src =
-           scsc_service_mifintrbit_alloc_fromhost(ant_service.service, SCSC_MIFINTR_TARGET_R4);
+       irq_ret = scsc_service_mifintrbit_alloc_fromhost(
+           ant_service.service, SCSC_MIFINTR_TARGET_R4);
+       if (irq_ret < 0)
+               return irq_ret;
+
+       ant_service.asmhcp_protocol->header.ap_to_bg_int_src = irq_ret;
+       ant_irq_mask |= 1 << irq_num++;
 
        SCSC_TAG_DEBUG(BT_COMMON, "Registered to-host IRQ bit %d, from-host IRQ bit %d\n",
                       ant_service.asmhcp_protocol->header.bg_to_ap_int_src,
                       ant_service.asmhcp_protocol->header.ap_to_bg_int_src);
+
+       return 0;
 }
 
 static ssize_t scsc_shm_ant_cmd_write(const unsigned char *data, size_t count)
@@ -645,9 +661,13 @@ int scsc_ant_shm_init(void)
        ant_service.mailbox_cmd_ctr_driv_read = 0;
        ant_service.mailbox_cmd_ctr_driv_write = 0;
        ant_service.read_index = 0;
+       ant_irq_mask = 0;
 
        /* Initialise the interrupt handlers */
-       scsc_ant_shm_init_interrupt();
+       if (scsc_ant_shm_init_interrupt() < 0) {
+               SCSC_TAG_ERR(BT_COMMON, "Failed to register IRQ bits\n");
+               return -EIO;
+       }
 
        return 0;
 }
@@ -659,16 +679,22 @@ int scsc_ant_shm_init(void)
  */
 void scsc_ant_shm_exit(void)
 {
+       u16 irq_num = 0;
+
        /* Release IRQs */
        if (ant_service.asmhcp_protocol != NULL) {
-               scsc_service_mifintrbit_unregister_tohost(
-                       ant_service.service,
-                       ant_service.asmhcp_protocol->header.bg_to_ap_int_src);
+               if (ant_irq_mask & 1 << irq_num++) {
+                       scsc_service_mifintrbit_unregister_tohost(
+                               ant_service.service,
+                               ant_service.asmhcp_protocol->header.bg_to_ap_int_src);
+               }
 
-               scsc_service_mifintrbit_free_fromhost(
-                       ant_service.service,
-                       ant_service.asmhcp_protocol->header.ap_to_bg_int_src,
-                       SCSC_MIFINTR_TARGET_R4);
+               if (ant_irq_mask & 1 << irq_num++) {
+                       scsc_service_mifintrbit_free_fromhost(
+                               ant_service.service,
+                               ant_service.asmhcp_protocol->header.ap_to_bg_int_src,
+                               SCSC_MIFINTR_TARGET_R4);
+               }
        }
 
        /* Clear all control structures */
index e4cb45b64cdc92c32b3518bac0d494a831c1889e..e5e1143ccbe1f8898d7f039950c16a161b90c2f9 100755 (executable)
@@ -24,6 +24,7 @@
 #include <asm/termios.h>
 #include <linux/wakelock.h>
 #include <linux/delay.h>
+#include <linux/seq_file.h>
 
 #ifdef CONFIG_ARCH_EXYNOS
 #include <linux/soc/samsung/exynos-soc.h>
@@ -51,6 +52,8 @@
 
 #define SCSC_ANT_MAX_TIMEOUT (20*HZ)
 
+static u16 bt_module_irq_mask;
+
 #ifdef CONFIG_SCSC_ANT
 static DECLARE_WAIT_QUEUE_HEAD(ant_recovery_complete_queue);
 #endif
@@ -239,15 +242,41 @@ static struct scsc_service_client mx_ant_client = {
 
 static void slsi_sm_bt_service_cleanup_interrupts(void)
 {
-       u16 int_src = bt_service.bsmhcp_protocol->header.info_bg_to_ap_int_src;
+       u16 irq_num = 0;
 
        SCSC_TAG_DEBUG(BT_COMMON,
                       "unregister firmware information interrupts\n");
 
-       scsc_service_mifintrbit_unregister_tohost(bt_service.service, int_src);
-       scsc_service_mifintrbit_free_fromhost(bt_service.service,
-               bt_service.bsmhcp_protocol->header.info_ap_to_bg_int_src,
-               SCSC_MIFINTR_TARGET_R4);
+       if (bt_module_irq_mask & 1 << irq_num++)
+               scsc_service_mifintrbit_unregister_tohost(bt_service.service,
+            bt_service.bsmhcp_protocol->header.info_bg_to_ap_int_src);
+       if (bt_module_irq_mask & 1 << irq_num++)
+               scsc_service_mifintrbit_free_fromhost(bt_service.service,
+                   bt_service.bsmhcp_protocol->header.info_ap_to_bg_int_src,
+                   SCSC_MIFINTR_TARGET_R4);
+}
+
+static int slsi_sm_bt_service_init_interrupts(void) {
+       int irq_ret;
+       u16 irq_num = 0;
+
+       irq_ret = scsc_service_mifintrbit_register_tohost(bt_service.service,
+           scsc_bt_shm_irq_handler, NULL);
+       if (irq_ret < 0)
+               return irq_ret;
+
+       bt_service.bsmhcp_protocol->header.info_bg_to_ap_int_src = irq_ret;
+       bt_module_irq_mask |= 1 << irq_num++;
+
+       irq_ret = scsc_service_mifintrbit_alloc_fromhost(bt_service.service,
+           SCSC_MIFINTR_TARGET_R4);
+       if (irq_ret < 0)
+               return irq_ret;
+
+       bt_service.bsmhcp_protocol->header.info_ap_to_bg_int_src = irq_ret;
+       bt_module_irq_mask |= 1 << irq_num++;
+
+       return 0;
 }
 
 static int slsi_sm_bt_service_cleanup_stop_service(void)
@@ -357,8 +386,10 @@ static int slsi_sm_bt_service_cleanup(bool force_cleanup)
                wake_up_interruptible(&bt_service.read_wait);
 
                /* Unregister firmware information interrupts */
-               if (bt_service.bsmhcp_protocol)
+               if (bt_service.bsmhcp_protocol) {
                        slsi_sm_bt_service_cleanup_interrupts();
+                       bt_module_irq_mask = 0;
+               }
 
                /* Shut down the shared memory interface */
                SCSC_TAG_DEBUG(BT_COMMON,
@@ -988,12 +1019,10 @@ int slsi_sm_bt_service_start(void)
                goto exit;
        }
 
-       bt_service.bsmhcp_protocol->header.info_ap_to_bg_int_src =
-               scsc_service_mifintrbit_alloc_fromhost(bt_service.service,
-                                               SCSC_MIFINTR_TARGET_R4);
-       bt_service.bsmhcp_protocol->header.info_bg_to_ap_int_src =
-               scsc_service_mifintrbit_register_tohost(bt_service.service,
-                                               scsc_bt_shm_irq_handler, NULL);
+       err = slsi_sm_bt_service_init_interrupts();
+       if (err < 0)
+               goto exit;
+
        bt_service.bsmhcp_protocol->header.mxlog_filter = firmware_mxlog_filter;
        bt_service.bsmhcp_protocol->header.firmware_control = firmware_control;
        bt_service.bsmhcp_protocol->header.abox_offset = bt_service.abox_ref;
@@ -2053,6 +2082,7 @@ static int __init scsc_bt_module_init(void)
 
        SCSC_TAG_INFO(BT_COMMON, "%s %s (C) %s\n",
                      SCSC_MODDESC, SCSC_MODVERSION, SCSC_MODAUTH);
+       bt_module_irq_mask = 0;
        bt_recovery_level = 0;
 #ifdef CONFIG_SCSC_ANT
        ant_recovery_level = 0;
index 3c12c09ccbb4d14889d94f2b0ee41622757ba539..96439a3f34e6c2940d029b4493f94f6012b5d7f0 100755 (executable)
@@ -258,6 +258,8 @@ struct scsc_bt_service {
        struct completion              recovery_release_complete;
        struct completion              recovery_probe_complete;
 
+       bool                           iq_reports_enabled;
+
 #ifdef CONFIG_SCSC_LOG_COLLECTION
        struct scsc_bt_hcf_collection  hcf_collection;
 #endif
index e1786b37aaabf9717d8daabbfad8c28e6c57d2a5..d41659b7d48ab99513606741daad0014ce0aeff7 100755 (executable)
@@ -45,7 +45,7 @@ static struct hci_credit_entry *h4_hci_credit_entries = (struct hci_credit_entry
 static u8   h4_hci_event_hardware_error[4] = { HCI_EVENT_PKT, HCI_EVENT_HARDWARE_ERROR_EVENT, 1, 0 };
 static u8   h4_iq_report_evt[HCI_IQ_REPORT_MAX_LEN];
 static u32  h4_iq_report_evt_len;
-
+static u16  h4_irq_mask;
 
 static void scsc_bt_shm_irq_handler(int irqbit, void *data)
 {
@@ -88,23 +88,61 @@ static void scsc_bt_shm_irq_handler(int irqbit, void *data)
 }
 
 /* Assign firmware/host interrupts */
-static void scsc_bt_shm_init_interrupt(void)
+static int scsc_bt_shm_init_interrupt(void)
 {
+       int irq_ret = 0;
+       u16 irq_num = 0;
+
        /* To-host f/w IRQ allocations and ISR registrations */
-       bt_service.bsmhcp_protocol->header.bg_to_ap_int_src = scsc_service_mifintrbit_register_tohost(bt_service.service, scsc_bt_shm_irq_handler, NULL);
-       bt_service.bsmhcp_protocol->header.fg_to_ap_int_src = scsc_service_mifintrbit_register_tohost(bt_service.service, scsc_bt_shm_irq_handler, NULL);
+       irq_ret = scsc_service_mifintrbit_register_tohost(
+           bt_service.service, scsc_bt_shm_irq_handler, NULL);
+       if (irq_ret < 0)
+               return irq_ret;
+
+       bt_service.bsmhcp_protocol->header.bg_to_ap_int_src = irq_ret;
+       h4_irq_mask |= 1 << irq_num++;
+
+       irq_ret = scsc_service_mifintrbit_register_tohost(
+           bt_service.service, scsc_bt_shm_irq_handler, NULL);
+       if (irq_ret < 0)
+               return irq_ret;
+
+       bt_service.bsmhcp_protocol->header.fg_to_ap_int_src = irq_ret;
+       h4_irq_mask |= 1 << irq_num++;
 
        /* From-host f/w IRQ allocations */
-       bt_service.bsmhcp_protocol->header.ap_to_bg_int_src = scsc_service_mifintrbit_alloc_fromhost(bt_service.service, SCSC_MIFINTR_TARGET_R4);
-       bt_service.bsmhcp_protocol->header.ap_to_fg_int_src = scsc_service_mifintrbit_alloc_fromhost(bt_service.service, SCSC_MIFINTR_TARGET_R4);
-       bt_service.bsmhcp_protocol->header.ap_to_fg_m4_int_src = scsc_service_mifintrbit_alloc_fromhost(bt_service.service, SCSC_MIFINTR_TARGET_M4);
+       irq_ret = scsc_service_mifintrbit_alloc_fromhost(
+           bt_service.service, SCSC_MIFINTR_TARGET_R4);
+       if (irq_ret < 0)
+               return irq_ret;
+
+       bt_service.bsmhcp_protocol->header.ap_to_bg_int_src = irq_ret;
+       h4_irq_mask |= 1 << irq_num++;
+
+       irq_ret = scsc_service_mifintrbit_alloc_fromhost(
+           bt_service.service, SCSC_MIFINTR_TARGET_R4);
+       if (irq_ret < 0)
+               return irq_ret;
+
+       bt_service.bsmhcp_protocol->header.ap_to_fg_int_src = irq_ret;
+       h4_irq_mask |= 1 << irq_num++;
 
-       SCSC_TAG_DEBUG(BT_COMMON, "Registered to-host IRQ bits %d:%d:%d, from-host IRQ bits %d:%d\n",
+       irq_ret = scsc_service_mifintrbit_alloc_fromhost(
+           bt_service.service, SCSC_MIFINTR_TARGET_M4);
+       if (irq_ret < 0)
+               return irq_ret;
+
+       bt_service.bsmhcp_protocol->header.ap_to_fg_m4_int_src = irq_ret;
+       h4_irq_mask |= 1 << irq_num++;
+
+       SCSC_TAG_DEBUG(BT_COMMON, "Registered to-host IRQ bits %d:%d, from-host IRQ bits %d:%d:%d\n",
                       bt_service.bsmhcp_protocol->header.bg_to_ap_int_src,
                       bt_service.bsmhcp_protocol->header.fg_to_ap_int_src,
-                      bt_service.bsmhcp_protocol->header.ap_to_fg_m4_int_src,
                       bt_service.bsmhcp_protocol->header.ap_to_bg_int_src,
-                      bt_service.bsmhcp_protocol->header.ap_to_fg_int_src);
+                      bt_service.bsmhcp_protocol->header.ap_to_fg_int_src,
+                      bt_service.bsmhcp_protocol->header.ap_to_fg_m4_int_src);
+
+       return 0;
 }
 
 bool scsc_bt_shm_h4_avdtp_detect_write(uint32_t flags,
@@ -810,63 +848,71 @@ static ssize_t scsc_bt_shm_h4_read_iq_report_evt(char __user *buf, size_t len)
                u32 j = 0;
                u32 i;
 
-               memset(h4_iq_report_evt, 0, sizeof(h4_iq_report_evt));
-               h4_iq_report_evt_len = 0;
-
-               h4_iq_report_evt[index++] = HCI_EVENT_PKT;
-               h4_iq_report_evt[index++] = 0x3E;
-               index++; /* Leaving room for total length of params  */
-               h4_iq_report_evt[index++] = td->subevent_code;
-
-               if (td->subevent_code == HCI_LE_CONNECTIONLESS_IQ_REPORT_EVENT_SUB_CODE) {
-                       /* LE Connectionless IQ Report Event*/
-                       h4_iq_report_evt[index++] = td->sync_handle & 0xFF;
-                       h4_iq_report_evt[index++] = (td->sync_handle >> 8) & 0xFF;
-               } else if (td->subevent_code == HCI_LE_CONNECTION_IQ_REPORT_EVENT_SUB_CODE) {
-                       /* LE connection IQ Report Event */
-                       h4_iq_report_evt[index++] = td->connection_handle & 0xFF;
-                       h4_iq_report_evt[index++] = (td->connection_handle >> 8) & 0xFF;
-                       h4_iq_report_evt[index++] = td->rx_phy;
-
-               }
-               h4_iq_report_evt[index++] = td->channel_index;
-               h4_iq_report_evt[index++] = td->rssi & 0xFF;
-               h4_iq_report_evt[index++] = (td->rssi >> 8) & 0xFF;
-               h4_iq_report_evt[index++] = td->rssi_antenna_id;
-               h4_iq_report_evt[index++] = td->cte_type;
-               h4_iq_report_evt[index++] = td->slot_durations;
-               h4_iq_report_evt[index++] = td->packet_status;
-               h4_iq_report_evt[index++] = td->event_count & 0xFF;
-               h4_iq_report_evt[index++] = (td->event_count >> 8) & 0xFF;
-               h4_iq_report_evt[index++] = td->sample_count;
-
-               /* Total length of hci event */
-               h4_iq_report_evt_len = index + (2 * td->sample_count);
-
-               /* Total length of hci event parameters */
-               h4_iq_report_evt[2] = h4_iq_report_evt_len - 3;
-
-               for (i = 0; i < td->sample_count; i++) {
-                       h4_iq_report_evt[index + i] = td->data[j++];
-                       h4_iq_report_evt[(index + td->sample_count) + i] = td->data[j++];
+               if (!bt_service.iq_reports_enabled)
+               {
+                       BSMHCP_INCREASE_INDEX(bt_service.mailbox_iq_report_read,
+                       BSMHCP_TRANSFER_RING_IQ_REPORT_SIZE);
                }
+               else
+               {
+                       memset(h4_iq_report_evt, 0, sizeof(h4_iq_report_evt));
+                       h4_iq_report_evt_len = 0;
+
+                       h4_iq_report_evt[index++] = HCI_EVENT_PKT;
+                       h4_iq_report_evt[index++] = 0x3E;
+                       index++; /* Leaving room for total length of params  */
+                       h4_iq_report_evt[index++] = td->subevent_code;
+
+                       if (td->subevent_code == HCI_LE_CONNECTIONLESS_IQ_REPORT_EVENT_SUB_CODE) {
+                               /* LE Connectionless IQ Report Event*/
+                               h4_iq_report_evt[index++] = td->sync_handle & 0xFF;
+                               h4_iq_report_evt[index++] = (td->sync_handle >> 8) & 0xFF;
+                       } else if (td->subevent_code == HCI_LE_CONNECTION_IQ_REPORT_EVENT_SUB_CODE) {
+                               /* LE connection IQ Report Event */
+                               h4_iq_report_evt[index++] = td->connection_handle & 0xFF;
+                               h4_iq_report_evt[index++] = (td->connection_handle >> 8) & 0xFF;
+                               h4_iq_report_evt[index++] = td->rx_phy;
 
-               bt_service.read_operation = BT_READ_OP_IQ_REPORT;
-               bt_service.read_index = bt_service.mailbox_iq_report_read;
+                       }
+                       h4_iq_report_evt[index++] = td->channel_index;
+                       h4_iq_report_evt[index++] = td->rssi & 0xFF;
+                       h4_iq_report_evt[index++] = (td->rssi >> 8) & 0xFF;
+                       h4_iq_report_evt[index++] = td->rssi_antenna_id;
+                       h4_iq_report_evt[index++] = td->cte_type;
+                       h4_iq_report_evt[index++] = td->slot_durations;
+                       h4_iq_report_evt[index++] = td->packet_status;
+                       h4_iq_report_evt[index++] = td->event_count & 0xFF;
+                       h4_iq_report_evt[index++] = (td->event_count >> 8) & 0xFF;
+                       h4_iq_report_evt[index++] = td->sample_count;
+
+                       /* Total length of hci event */
+                       h4_iq_report_evt_len = index + (2 * td->sample_count);
+
+                       /* Total length of hci event parameters */
+                       h4_iq_report_evt[2] = h4_iq_report_evt_len - 3;
+
+                       for (i = 0; i < td->sample_count; i++) {
+                               h4_iq_report_evt[index + i] = td->data[j++];
+                               h4_iq_report_evt[(index + td->sample_count) + i] = td->data[j++];
+                       }
 
-               ret = scsc_iq_report_evt_read(&buf[consumed], len - consumed);
-               if (ret > 0) {
-                       /* All good - Update our consumed information */
-                       consumed += ret;
-                       ret = 0;
+                       bt_service.read_operation = BT_READ_OP_IQ_REPORT;
+                       bt_service.read_index = bt_service.mailbox_iq_report_read;
 
-                       /**
-                        * Update the index if all the data could be copied to the userspace
-                        * buffer otherwise stop processing the HCI events
-                        */
-                       if (bt_service.read_operation == BT_READ_OP_NONE)
-                               BSMHCP_INCREASE_INDEX(bt_service.mailbox_iq_report_read,
+                       ret = scsc_iq_report_evt_read(&buf[consumed], len - consumed);
+                       if (ret > 0) {
+                               /* All good - Update our consumed information */
+                               consumed += ret;
+                               ret = 0;
+
+                               /**
+                                * Update the index if all the data could be copied to the userspace
+                                * buffer otherwise stop processing the HCI events
+                                */
+                               if (bt_service.read_operation == BT_READ_OP_NONE)
+                                       BSMHCP_INCREASE_INDEX(bt_service.mailbox_iq_report_read,
                                                                          BSMHCP_TRANSFER_RING_IQ_REPORT_SIZE);
+                       }
                }
        }
 
@@ -889,7 +935,7 @@ static ssize_t scsc_bt_shm_h4_read_hci_evt(char __user *buf, size_t len)
                }
 
                /* A connection event has been detected by the firmware */
-               if (td->event_type & BSMHCP_EVENT_TYPE_CONNECTED) {
+               if (td->event_type == BSMHCP_EVENT_TYPE_CONNECTED) {
                        /* Sanity check of the HCI connection handle */
                        if (td->hci_connection_handle >= SCSC_BT_CONNECTION_INFO_MAX) {
                                SCSC_TAG_ERR(BT_H4, "connection handle is beyond max (hci_connection_handle=0x%03x)\n",
@@ -909,7 +955,7 @@ static ssize_t scsc_bt_shm_h4_read_hci_evt(char __user *buf, size_t len)
                        bt_service.acldata_paused = false;
 
                        /* A disconnection event has been detected by the firmware */
-               } else if (td->event_type & BSMHCP_EVENT_TYPE_DISCONNECTED) {
+               } else if (td->event_type == BSMHCP_EVENT_TYPE_DISCONNECTED) {
                        SCSC_TAG_DEBUG(BT_H4, "disconnected (hci_connection_handle=0x%03x, state=%u)\n",
                                       td->hci_connection_handle, bt_service.connection_handle_list[td->hci_connection_handle].state);
 
@@ -926,6 +972,10 @@ static ssize_t scsc_bt_shm_h4_read_hci_evt(char __user *buf, size_t len)
 
                        /* Firmware does not have more ACL data - Mark the connection as inactive */
                        bt_service.connection_handle_list[td->hci_connection_handle].state = CONNECTION_NONE;
+               } else if (td->event_type == BSMHCP_EVENT_TYPE_IQ_REPORT_ENABLED) {
+                       bt_service.iq_reports_enabled = true;
+               } else if (td->event_type == BSMHCP_EVENT_TYPE_IQ_REPORT_DISABLED) {
+                       bt_service.iq_reports_enabled = false;
                }
 
                /* Start a HCI event copy to userspace */
@@ -1332,7 +1382,7 @@ ssize_t scsc_bt_shm_h4_read(struct file *file, char __user *buf, size_t len, lof
                        bt_service.read_operation = BT_READ_OP_HCI_EVT_ERROR;
 
                if (BT_READ_OP_HCI_EVT_ERROR == bt_service.read_operation) {
-                       SCSC_TAG_DEBUG(BT_H4, "BT_READ_OP_HCI_EVT_ERROR\n");
+                       SCSC_TAG_ERR(BT_H4, "BT_READ_OP_HCI_EVT_ERROR\n");
 
                        /* Copy data into the userspace buffer */
                        ret = scsc_hci_evt_error_read(buf, len);
@@ -1557,9 +1607,14 @@ int scsc_bt_shm_init(void)
        bt_service.mailbox_iq_report_read = 0;
        bt_service.read_index = 0;
        bt_service.allocated_count = 0;
+       bt_service.iq_reports_enabled = false;
+       h4_irq_mask = 0;
 
        /* Initialise the interrupt handlers */
-       scsc_bt_shm_init_interrupt();
+       if (scsc_bt_shm_init_interrupt() < 0) {
+               SCSC_TAG_ERR(BT_COMMON, "Failed to register IRQ bits\n");
+               return -EIO;
+       }
 
        return 0;
 }
@@ -1571,14 +1626,26 @@ int scsc_bt_shm_init(void)
  */
 void scsc_bt_shm_exit(void)
 {
+       u16 irq_num = 0;
+
        /* Release IRQs */
        if (bt_service.bsmhcp_protocol != NULL) {
-               scsc_service_mifintrbit_unregister_tohost(bt_service.service, bt_service.bsmhcp_protocol->header.bg_to_ap_int_src);
-               scsc_service_mifintrbit_unregister_tohost(bt_service.service, bt_service.bsmhcp_protocol->header.fg_to_ap_int_src);
 
-               scsc_service_mifintrbit_free_fromhost(bt_service.service, bt_service.bsmhcp_protocol->header.ap_to_bg_int_src, SCSC_MIFINTR_TARGET_R4);
-               scsc_service_mifintrbit_free_fromhost(bt_service.service, bt_service.bsmhcp_protocol->header.ap_to_fg_int_src, SCSC_MIFINTR_TARGET_R4);
-               scsc_service_mifintrbit_free_fromhost(bt_service.service, bt_service.bsmhcp_protocol->header.ap_to_fg_m4_int_src, SCSC_MIFINTR_TARGET_M4);
+               if (h4_irq_mask & 1 << irq_num++)
+                       scsc_service_mifintrbit_unregister_tohost(
+                           bt_service.service, bt_service.bsmhcp_protocol->header.bg_to_ap_int_src);
+               if (h4_irq_mask & 1 << irq_num++)
+                       scsc_service_mifintrbit_unregister_tohost(
+                           bt_service.service, bt_service.bsmhcp_protocol->header.fg_to_ap_int_src);
+               if (h4_irq_mask & 1 << irq_num++)
+                       scsc_service_mifintrbit_free_fromhost(
+                           bt_service.service, bt_service.bsmhcp_protocol->header.ap_to_bg_int_src, SCSC_MIFINTR_TARGET_R4);
+               if (h4_irq_mask & 1 << irq_num++)
+                       scsc_service_mifintrbit_free_fromhost(
+                           bt_service.service, bt_service.bsmhcp_protocol->header.ap_to_fg_int_src, SCSC_MIFINTR_TARGET_R4);
+               if (h4_irq_mask & 1 << irq_num++)
+                       scsc_service_mifintrbit_free_fromhost(
+                           bt_service.service, bt_service.bsmhcp_protocol->header.ap_to_fg_m4_int_src, SCSC_MIFINTR_TARGET_M4);
        }
 
        /* Clear all control structures */
index 5d480b1484ce10c8bc079c67f21b9116ed74576e..605b3b5377122e8f1d2b7093f03db33f6f8e87f5 100755 (executable)
@@ -137,7 +137,7 @@ config SCSC_WLAN_MAC_ADDRESS_FILENAME
 
 config SCSC_WLAN_MAX_INTERFACES
         int "Max number of virtual interfaces supported"
-        range 1 3
+        range 1 12
         default 3
         ---help---
           The driver structures are sized to support this
@@ -268,9 +268,3 @@ config SCSC_WLAN_SILENT_RECOVERY
        default y
        ---help---
        This option tells if silent recovery is enabled or not.
-
-config SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
-        bool "Enable abnormal multicast packet filtering in suspend"
-        default n
-        ---help---
-          This option tells if abnormal multicast packet filtering in suspend is supported or not.
index 8abcb20895aed6c03787aff6a359aeb30ebe90e5..7fc55241b4f2e1324f4100533d2bd1ee7a7ae532 100755 (executable)
@@ -57,6 +57,7 @@ scsc_wlan-$(CONFIG_SCSC_WLAN) += scsc_wifi_fcq.o
 scsc_wlan-$(CONFIG_SCSC_WLAN) += ioctl.o
 scsc_wlan-$(CONFIG_SCSC_WLAN) += wakelock.o
 scsc_wlan-$(CONFIG_SCSC_WLAN) += traffic_monitor.o
+scsc_wlan-$(CONFIG_SCSC_WLAN) += reg_info.o
 
 # ----------------------------------------------------------------------------
 # ACM
index 70abc0471978bba5ceb4ce6aaf5e29ba4abc9bbb..eb44d0b2d68548b65e18f8bb6c476197b337ddd0 100755 (executable)
@@ -49,21 +49,6 @@ static u8        ccx_status = BSS_CCX_DISABLED;
 
 static void cac_set_ric_ie(struct slsi_dev *sdev, struct net_device *netdev);
 static int cac_get_rde_tspec_ie(struct slsi_dev *sdev, u8 *assoc_rsp_ie, int assoc_rsp_ie_len, const u8 **tspec_ie_arr);
-/* Name: strtoint
- * Desc: Converts a string to a decimal or hexadecimal integer
- * s: the string to be converted
- * res: pointer to the calculated integer
- * return: 0 (success), 1(failure)
- */
-static int strtoint(const char *s, int *res)
-{
-       int base = 10;
-
-       if (strlen(s) > 2)
-               if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
-                       base = 16;
-       return kstrtoint(s, base, res);
-}
 
 /* Name: find_tspec_entry
  * Desc: Finds a tspec entry in the list of tspecs (tspec_list)
index 7c76b40fe2c7a13eae2a4b078ffa54a21822ed99..345bc74921603063fd867600503793a48a4c695e 100755 (executable)
@@ -968,7 +968,6 @@ int slsi_connect(struct wiphy *wiphy, struct net_device *dev,
        }
        prev_vif_type = ndev_vif->vif_type;
 
-       prev_vif_type = ndev_vif->vif_type;
        switch (ndev_vif->iftype) {
        case NL80211_IFTYPE_UNSPECIFIED:
        case NL80211_IFTYPE_STATION:
@@ -2011,37 +2010,35 @@ static int slsi_get_max_bw_mhz(struct slsi_dev *sdev, u16 prim_chan_cf)
        return 0;
 }
 
+#ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
 void slsi_store_settings_for_recovery(struct cfg80211_ap_settings *settings, struct netdev_vif *ndev_vif)
 {
        ndev_vif->backup_settings = *settings;
-       ndev_vif->backup_settings.chandef.chan = kmalloc(sizeof(struct ieee80211_channel), GFP_KERNEL);
-       memcpy(ndev_vif->backup_settings.chandef.chan, settings->chandef.chan, sizeof(struct ieee80211_channel));
-       ndev_vif->backup_settings.beacon.head = kmalloc(settings->beacon.head_len, GFP_KERNEL);
-       memcpy((u8 *)ndev_vif->backup_settings.beacon.head, settings->beacon.head, settings->beacon.head_len);
-       ndev_vif->backup_settings.beacon.tail = kmalloc(settings->beacon.tail_len, GFP_KERNEL);
-       memcpy((u8 *)ndev_vif->backup_settings.beacon.tail, settings->beacon.tail, settings->beacon.tail_len);
-       ndev_vif->backup_settings.beacon.beacon_ies = kmalloc(settings->beacon.beacon_ies_len, GFP_KERNEL);
-       memcpy((u8 *)ndev_vif->backup_settings.beacon.beacon_ies, settings->beacon.beacon_ies, settings->beacon.beacon_ies_len);
-
-       ndev_vif->backup_settings.beacon.proberesp_ies = kmalloc(settings->beacon.proberesp_ies_len, GFP_KERNEL);
-       memcpy((u8 *)ndev_vif->backup_settings.beacon.proberesp_ies, settings->beacon.proberesp_ies,settings->beacon.proberesp_ies_len);
-       ndev_vif->backup_settings.beacon.assocresp_ies = kmalloc(settings->beacon.assocresp_ies_len, GFP_KERNEL);
-       memcpy((u8 *)ndev_vif->backup_settings.beacon.assocresp_ies, settings->beacon.assocresp_ies, settings->beacon.assocresp_ies_len);
-       ndev_vif->backup_settings.beacon.probe_resp = kmalloc(settings->beacon.probe_resp_len, GFP_KERNEL);
-       memcpy((u8 *)ndev_vif->backup_settings.beacon.probe_resp, settings->beacon.probe_resp, settings->beacon.probe_resp_len);
-
-       ndev_vif->backup_settings.ssid= kmalloc(settings->ssid_len, GFP_KERNEL);
-       memcpy((u8 *)ndev_vif->backup_settings.ssid, settings->ssid, settings->ssid_len);
+       if (&ndev_vif->backup_settings == settings)
+               return;
+       ndev_vif->backup_settings.chandef.chan =
+       (struct ieee80211_channel *)slsi_mem_dup((u8 *)settings->chandef.chan, sizeof(struct ieee80211_channel));
+       ndev_vif->backup_settings.beacon.head = slsi_mem_dup((u8 *)settings->beacon.head, settings->beacon.head_len);
+       ndev_vif->backup_settings.beacon.tail = slsi_mem_dup((u8 *)settings->beacon.tail, settings->beacon.tail_len);
+       ndev_vif->backup_settings.beacon.beacon_ies = slsi_mem_dup((u8 *)settings->beacon.beacon_ies,
+                                                                  settings->beacon.beacon_ies_len);
+       ndev_vif->backup_settings.beacon.proberesp_ies = slsi_mem_dup((u8 *)settings->beacon.proberesp_ies,
+                                                                     settings->beacon.proberesp_ies_len);
+       ndev_vif->backup_settings.beacon.assocresp_ies = slsi_mem_dup((u8 *)settings->beacon.assocresp_ies,
+                                                                     settings->beacon.assocresp_ies_len);
+       ndev_vif->backup_settings.beacon.probe_resp = slsi_mem_dup((u8 *)settings->beacon.probe_resp,
+                                                                  settings->beacon.probe_resp_len);
+       ndev_vif->backup_settings.ssid = slsi_mem_dup((u8 *)settings->ssid, settings->ssid_len);
        if (settings->ht_cap) {
-               ndev_vif->backup_settings.ht_cap = kmalloc(sizeof(struct ieee80211_ht_cap), GFP_KERNEL);
-               memcpy((u8 *)ndev_vif->backup_settings.ht_cap, settings->ht_cap, sizeof(struct ieee80211_ht_cap));
+               ndev_vif->backup_settings.ht_cap =
+               (struct ieee80211_ht_cap *)slsi_mem_dup((u8 *)settings->ht_cap, sizeof(struct ieee80211_ht_cap));
        }
        if (settings->vht_cap) {
-               ndev_vif->backup_settings.vht_cap = kmalloc(sizeof(struct ieee80211_vht_cap), GFP_KERNEL);
-               memcpy((u8 *)ndev_vif->backup_settings.vht_cap, settings->vht_cap, sizeof(struct ieee80211_vht_cap));
+               ndev_vif->backup_settings.vht_cap =
+               (struct ieee80211_vht_cap *)slsi_mem_dup((u8 *)settings->vht_cap, sizeof(struct ieee80211_vht_cap));
        }
-
 }
+#endif
 
 int slsi_start_ap(struct wiphy *wiphy, struct net_device *dev,
                  struct cfg80211_ap_settings *settings)
index 8ab87ecd9cb0b1a488e67aed5d6df76eba5e716c..0f3ce40c3fcc24ce8922774826386eebdcb9da21 100755 (executable)
@@ -77,18 +77,9 @@ static int wlan_resume(struct scsc_service_client *client)
 static u8 wlan_failure_notification(struct scsc_service_client *client, struct mx_syserr_decode *err)
 {
        struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client);
-       struct netdev_vif *ndev_vif;
-       struct net_device *dev;
 
        atomic_set(&sdev->cm_if.reset_level, err->level);
        SLSI_INFO_NODEV("SubSystem:%d,Level:%d,Type:%d,Sub_code:%d\n", err->subsys, err->level, err->type, err->subcode);
-       /* system recovery not tested for p2p. So raise it to highest level for now. */
-       dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2PX_SWLAN);
-       if (dev) {
-               ndev_vif = netdev_priv(dev);
-               if (SLSI_IS_VIF_INDEX_P2P_GROUP(sdev, ndev_vif))
-                       return SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC;
-       }
        return err->level;
 }
 
@@ -104,18 +95,14 @@ static void wlan_failure_reset_v2(struct scsc_service_client *client, u8 level,
                SLSI_WARN_NODEV("Low level error level:%d\n", level);
        if (level == 5 || level == 6)
                blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_SUBSYSTEM_RESET, sdev);
-}
-#endif
-static void wlan_failure_reset(struct scsc_service_client *client, u16 scsc_panic_code)
-{
-       SLSI_INFO_NODEV("\n");
-       latest_scsc_panic_code = scsc_panic_code;
+       if (level == SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC)
+               latest_scsc_panic_code = scsc_syserr_code;
 }
 
-#ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
 static  bool wlan_stop_on_failure_v2(struct scsc_service_client *client, struct mx_syserr_decode *err)
 {
        int state;
+       u8 system_error_level;
        struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client);
 
        SLSI_INFO_NODEV("\n");
@@ -125,6 +112,13 @@ static  bool wlan_stop_on_failure_v2(struct scsc_service_client *client, struct
        sdev->recovery_status = 1;
        state = atomic_read(&sdev->cm_if.cm_if_state);
        atomic_set(&sdev->cm_if.reset_level, err->level);
+       /* system error level is set in failure_notification. if this is not yet set, consider
+        * a full panic. set it to SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC
+        */
+       system_error_level = atomic_read(&sdev->cm_if.reset_level);
+       if (!system_error_level) {
+               atomic_set(&sdev->cm_if.reset_level, SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC);
+       }
        if (state != SCSC_WIFI_CM_IF_STATE_STOPPED) {
                atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_BLOCKED);
                sdev->fail_reported = true;
@@ -150,11 +144,19 @@ static  bool wlan_stop_on_failure_v2(struct scsc_service_client *client, struct
        return true;
 }
 #endif
-static void wlan_stop_on_failure(struct scsc_service_client *client)
 
+static void wlan_failure_reset(struct scsc_service_client *client, u16 scsc_panic_code)
+{
+       SLSI_INFO_NODEV("\n");
+       latest_scsc_panic_code = scsc_panic_code;
+}
+
+static void wlan_stop_on_failure(struct scsc_service_client *client)
 {
        int state;
+#ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
        u8 system_error_level;
+#endif
        struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client);
 
        SLSI_INFO_NODEV("\n");
@@ -166,10 +168,12 @@ static void wlan_stop_on_failure(struct scsc_service_client *client)
        /* system error level is set in failure_notification. if this is not yet set, consider
         * a full panic. set it to SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC
         */
+#ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
        system_error_level = atomic_read(&sdev->cm_if.reset_level);
        if (!system_error_level) {
                atomic_set(&sdev->cm_if.reset_level, SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC);
        }
+#endif
        if (state != SCSC_WIFI_CM_IF_STATE_STOPPED) {
                atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_BLOCKED);
                sdev->fail_reported = true;
@@ -194,6 +198,7 @@ static void wlan_stop_on_failure(struct scsc_service_client *client)
        mutex_unlock(&slsi_start_mutex);
 }
 
+
 int slsi_check_rf_test_mode(void)
 {
        struct file *fp = NULL;
@@ -202,12 +207,19 @@ int slsi_check_rf_test_mode(void)
 #else
        char *filepath = "/data/misc/conn/.psm.info";
 #endif
+       char *file_path = "/data/vendor/wifi/rftest.info";
        char power_val = 0;
 
+       /* reading power value from /data/vendor/conn/.psm.info */
        fp = filp_open(filepath, O_RDONLY, 0);
        if (IS_ERR(fp) || (!fp)) {
                pr_err("%s is not exist.\n", filepath);
-               return -ENOENT; /* -2 */
+               /* reading power value from /data/vendor/wifi/rftest.info */
+               fp = filp_open(file_path, O_RDONLY, 0);
+               if(IS_ERR(fp) || (!fp)) {
+                       pr_err("%s is not exist.\n", file_path);
+                       return -ENOENT; /* -2 */
+               }
        }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
@@ -257,7 +269,6 @@ void slsi_wlan_service_probe(struct scsc_mx_module_client *module_client, struct
                recovery_in_progress = 0;
                sdev->fail_reported = false;
                sdev->recovery_status = 0;
-               sdev->mlme_blocked = false;
 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
                mutex_unlock(&slsi_start_mutex);
                blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_CHIP_READY, sdev);
@@ -317,7 +328,9 @@ void slsi_wlan_service_probe(struct scsc_mx_module_client *module_client, struct
 
        if (reason != SCSC_MODULE_CLIENT_REASON_RECOVERY)
                atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_PROBED);
+#ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
        atomic_set(&sdev->cm_if.reset_level, 0);
+#endif
 done:
        mutex_unlock(&slsi_start_mutex);
 }
index b4ec5c571f1d842b50db2c4ad883d3bfd9eb02ec..b0b947c5d1820b402052076ce59fd463b94e4325 100755 (executable)
@@ -88,6 +88,20 @@ MODULE_PARM_DESC(mac_randomisation_disabled, "Disable MAC Randomisation: to disa
 #endif
 //END IKSAMP-1972
 
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+static bool nan_include_ipv6_tlv = true;
+module_param(nan_include_ipv6_tlv, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(nan_include_ipv6_tlv, "include ipv6 address tlv: to disable NAN set 0. Enabled by default");
+
+static int nan_max_ndp_instances = 1;
+module_param(nan_max_ndp_instances, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(nan_max_ndp_instances, "max ndp sessions");
+
+static int nan_max_ndi_ifaces = 1;
+module_param(nan_max_ndi_ifaces, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(nan_max_ndi_ifaces, "max ndi interface");
+#endif
+
 bool slsi_dev_gscan_supported(void)
 {
        return !gscan_disabled;
@@ -143,6 +157,23 @@ bool slsi_dev_mac_randomisation_support(void)
 #endif
 //END IKSAMP-1972
 
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+bool slsi_dev_nan_is_ipv6_link_tlv_include(void)
+{
+       return nan_include_ipv6_tlv;
+}
+
+int slsi_get_nan_max_ndp_instances(void)
+{
+       return nan_max_ndp_instances;
+}
+
+int slsi_get_nan_max_ndi_ifaces(void)
+{
+       return nan_max_ndi_ifaces;
+}
+#endif
+
 static int slsi_dev_inetaddr_changed(struct notifier_block *nb, unsigned long data, void *arg)
 {
        struct slsi_dev     *sdev = container_of(nb, struct slsi_dev, inetaddr_notifier);
@@ -210,40 +241,6 @@ static int slsi_dev_inet6addr_changed(struct notifier_block *nb, unsigned long d
 }
 #endif
 
-void slsi_regd_init(struct slsi_dev *sdev)
-{
-       struct ieee80211_regdomain *slsi_world_regdom_custom = sdev->device_config.domain_info.regdomain;
-       struct ieee80211_reg_rule  reg_rules[] = {
-               /* Channel 1 - 11*/
-               REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0),
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
-               /* Channel 12 - 13 NO_IR*/
-               REG_RULE(2467 - 10, 2472 + 10, 40, 0, 20, NL80211_RRF_NO_IR),
-#endif
-               /* Channel 36 - 48 */
-               REG_RULE(5180 - 10, 5240 + 10, 80, 0, 20, 0),
-               /* Channel 52 - 64 */
-               REG_RULE(5260 - 10, 5320 + 10, 80, 0, 20, NL80211_RRF_DFS),
-               /* Channel 100 - 140 */
-               REG_RULE(5500 - 10, 5700 + 10, 80, 0, 20, NL80211_RRF_DFS),
-               /* Channel 149 - 165 */
-               REG_RULE(5745 - 10, 5825 + 10, 80, 0, 20, 0),
-       };
-
-       int                        i;
-
-       SLSI_DBG1_NODEV(SLSI_INIT_DEINIT, "regulatory init\n");
-       slsi_world_regdom_custom->n_reg_rules = 6;
-       for (i = 0; i < slsi_world_regdom_custom->n_reg_rules; i++)
-               slsi_world_regdom_custom->reg_rules[i] = reg_rules[i];
-
-       /* Country code '00' indicates world regulatory domain */
-       slsi_world_regdom_custom->alpha2[0] = '0';
-       slsi_world_regdom_custom->alpha2[1] = '0';
-
-       wiphy_apply_custom_regulatory(sdev->wiphy, slsi_world_regdom_custom);
-}
-
 struct slsi_dev *slsi_dev_attach(struct device *dev, struct scsc_mx *core, struct scsc_service_client *mx_wlan_client)
 {
        struct slsi_dev *sdev;
@@ -408,9 +405,6 @@ struct slsi_dev *slsi_dev_attach(struct device *dev, struct scsc_mx *core, struc
 #endif
 #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
        sdev->enhanced_pkt_filter_enabled = true;
-#endif
-#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
-       sdev->abnormal_multicast_pkt_filter_enabled = true;
 #endif
        sdev->device_state = SLSI_DEVICE_STATE_STOPPED;
        sdev->current_tspec_id = -1;
@@ -436,6 +430,8 @@ struct slsi_dev *slsi_dev_attach(struct device *dev, struct scsc_mx *core, struc
        }
 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
        INIT_WORK(&sdev->recovery_work, slsi_subsystem_reset);
+       INIT_WORK(&sdev->recovery_work_on_stop, slsi_failure_reset);
+       INIT_WORK(&sdev->recovery_work_on_start, slsi_chip_recovery);
 #endif
        return sdev;
 
index 6658988a352ccf895e20e4928f4fc8d28235823f..854f4eebe89bfe60b4a0c7bf026a7e1d3f21085e 100755 (executable)
@@ -46,6 +46,7 @@
 #include "hip4.h"
 #include "nl80211_vendor.h"
 #include "traffic_monitor.h"
+#include "reg_info.h"
 
 #define FAPI_MAJOR_VERSION(v) (((v) >> 8) & 0xFF)
 #define FAPI_MINOR_VERSION(v) ((v) & 0xFF)
@@ -412,6 +413,7 @@ struct slsi_peer {
        bool     qos_map_set;
        struct cfg80211_qos_map qos_map;
 #endif
+       u16 ndl_vif;
 };
 
 /* Used to update vif type on vif deactivation indicating vif is no longer available */
@@ -464,42 +466,42 @@ struct slsi_wmm_parameter_element {
 #ifdef CONFIG_SCSC_WLAN_BLOCK_IPV6
 
 enum slsi_filter_id {
-       SLSI_ALL_ARP_FILTER_ID = SLSI_MIN_FILTER_ID,    /* 0x80 */
-       SLSI_LOCAL_ARP_FILTER_ID,                                               /* 0x81 */
-       SLSI_ALL_BC_MC_FILTER_ID,                                               /* 0x82 */
-       SLSI_PROXY_ARP_FILTER_ID,                                               /* 0x83 */
-       SLSI_ALL_IPV6_PKTS_FILTER_ID,                                   /* 0x84 */
+       SLSI_LOCAL_ARP_FILTER_ID = SLSI_MIN_FILTER_ID,                          /* 0x80 */
+       SLSI_ALL_BC_MC_FILTER_ID,                                               /* 0x81 */
+       SLSI_PROXY_ARP_FILTER_ID,                                               /* 0x82 */
+       SLSI_ALL_IPV6_PKTS_FILTER_ID,                                           /* 0x83 */
 #ifndef CONFIG_SCSC_WLAN_DISABLE_NAT_KA
-       SLSI_NAT_IPSEC_FILTER_ID,                                               /* 0x85 */
+       SLSI_NAT_IPSEC_FILTER_ID,                                               /* 0x84 */
 #endif
 #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
-       SLSI_OPT_OUT_ALL_FILTER_ID,                                             /* 0x86 */
-       SLSI_OPT_IN_TCP4_FILTER_ID,                                             /* 0x87 */
-       SLSI_OPT_IN_TCP6_FILTER_ID,                                             /* 0x88 */
+       SLSI_OPT_OUT_ALL_FILTER_ID,                                             /* 0x85 */
+       SLSI_OPT_IN_TCP4_FILTER_ID,                                             /* 0x86 */
+       SLSI_OPT_IN_TCP6_FILTER_ID,                                             /* 0x87 */
 #endif
-       SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID,                             /* 0x89 */
-       SLSI_REGD_MC_FILTER_ID,                                                 /* 0x8A */
+       SLSI_ABNORMAL_MULTICAST_ID,                                             /* 0x85 / 0x88*/
+       SLSI_ALL_ARP_FILTER_ID,                                                 /* 0x86 / 0x89 */
+       SLSI_REGD_MC_FILTER_ID,                                                 /* 0x87 / 0x8a */
 };
 #else
 
 /* for STA */
 enum slsi_filter_id {
-       SLSI_ALL_ARP_FILTER_ID = SLSI_MIN_FILTER_ID,    /* 0x80 */
-       SLSI_LOCAL_ARP_FILTER_ID,                                               /* 0x81 */
-       SLSI_ALL_BC_MC_FILTER_ID,                                               /* 0x82 */
-       SLSI_PROXY_ARP_FILTER_ID,                                               /* 0x83 */
-       SLSI_LOCAL_NS_FILTER_ID,                                                /* 0x84 */
-       SLSI_PROXY_ARP_NA_FILTER_ID,                                    /* 0x85 */
+       SLSI_LOCAL_ARP_FILTER_ID = SLSI_MIN_FILTER_ID,                          /* 0x80 */
+       SLSI_ALL_BC_MC_FILTER_ID,                                               /* 0x81 */
+       SLSI_PROXY_ARP_FILTER_ID,                                               /* 0x82 */
+       SLSI_LOCAL_NS_FILTER_ID,                                                /* 0x83 */
+       SLSI_PROXY_ARP_NA_FILTER_ID,                                            /* 0x84 */
 #ifndef CONFIG_SCSC_WLAN_DISABLE_NAT_KA
-       SLSI_NAT_IPSEC_FILTER_ID,                                               /* 0x86 */
+       SLSI_NAT_IPSEC_FILTER_ID,                                               /* 0x85 */
 #endif
 #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
-       SLSI_OPT_OUT_ALL_FILTER_ID,                                             /* 0x87 */
-       SLSI_OPT_IN_TCP4_FILTER_ID,                                             /* 0x88 */
-       SLSI_OPT_IN_TCP6_FILTER_ID,                                             /* 0x89 */
+       SLSI_OPT_OUT_ALL_FILTER_ID,                                             /* 0x86 */
+       SLSI_OPT_IN_TCP4_FILTER_ID,                                             /* 0x87 */
+       SLSI_OPT_IN_TCP6_FILTER_ID,                                             /* 0x88 */
 #endif
-       SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID,                             /* 0x8a */
-       SLSI_REGD_MC_FILTER_ID,                                                 /* 0x8b */
+       SLSI_ABNORMAL_MULTICAST_ID,                                             /* 0x86 / 0x89 */
+       SLSI_ALL_ARP_FILTER_ID,                                                 /* 0x87 / 0x8a */
+       SLSI_REGD_MC_FILTER_ID,                                                 /* 0x88 / 0x8b */
 };
 
 #endif
@@ -642,12 +644,41 @@ struct slsi_vif_ap {
        u8                                ssid_len;
 };
 
-#define SLSI_NAN_MAX_PUBLISH_ID 16
-#define SLSI_NAN_MAX_SUBSCRIBE_ID 16
+struct slsi_nan_ndl_info {
+    u8 peer_nmi[ETH_ALEN];
+    s8 ndp_count;
+};
+
+enum ndp_slot_status {
+       ndp_slot_status_free,
+       ndp_slot_status_in_use,
+       ndp_slot_status_terminating,
+};
 
 struct slsi_vif_nan {
-       u32 publish_id_map;
-       u32 subscribe_id_map;
+       struct slsi_hal_nan_config_req config;
+       u32 service_id_map;
+       u32 followup_id_map;
+       u32 ndp_id_map;
+       struct slsi_nan_ndl_info ndl_list[SLSI_NAN_MAX_NDP_INSTANCES];
+       u8  ndp_ndi[SLSI_NAN_MAX_NDP_INSTANCES][ETH_ALEN];
+       u16 ndp_id2ndl_vif[SLSI_NAN_MAX_NDP_INSTANCES];
+       u16 ndp_local_ndp_id[SLSI_NAN_MAX_NDP_INSTANCES];
+       enum ndp_slot_status ndp_state[SLSI_NAN_MAX_NDP_INSTANCES];
+       u32 followup_trans_id;
+
+       u8 disable_cluster_merge;
+       u16 nan_sdf_flags[SLSI_NAN_MAX_SERVICE_ID+1];
+       /* fields used for nan stats/status*/
+       u8 local_nmi[ETH_ALEN];
+       u8 cluster_id[ETH_ALEN];
+       u32 operating_channel[2];
+       u8 role;
+       u8 state; /* 1 -> nan on; 0 -> nan off */
+       u8 master_pref_value;
+       u8 amt;
+       u8 hopcount;
+       u32 random_mac_interval_sec;
 };
 
 #define TCP_ACK_SUPPRESSION_RECORDS_MAX                                16
@@ -829,7 +860,9 @@ struct netdev_vif {
        u8 target_ip_addr[4];
        int enhanced_arp_host_tag[5];
 #endif
+#ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
        struct cfg80211_ap_settings backup_settings;
+#endif
 };
 
 struct slsi_802_11d_reg_domain {
@@ -1045,7 +1078,9 @@ struct slsi_dev {
        /* BoT */
        atomic_t                   in_pause_state;
 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
-       struct work_struct recovery_work;   /* Work on failure_reset recovery*/
+       struct work_struct recovery_work;   /* Work on subsystem_reset recovery*/
+       struct work_struct recovery_work_on_stop;   /* Work on failure_reset recovery*/
+       struct work_struct recovery_work_on_start;   /* Work on chip recovery*/
 #endif
        /* Locking used to control Starting and stopping the chip */
 #ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG
@@ -1179,9 +1214,7 @@ struct slsi_dev {
 #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
        bool                       enhanced_pkt_filter_enabled;
 #endif
-#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
-       bool                       abnormal_multicast_pkt_filter_enabled;
-#endif
+       struct reg_database regdb;
 };
 
 /* Compact representation of channels a ESS has been seen on
@@ -1231,7 +1264,6 @@ int slsi_tx_data_lower(struct slsi_dev *sdev, struct sk_buff *skb);
 bool slsi_is_test_mode_enabled(void);
 bool slsi_is_rf_test_mode_enabled(void);
 int slsi_check_rf_test_mode(void);
-void slsi_regd_deinit(struct slsi_dev *sdev);
 void slsi_init_netdev_mac_addr(struct slsi_dev *sdev);
 bool slsi_dev_lls_supported(void);
 bool slsi_dev_gscan_supported(void);
@@ -1240,7 +1272,11 @@ bool slsi_dev_vo_vi_block_ack(void);
 int slsi_dev_get_scan_result_count(void);
 bool slsi_dev_llslogs_supported(void);
 int slsi_dev_nan_supported(struct slsi_dev *sdev);
-void slsi_regd_init(struct slsi_dev *sdev);
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+bool slsi_dev_nan_is_ipv6_link_tlv_include(void);
+int slsi_get_nan_max_ndp_instances(void);
+int slsi_get_nan_max_ndi_ifaces(void);
+#endif
 bool slsi_dev_rtt_supported(void);
 
 //BEGIN IKSAMP-1972
@@ -1296,6 +1332,58 @@ static inline struct net_device *slsi_get_netdev(struct slsi_dev *sdev, u16 ifnu
        return dev;
 }
 
+static inline struct net_device *slsi_get_netdev_by_mac_addr(struct slsi_dev *sdev, u8 *mac_addr, int start_idx)
+{
+       int i;
+
+       if (!start_idx)
+               start_idx = 1;
+       for (i = start_idx; i < CONFIG_SCSC_WLAN_MAX_INTERFACES + 1; i++) {
+               if (sdev->netdev[i] && ether_addr_equal(mac_addr, sdev->netdev[i]->dev_addr))
+                       return sdev->netdev[i];
+       }
+       return NULL;
+}
+
+static inline struct net_device *slsi_get_netdev_by_mac_addr_lockless(struct slsi_dev *sdev, u8 *mac_addr, int start_idx)
+{
+       return slsi_get_netdev_by_mac_addr(sdev, mac_addr, start_idx);
+}
+
+static inline struct net_device *slsi_get_netdev_by_mac_addr_locked(struct slsi_dev *sdev, u8 *mac_addr, int start_idx)
+{
+       struct net_device *dev;
+
+       SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex);
+       dev = slsi_get_netdev_by_mac_addr(sdev, mac_addr, start_idx);
+       SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex);
+
+       return dev;
+}
+
+static inline struct net_device *slsi_get_netdev_by_ifname_locked(struct slsi_dev *sdev, u8 *ifname)
+{
+       int i;
+
+       WARN_ON(!SLSI_MUTEX_IS_LOCKED(sdev->netdev_add_remove_mutex));
+       for (i = 1; i < CONFIG_SCSC_WLAN_MAX_INTERFACES + 1; i++) {
+               if (sdev->netdev[i] && strcmp(ifname, sdev->netdev[i]->name) == 0)
+                       return sdev->netdev[i];
+       }
+       return NULL;
+}
+
+static inline struct net_device *slsi_get_netdev_by_ifname(struct slsi_dev *sdev, u8 *ifname)
+{
+       struct net_device *dev;
+
+       SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex);
+       dev = slsi_get_netdev_by_ifname_locked(sdev, ifname);
+       SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex);
+
+       return dev;
+}
+
 static inline int slsi_get_supported_mode(const u8 *peer_ie)
 {
        const u8             *peer_ie_data;
index 2148bebe6fb941f7328738dd70fa3a33a97dcf8d..b63f831e5034855b2b39288e4da2ca7167ac971d 100644 (file)
@@ -53,12 +53,12 @@ static inline struct slsi_skb_cb *slsi_skb_cb_init(struct sk_buff *skb)
 
 #define FAPI_DEBUG_SAP_ENG_VERSION               0x0001
 #define FAPI_DATA_SAP_ENG_VERSION                0x0001
-#define FAPI_CONTROL_SAP_ENG_VERSION             0x0009
+#define FAPI_CONTROL_SAP_ENG_VERSION             0x000a
 #define FAPI_TEST_SAP_ENG_VERSION                0x0010
 #define FAPI_DEBUG_SAP_VERSION                   0x0d03
 #define FAPI_TEST_SAP_VERSION                    0x0e00
-#define FAPI_DATA_SAP_VERSION                    0x0e00
-#define FAPI_CONTROL_SAP_VERSION                 0x0e02
+#define FAPI_DATA_SAP_VERSION                    0x0e01
+#define FAPI_CONTROL_SAP_VERSION                 0x0e03
 
 #define FAPI_ACLPOLICY_BLACKLIST   0x0000
 #define FAPI_ACLPOLICY_WHITELIST   0x0001
@@ -75,6 +75,10 @@ static inline struct slsi_skb_cb *slsi_skb_cb_init(struct sk_buff *skb)
 #define FAPI_AUTHENTICATIONTYPE_SAE           0x0003
 #define FAPI_AUTHENTICATIONTYPE_LEAP          0x0080
 
+#define FAPI_BAND_AUTO     0x0000
+#define FAPI_BAND_5GHZ     0x0001
+#define FAPI_BAND_2_4GHZ   0x0002
+
 #define FAPI_BANDWIDTH_20_MHZ    0x0
 #define FAPI_BANDWIDTH_40_MHZ    0x1
 #define FAPI_BANDWIDTH_80_MHZ    0x2
@@ -1039,7 +1043,7 @@ static inline struct slsi_skb_cb *slsi_skb_cb_init(struct sk_buff *skb)
 #define FAPI_RESULTCODE_ASSOC_FAILED_CODE                   0x8200
 #define FAPI_RESULTCODE_INVALID_TLV_VALUE                   0x9000
 #define FAPI_RESULTCODE_NAN_PROTOCOL_FAILURE                0x9001
-#define FAPI_RESULTCODE_NAN_INVALID_PUBLISH_SUBSCRIBE_ID    0x9002
+#define FAPI_RESULTCODE_NAN_INVALID_SESSION_ID              0x9002
 #define FAPI_RESULTCODE_NAN_INVALID_REQUESTOR_INSTANCE_ID   0x9003
 #define FAPI_RESULTCODE_UNSUPPORTED_CONCURRENCY             0x9004
 #define FAPI_RESULTCODE_NAN_INVALID_NDP_ID                  0x9005
@@ -1052,6 +1056,9 @@ static inline struct slsi_skb_cb *slsi_skb_cb_init(struct sk_buff *skb)
 #define FAPI_RESULTCODE_NDL_UNACCEPTABLE                    0x900c
 #define FAPI_RESULTCODE_NDL_FAILED_SCHEDULE                 0x900d
 
+#define FAPI_ROAMINGTYPE_LEGACY   0x0000
+#define FAPI_ROAMINGTYPE_NCHO     0x0001
+
 #define FAPI_RTTBANDWIDTH_20MHZ    0x0004
 #define FAPI_RTTBANDWIDTH_40MHZ    0x0008
 #define FAPI_RTTBANDWIDTH_80MHZ    0x0010
@@ -1104,25 +1111,23 @@ static inline struct slsi_skb_cb *slsi_skb_cb_init(struct sk_buff *skb)
 #define FAPI_SCANPOLICY_DFS          0x40
 #define FAPI_SCANPOLICY_ON_CHANNEL   0x80
 
-#define FAPI_SCANTYPE_INITIAL_SCAN                  0x0001
-#define FAPI_SCANTYPE_FULL_SCAN                     0x0002
-#define FAPI_SCANTYPE_SCHEDULED_SCAN                0x0003
-#define FAPI_SCANTYPE_P2P_SCAN_FULL                 0x0004
-#define FAPI_SCANTYPE_P2P_SCAN_SOCIAL               0x0005
-#define FAPI_SCANTYPE_OBSS_SCAN                     0x0006
-#define FAPI_SCANTYPE_AP_AUTO_CHANNEL_SELECTION     0x0007
-#define FAPI_SCANTYPE_GSCAN                         0x0009
-#define FAPI_SCANTYPE_MEASUREMENT_SCAN              0x000a
-#define FAPI_SCANTYPE_SOFT_NEIGHBOUR_ROAMING_SCAN   0x000b
-#define FAPI_SCANTYPE_SOFT_CACHED_ROAMING_SCAN      0x000c
-#define FAPI_SCANTYPE_SOFT_ALL_ROAMING_SCAN         0x000d
-#define FAPI_SCANTYPE_HARD_NEIGHBOUR_ROAMING_SCAN   0x000e
-#define FAPI_SCANTYPE_HARD_CACHED_ROAMING_SCAN      0x000f
-#define FAPI_SCANTYPE_HARD_ALL_ROAMING_SCAN         0x0010
-#define FAPI_SCANTYPE_OBSS_SCAN_INTERNAL            0x0011
-#define FAPI_SCANTYPE_NAN_SCAN                      0x0012
-#define FAPI_SCANTYPE_FTM_NEIGHBOUR_SCAN            0x0013
-#define FAPI_SCANTYPE_FIRST_ILLEGAL                 0x0014
+#define FAPI_SCANTYPE_INITIAL_SCAN                0x0001
+#define FAPI_SCANTYPE_FULL_SCAN                   0x0002
+#define FAPI_SCANTYPE_SCHEDULED_SCAN              0x0003
+#define FAPI_SCANTYPE_P2P_SCAN_FULL               0x0004
+#define FAPI_SCANTYPE_P2P_SCAN_SOCIAL             0x0005
+#define FAPI_SCANTYPE_OBSS_SCAN                   0x0006
+#define FAPI_SCANTYPE_AP_AUTO_CHANNEL_SELECTION   0x0007
+#define FAPI_SCANTYPE_GSCAN                       0x0009
+#define FAPI_SCANTYPE_MEASUREMENT_SCAN            0x000a
+#define FAPI_SCANTYPE_SOFT_CACHED_ROAMING_SCAN    0x000b
+#define FAPI_SCANTYPE_SOFT_ALL_ROAMING_SCAN       0x000c
+#define FAPI_SCANTYPE_HARD_CACHED_ROAMING_SCAN    0x000d
+#define FAPI_SCANTYPE_HARD_ALL_ROAMING_SCAN       0x000e
+#define FAPI_SCANTYPE_OBSS_SCAN_INTERNAL          0x000f
+#define FAPI_SCANTYPE_NAN_SCAN                    0x0010
+#define FAPI_SCANTYPE_FTM_NEIGHBOUR_SCAN          0x0011
+#define FAPI_SCANTYPE_FIRST_ILLEGAL               0x0012
 
 #define FAPI_STATSSTOPBITMAP_STATS_RADIO              0x0001
 #define FAPI_STATSSTOPBITMAP_STATS_RADIO_CCA          0x0002
@@ -1317,9 +1322,11 @@ static inline struct slsi_skb_cb *slsi_skb_cb_init(struct sk_buff *skb)
 #define MLME_READ_APF_REQ                     0x203e
 #define MLME_SET_NUM_ANTENNAS_REQ             0x203f
 #define MLME_ARP_DETECT_REQ                   0x2040
-#define MLME_SPARE_SIGNAL_1_REQ               0x2041
-#define MLME_SPARE_SIGNAL_2_REQ               0x2042
-#define MLME_SPARE_SIGNAL_3_REQ               0x2043
+#define MLME_SET_ROAMING_TYPE_REQ             0x2041
+#define MLME_SET_BAND_REQ                     0x2042
+#define MLME_SPARE_SIGNAL_1_REQ               0x2043
+#define MLME_SPARE_SIGNAL_2_REQ               0x2044
+#define MLME_SPARE_SIGNAL_3_REQ               0x2045
 #define MLME_GET_CFM                          0x2101
 #define MLME_SET_CFM                          0x2102
 #define MLME_POWERMGT_CFM                     0x2103
@@ -1376,9 +1383,11 @@ static inline struct slsi_skb_cb *slsi_skb_cb_init(struct sk_buff *skb)
 #define MLME_READ_APF_CFM                     0x213e
 #define MLME_SET_NUM_ANTENNAS_CFM             0x213f
 #define MLME_ARP_DETECT_CFM                   0x2140
-#define MLME_SPARE_SIGNAL_1_CFM               0x2141
-#define MLME_SPARE_SIGNAL_2_CFM               0x2142
-#define MLME_SPARE_SIGNAL_3_CFM               0x2143
+#define MLME_SET_ROAMING_TYPE_CFM             0x2141
+#define MLME_SET_BAND_CFM                     0x2142
+#define MLME_SPARE_SIGNAL_1_CFM               0x2143
+#define MLME_SPARE_SIGNAL_2_CFM               0x2144
+#define MLME_SPARE_SIGNAL_3_CFM               0x2145
 #define MLME_CONNECT_RES                      0x2200
 #define MLME_CONNECTED_RES                    0x2201
 #define MLME_REASSOCIATE_RES                  0x2202
@@ -2142,7 +2151,7 @@ struct fapi_signal {
                } __packed mlme_nan_config_req;
                struct {
                        __le16 vif;
-                       __le16 publish_id;
+                       __le16 session_id;
                        __le16 nan_sdf_flags;
                        __le32 spare_1;
                        __le32 spare_2;
@@ -2151,7 +2160,7 @@ struct fapi_signal {
                } __packed mlme_nan_publish_req;
                struct {
                        __le16 vif;
-                       __le16 subscribe_id;
+                       __le16 session_id;
                        __le16 nan_sdf_flags;
                        __le32 spare_1;
                        __le32 spare_2;
@@ -2160,7 +2169,7 @@ struct fapi_signal {
                } __packed mlme_nan_subscribe_req;
                struct {
                        __le16 vif;
-                       __le16 publish_subscribe_id;
+                       __le16 session_id;
                        __le16 match_id;
                        __le16 nan_sdf_flags;
                        __le32 spare_1;
@@ -2203,7 +2212,7 @@ struct fapi_signal {
                } __packed mlme_ndp_request_req;
                struct {
                        __le16 vif;
-                       __le16 local_ndp_id;
+                       __le16 request_id;
                        __le16 ndl_vif_index;
                        __le16 reason_code;
                        u8     local_ndp_interface_address[ETH_ALEN];
@@ -2273,6 +2282,22 @@ struct fapi_signal {
                        __le32 spare_3;
                        u8     dr[0];
                } __packed mlme_arp_detect_req;
+               struct {
+                       __le16 vif;
+                       __le16 roaming_type;
+                       __le32 spare_1;
+                       __le32 spare_2;
+                       __le32 spare_3;
+                       u8     dr[0];
+               } __packed mlme_set_roaming_type_req;
+               struct {
+                       __le16 vif;
+                       __le16 band;
+                       __le32 spare_1;
+                       __le32 spare_2;
+                       __le32 spare_3;
+                       u8     dr[0];
+               } __packed mlme_set_band_req;
                struct {
                        __le16 vif;
                        __le32 spare_1;
@@ -2746,6 +2771,22 @@ struct fapi_signal {
                        __le32 spare_3;
                        u8     dr[0];
                } __packed mlme_arp_detect_cfm;
+               struct {
+                       __le16 vif;
+                       __le16 result_code;
+                       __le32 spare_1;
+                       __le32 spare_2;
+                       __le32 spare_3;
+                       u8     dr[0];
+               } __packed mlme_set_roaming_type_cfm;
+               struct {
+                       __le16 vif;
+                       __le16 result_code;
+                       __le32 spare_1;
+                       __le32 spare_2;
+                       __le32 spare_3;
+                       u8     dr[0];
+               } __packed mlme_set_band_cfm;
                struct {
                        __le16 vif;
                        __le16 result_code;
@@ -3048,7 +3089,7 @@ struct fapi_signal {
                } __packed mlme_nan_event_ind;
                struct {
                        __le16 vif;
-                       __le16 publish_subscribe_id;
+                       __le16 session_id;
                        __le16 match_id;
                        __le32 ranging_measurement;
                        __le16 rangingindicationtype;
@@ -3059,7 +3100,7 @@ struct fapi_signal {
                } __packed mlme_nan_service_ind;
                struct {
                        __le16 vif;
-                       __le16 publish_subscribe_id;
+                       __le16 session_id;
                        __le16 match_id;
                        u8     peer_nan_management_interface_address[ETH_ALEN];
                        __le32 spare_1;
@@ -3119,8 +3160,8 @@ struct fapi_signal {
                } __packed mlme_ndp_request_ind;
                struct {
                        __le16 vif;
-                       __le16 publish_subscribe_id;
-                       __le16 local_ndp_id;
+                       __le16 session_id;
+                       __le16 request_id;
                        u8     peer_nan_management_interface_address[ETH_ALEN];
                        __le16 security_required;
                        __le32 spare_1;
@@ -4330,6 +4371,8 @@ static inline u16 fapi_get_expected_size(struct sk_buff *skb)
                fapi_sig_size(mlme_read_apf_req),
                fapi_sig_size(mlme_set_num_antennas_req),
                fapi_sig_size(mlme_arp_detect_req),
+               fapi_sig_size(mlme_set_roaming_type_req),
+               fapi_sig_size(mlme_set_band_req),
                fapi_sig_size(mlme_spare_signal_1_req),
                fapi_sig_size(mlme_spare_signal_2_req),
                fapi_sig_size(mlme_spare_signal_3_req),
@@ -4461,6 +4504,8 @@ static inline u16 fapi_get_expected_size(struct sk_buff *skb)
                fapi_sig_size(mlme_read_apf_cfm),
                fapi_sig_size(mlme_set_num_antennas_cfm),
                fapi_sig_size(mlme_arp_detect_cfm),
+               fapi_sig_size(mlme_set_roaming_type_cfm),
+               fapi_sig_size(mlme_set_band_cfm),
                fapi_sig_size(mlme_spare_signal_1_cfm),
                fapi_sig_size(mlme_spare_signal_2_cfm),
                fapi_sig_size(mlme_spare_signal_3_cfm),
index 31decad088ab9b08987dd96858d951920fcd9fac..52c7a55b8191301357f53c1c6b6394710f460609 100755 (executable)
@@ -992,7 +992,8 @@ static void hip4_watchdog(unsigned long data)
 
 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
        if (conf_hip4_ver == 4) {
-               for (u8 i = 0; i < MIF_HIP_CFG_Q_NUM; i++) {
+               u8 i;
+               for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++) {
                        if (hip->hip_priv->intr_tohost_mul[i] == MIF_NO_IRQ)
                                continue;
                        if (scsc_service_mifintrbit_bit_mask_status_get(service) & (1 << hip->hip_priv->intr_tohost_mul[i])) {
@@ -1086,15 +1087,15 @@ static void hip4_wq_fb(struct work_struct *data)
                /* colour is defined as: */
                /* u16 register bits:
                 * 0      - do not use
-                * [2:1]  - vif
-                * [7:3]  - peer_index
+                * [3:1]  - vif
+                * [7:4]  - peer_index
                 * [10:8] - ac queue
                 */
                colour = ((m->clas & 0xc0) << 2) | (m->pid & 0xfe);
                /* Account ONLY for data RFB */
                if ((m->pid & 0x1) == MBULK_POOL_ID_DATA) {
 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
-                       SCSC_HIP4_SAMPLER_VIF_PEER(hip->hip_priv->minor, 0, (colour & 0x6) >> 1, (colour & 0xf8) >> 3);
+                       SCSC_HIP4_SAMPLER_VIF_PEER(hip->hip_priv->minor, 0, (colour & 0xE) >> 1, (colour & 0xF0) >> 4);
                        /* to profile round-trip */
                        {
                                u16 host_tag;
@@ -1708,15 +1709,15 @@ static void hip4_wq(struct work_struct *data)
                /* colour is defined as: */
                /* u16 register bits:
                 * 0      - do not use
-                * [2:1]  - vif
-                * [7:3]  - peer_index
+                * [3:1]  - vif
+                * [7:4]  - peer_index
                 * [10:8] - ac queue
                 */
                colour = ((m->clas & 0xc0) << 2) | (m->pid & 0xfe);
                /* Account ONLY for data RFB */
                if ((m->pid & 0x1) == MBULK_POOL_ID_DATA) {
 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
-                       SCSC_HIP4_SAMPLER_VIF_PEER(hip->hip_priv->minor, 0, (colour & 0x6) >> 1, (colour & 0xf8) >> 3);
+                       SCSC_HIP4_SAMPLER_VIF_PEER(hip->hip_priv->minor, 0, (colour & 0xE) >> 1, (colour & 0xF0) >> 4);
                        /* to profile round-trip */
                        {
                                u16 host_tag;
@@ -2694,7 +2695,8 @@ void hip4_suspend(struct slsi_hip4 *hip)
        conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init);
 
        if (conf_hip4_ver == 4) {
-               for (u8 i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
+               u8 i;
+               for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
                        if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ)
                                scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[i]);
        } else {
@@ -2729,7 +2731,8 @@ void hip4_resume(struct slsi_hip4 *hip)
        conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init);
 
        if (conf_hip4_ver == 4) {
-               for (u8 i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
+               u8 i;
+               for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
                        if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ)
                                scsc_service_mifintrbit_bit_unmask(service, hip->hip_priv->intr_tohost_mul[i]);
        } else {
@@ -2772,7 +2775,8 @@ void hip4_freeze(struct slsi_hip4 *hip)
        conf_hip4_ver = scsc_wifi_get_hip_config_version(&hip->hip_control->init);
 
        if (conf_hip4_ver == 4) {
-               for (u8 i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
+               u8 i;
+               for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
                        if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ)
                                scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[i]);
 
@@ -2799,7 +2803,9 @@ void hip4_deinit(struct slsi_hip4 *hip)
 {
        struct slsi_dev     *sdev = container_of(hip, struct slsi_dev, hip4_inst);
        struct scsc_service *service;
-
+#ifdef CONFIG_SCSC_WLAN_RX_NAPI
+       u8 i;
+#endif
        if (!sdev || !sdev->service)
                return;
 
@@ -2828,7 +2834,7 @@ void hip4_deinit(struct slsi_hip4 *hip)
        atomic_set(&hip->hip_priv->closing, 1);
 
 #ifdef CONFIG_SCSC_WLAN_RX_NAPI
-       for (u8 i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
+       for (i = 0; i < MIF_HIP_CFG_Q_NUM; i++)
                if (hip->hip_priv->intr_tohost_mul[i] != MIF_NO_IRQ)
                        scsc_service_mifintrbit_bit_mask(service, hip->hip_priv->intr_tohost_mul[i]);
 
index 972a2d243ccd58b9c67ccbf3fdf41f22038341ef..1a0beb142106e53f71af523cd29a8eb3ef2ecbde 100755 (executable)
 #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
 #define CMD_ENHANCED_PKT_FILTER "ENHANCED_PKT_FILTER"
 #endif
-#ifdef SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
-#define CMD_ABNORMAL_MULTICAST_PKT_FILTER "ABNORMAL_MULTICAST_PKT_FILTER"
-#endif
 #define CMD_GET_MAX_LINK_SPEED "GET_MAX_LINK_SPEED"
 
 #ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS
@@ -2030,8 +2027,6 @@ int slsi_set_fcc_channel(struct net_device *dev, char *cmd, int cmd_len)
        int                  status;
        bool                 flight_mode_ena;
        u8                   host_state;
-       int                  err;
-       char                 alpha2[3];
 
        /* SET_FCC_CHANNEL 0 when device is in flightmode */
        flight_mode_ena = (cmd[0]  == '0');
@@ -2048,20 +2043,8 @@ int slsi_set_fcc_channel(struct net_device *dev, char *cmd, int cmd_len)
        if (status) {
                SLSI_ERR(sdev, "Err setting MMaxPowerEna. error = %d\n", status);
        } else {
-               err = slsi_read_default_country(sdev, alpha2, 1);
-               if (err) {
-                       SLSI_WARN(sdev, "Err updating reg_rules = %d\n", err);
-               } else {
-                       memcpy(sdev->device_config.domain_info.regdomain->alpha2, alpha2, 2);
-                       /* Read the regulatory params for the country.*/
-                       if (slsi_read_regulatory_rules(sdev, &sdev->device_config.domain_info, alpha2) == 0) {
-                               slsi_reset_channel_flags(sdev);
-                               wiphy_apply_custom_regulatory(sdev->wiphy, sdev->device_config.domain_info.regdomain);
-                               slsi_update_supported_channels_regd_flags(sdev);
-                               if (flight_mode_ena && sdev->device_config.disable_ch12_ch13)
-                                       slsi_disable_ch12_13(sdev);
-                       }
-               }
+               if (flight_mode_ena && sdev->device_config.disable_ch12_ch13)
+                       slsi_disable_ch12_13(sdev);
        }
        SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
 
@@ -2610,10 +2593,11 @@ int slsi_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        } else if (strncasecmp(command, CMD_GETWESMODE, strlen(CMD_GETWESMODE)) == 0) {
                ret = slsi_wes_mode_read(dev, command, priv_cmd.total_len);
        } else if (strncasecmp(command, CMD_SETROAMSCANCHANNELS, strlen(CMD_SETROAMSCANCHANNELS)) == 0) {
-               int skip = strlen(CMD_SETROAMSCANCHANNELS) + 1;
-
-               ret = slsi_roam_scan_channels_write(dev, command + skip,
+               u8 skip = strlen(CMD_SETROAMSCANCHANNELS) + 1;
+               if (skip <= priv_cmd.total_len) {
+                       ret = slsi_roam_scan_channels_write(dev, command + skip,
                                                    priv_cmd.total_len - skip);
+               }
        } else if (strncasecmp(command, CMD_GETROAMSCANCHANNELS, strlen(CMD_GETROAMSCANCHANNELS)) == 0) {
                ret = slsi_roam_scan_channels_read(dev, command, priv_cmd.total_len);
 #endif
@@ -2622,9 +2606,10 @@ int slsi_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        } else if (strncasecmp(command, CMD_HAPD_GET_CHANNEL, strlen(CMD_HAPD_GET_CHANNEL)) == 0) {
                ret = slsi_auto_chan_read(dev, command, priv_cmd.total_len);
        } else if (strncasecmp(command, CMD_SET_SAP_CHANNEL_LIST, strlen(CMD_SET_SAP_CHANNEL_LIST)) == 0) {
-               int skip = strlen(CMD_SET_SAP_CHANNEL_LIST) + 1;
-
-               ret = slsi_auto_chan_write(dev, command + skip);
+               u8 skip = strlen(CMD_SET_SAP_CHANNEL_LIST) + 1;
+               if (skip <= priv_cmd.total_len) {
+                       ret = slsi_auto_chan_write(dev, command + skip);
+               }
        } else if (strncasecmp(command, CMD_REASSOC, strlen(CMD_REASSOC)) == 0) {
                int skip = strlen(CMD_REASSOC) + 1;
 
@@ -2750,12 +2735,6 @@ int slsi_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
                ret = slsi_set_enhanced_pkt_filter(dev, enable);
 #endif
-#ifdef SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
-       } else if ((strncasecmp(command, CMD_ABNORMAL_MULTICAST_PKT_FILTER, strlen(CMD_ABNORMAL_MULTICAST_PKT_FILTER)) == 0)) {
-               const u8 enable = *(command + strlen(CMD_ABNORMAL_MULTICAST_PKT_FILTER) + 1) - '0';
-
-               ret = slsi_set_abnormal_multicast_pkt_filter(dev, enable);
-#endif
 #ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS
        } else if (strncasecmp(command, CMD_SET_NUM_ANTENNAS, strlen(CMD_SET_NUM_ANTENNAS)) == 0) {
                struct netdev_vif *ndev_vif = netdev_priv(dev);
index 0a8dca9176d9ee12b0e34fbb48472c7ad90178e1..206d6e768323c9e907a2fb8d9190ad5fa57609d6 100755 (executable)
@@ -112,7 +112,7 @@ static ssize_t sysfs_store_macaddr(struct kobject *kobj,
        SLSI_INFO_NODEV("Override WLAN MAC address %s\n", buf);
 
        /* size of macaddr string */
-       r = sscanf(buf, "%18s", &sysfs_mac_override);
+       r = sscanf(buf, "%17s", &sysfs_mac_override);
 
        return (r > 0) ? count : 0;
 }
@@ -574,7 +574,7 @@ int slsi_start(struct slsi_dev *sdev)
 #ifndef CONFIG_SCSC_DOWNLOAD_FILE
        const struct firmware *fw[SLSI_WLAN_MAX_MIB_FILE] = { NULL, NULL };
 #endif
-       int  err = 0, r;
+       int  err = 0, r, reg_err = 0;
        int i;
        char alpha2[3];
 #ifdef CONFIG_SCSC_WLAN_AP_INFO_FILE
@@ -588,10 +588,8 @@ int slsi_start(struct slsi_dev *sdev)
        char buf[512];
 #endif
 #ifdef CONFIG_SCSC_WLAN_SET_PREFERRED_ANTENNA
-       struct file *file_ptr = NULL;
        char *ant_file_path = "/data/vendor/conn/.ant.info";
-       char ant_mode = '0';
-       u16 antenna = 0;
+       char *antenna_file_path = "/data/vendor/wifi/antenna.info";
 #endif
 
        if (WARN_ON(!sdev))
@@ -672,6 +670,7 @@ int slsi_start(struct slsi_dev *sdev)
                slsi_sm_wlan_service_close(sdev);
                goto err_done;
        }
+
        for (i = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++)
                slsi_mib_close_file(sdev, fw[i]);
 #else
@@ -703,19 +702,29 @@ int slsi_start(struct slsi_dev *sdev)
        SLSI_INFO(sdev, "Platform : 0x%.4X (%u)\n", sdev->plat_info_mib.plat_build, sdev->plat_info_mib.plat_build);
        slsi_cfg80211_update_wiphy(sdev);
 
-       /* Get UnifiCountryList */
        SLSI_MUTEX_LOCK(sdev->device_config_mutex);
        sdev->device_config.host_state = SLSI_HOSTSTATE_CELLULAR_ACTIVE;
-       err = slsi_read_unifi_countrylist(sdev, SLSI_PSID_UNIFI_COUNTRY_LIST);
+       reg_err = slsi_read_regulatory(sdev);
+       if (reg_err) {
+               SLSI_ERR(sdev, "Error in reading regulatory!\n");
+               /* Get UnifiCountryList */
+               err = slsi_read_unifi_countrylist(sdev, SLSI_PSID_UNIFI_COUNTRY_LIST);
+               if (err) {
+                       SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
+                       goto err_hip_started;
+               }
+       }
        SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
-       if (err)
-               goto err_hip_started;
 
-       /* Get unifiDefaultCountry  */
-       err = slsi_read_default_country(sdev, alpha2, 1);
+       alpha2[0] = '0';
+       alpha2[1] = '0';
        alpha2[2] = '\0';
-       if (err < 0)
-               goto err_hip_started;
+       if (!slsi_is_test_mode_enabled()) {
+               err = slsi_mlme_set_country(sdev, alpha2);
+
+               if (err < 0)
+                       goto err_hip_started;
+       }
 
        /* unifiDefaultCountry != world_domain */
        if (!(alpha2[0] == '0' && alpha2[1] == '0'))
@@ -769,25 +778,10 @@ int slsi_start(struct slsi_dev *sdev)
 
 #ifdef CONFIG_SCSC_WLAN_SET_PREFERRED_ANTENNA
        if (slsi_is_rf_test_mode_enabled()) {
-               /* reading antenna mode from /data/vendor/conn/.ant.info */
-               file_ptr = filp_open(ant_file_path, O_RDONLY, 0);
-               /* if file is not found, set the default antenna value to 3(ANT_ALL) */
-               if (!file_ptr)  {
-                       SLSI_DBG1(sdev, SLSI_CFG80211, "%s doesn't exist\n", ant_file_path);
-                       slsi_set_mib_preferred_antenna(sdev, 3);
-               } else if (IS_ERR(file_ptr)) {
-                       SLSI_DBG1(sdev, SLSI_CFG80211, "%s open returned error %d\n", ant_file_path, IS_ERR(file_ptr));
-                       slsi_set_mib_preferred_antenna(sdev, 3);
-               } else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
-                       kernel_read(file_ptr, &ant_mode, 1, &file_ptr->f_pos);
-#else
-                       kernel_read(file_ptr, file_ptr->f_pos, &ant_mode, 1);
-#endif
-                       antenna = ant_mode - '0';
-                       filp_close(file_ptr, NULL);
-
-                       slsi_set_mib_preferred_antenna(sdev, antenna);
+               /* reading antenna mode from configured file /data/vendor/conn/.ant.info */
+               if (!(slsi_read_preferred_antenna_from_file(sdev, ant_file_path))) {
+                       /* reading antenna mode from configured file /data/vendor/wifi/antenna.info */
+                       slsi_read_preferred_antenna_from_file(sdev, antenna_file_path);
                }
        }
 #endif
@@ -802,6 +796,9 @@ int slsi_start(struct slsi_dev *sdev)
        SLSI_DBG2(sdev, SLSI_INIT_DEINIT, "---Driver started successfully---\n");
        sdev->device_state = SLSI_DEVICE_STATE_STARTED;
        memset(sdev->rtt_vif, -1, sizeof(sdev->rtt_vif));
+#ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
+       sdev->cm_if.recovery_state = SLSI_RECOVERY_SERVICE_STARTED;
+#endif
        SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex);
 
        slsi_kic_system_event(slsi_kic_system_event_category_initialisation,
@@ -830,6 +827,30 @@ done:
        return err;
 }
 
+#ifdef CONFIG_SCSC_WLAN_SET_PREFERRED_ANTENNA
+bool slsi_read_preferred_antenna_from_file(struct slsi_dev *sdev, char *antenna_file_path) {
+       char ant_mode = '0';
+       u16 antenna = 0;
+       struct file *file_ptr = NULL;
+
+       file_ptr = filp_open(antenna_file_path, O_RDONLY, 0);
+       if (!file_ptr || IS_ERR(file_ptr)) {
+               SLSI_DBG1(sdev, SLSI_CFG80211, "%s open returned error %d\n", antenna_file_path, IS_ERR(file_ptr));
+               return false;
+       } else {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
+               kernel_read(file_ptr, &ant_mode, 1, &file_ptr->f_pos);
+#else
+               kernel_read(file_ptr, file_ptr->f_pos, &ant_mode, 1);
+#endif
+               antenna = ant_mode - '0';
+               filp_close(file_ptr, NULL);
+               slsi_set_mib_preferred_antenna(sdev, antenna);
+               return true;
+       }
+}
+#endif
+
 struct net_device *slsi_dynamic_interface_create(struct wiphy        *wiphy,
                                             const char          *name,
                                             enum nl80211_iftype type,
@@ -918,6 +939,28 @@ static void slsi_stop_chip(struct slsi_dev *sdev)
        SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
 }
 
+#ifdef SCSC_WIFI_NAN_ENABLE
+void slsi_ndl_vif_cleanup(struct slsi_dev *sdev, struct net_device *dev, bool hw_available)
+{
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+       int i;
+       struct slsi_peer *peer;
+       u32 ndp_id;
+       struct net_device *nan_mgmt_dev = slsi_nan_get_netdev(sdev);
+
+       netif_carrier_off(dev);
+       for (i = 0; i < SLSI_ADHOC_PEER_CONNECTIONS_MAX; i++) {
+               peer = ndev_vif->peer_sta_record[i];
+               if (peer && peer->valid) {
+                       ndp_id = slsi_nan_get_ndp_from_ndl_local_ndi(nan_mgmt_dev, peer->ndl_vif, dev->dev_addr);
+                       slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED);
+                       slsi_peer_remove(sdev, dev, peer);
+                       if (nan_mgmt_dev && ndp_id < SLSI_NAN_MAX_NDP_INSTANCES + 1)
+                               slsi_nan_ndp_del_entry(sdev, nan_mgmt_dev, ndp_id);
+               }
+       }
+}
+#endif
 void slsi_vif_cleanup(struct slsi_dev *sdev, struct net_device *dev, bool hw_available)
 {
        struct netdev_vif *ndev_vif = netdev_priv(dev);
@@ -926,7 +969,12 @@ void slsi_vif_cleanup(struct slsi_dev *sdev, struct net_device *dev, bool hw_ava
        SLSI_NET_DBG3(dev, SLSI_INIT_DEINIT, "clean VIF\n");
 
        WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
-
+#ifdef SCSC_WIFI_NAN_ENABLE
+       if (ndev_vif->ifnum >= SLSI_NAN_DATA_IFINDEX_START) {
+               slsi_ndl_vif_cleanup(sdev, dev, hw_available);
+               return;
+       }
+#endif
        if (ndev_vif->activated) {
                netif_carrier_off(dev);
                for (i = 0; i < SLSI_ADHOC_PEER_CONNECTIONS_MAX; i++) {
@@ -1046,8 +1094,6 @@ static void slsi_stop_net_dev_locked(struct slsi_dev *sdev, struct net_device *d
                return;
        }
 
-       complete_all(&ndev_vif->sig_wait.completion);
-
        slsi_scan_cleanup(sdev, dev);
 
        SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
@@ -1056,6 +1102,7 @@ static void slsi_stop_net_dev_locked(struct slsi_dev *sdev, struct net_device *d
        sdev->netdev_up_count--;
        SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
 
+       complete_all(&ndev_vif->sig_wait.completion);
        slsi_stop_chip(sdev);
 }
 
@@ -1281,7 +1328,7 @@ static int slsi_mib_open_file(struct slsi_dev *sdev, struct slsi_dev_mib_info *m
 
        if (!mib_file_name || !fw)
                return -EINVAL;
-       if(index > SLSI_WLAN_MAX_MIB_FILE + 1) {
+       if (index > SLSI_WLAN_MAX_MIB_FILE + 1) {
                SLSI_ERR(sdev, "collect mib index is invalid:%d\n", index);
                return -EINVAL;
        }
@@ -1481,13 +1528,19 @@ static int slsi_mib_initial_get(struct slsi_dev *sdev)
                }
 
                if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) {    /* SUPPORTED_CHANNELS */
-                       int k = 0;
-                       int increment = 4; /* increment channel by 4 for 5G and by 1 for 2G */
-                       int buf_len = 150; /* 150 bytes for 14+25=39 channels and spaces between them */
-                       char *supported_channels_buffer = kmalloc(buf_len, GFP_KERNEL);
-                       int buf_pos = 0;
                        SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_OCTET);
                        if (values[mib_index].type == SLSI_MIB_TYPE_OCTET) {
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+                               int k = 0;
+                               int increment = 4; /* increment channel by 4 for 5G and by 1 for 2G */
+                               int buf_len = 150; /* 150 bytes for 14+25=39 channels and spaces between them */
+                               char *supported_channels_buffer = NULL;
+                               int buf_pos = 0;
+
+                               supported_channels_buffer = kmalloc(buf_len, GFP_KERNEL);
+                               if (!supported_channels_buffer)
+                                       return -ENOMEM;
+#endif
                                sdev->band_5g_supported = 0;
                                memset(sdev->supported_2g_channels, 0, sizeof(sdev->supported_2g_channels));
                                memset(sdev->supported_5g_channels, 0, sizeof(sdev->supported_5g_channels));
@@ -1500,13 +1553,17 @@ static int slsi_mib_initial_get(struct slsi_dev *sdev)
                                        }
                                }
                                for (i = 0; i < values[mib_index].u.octetValue.dataLength; i += 2) {
-                                       increment = 4;
-                                       k = 0;
                                        chan_start = values[mib_index].u.octetValue.data[i];
                                        chan_count = values[mib_index].u.octetValue.data[i + 1];
                                        band = sdev->supported_5g_channels;
-                                       if (chan_start < 15) {
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+                                       k = 0;
+                                       if (chan_start < 15)
                                                increment = 1;
+                                       else
+                                               increment = 4;
+#endif
+                                       if (chan_start < 15) {
                                                index = chan_start - 1;
                                                band = sdev->supported_2g_channels;
                                        } else if (chan_start >= 36 && chan_start <= 48) {
@@ -1523,16 +1580,20 @@ static int slsi_mib_initial_get(struct slsi_dev *sdev)
 
                                        for (j = 0; j < chan_count; j++) {
                                                band[index + j] = 1;
+#ifdef CONFIG_SCSC_WLAN_DEBUG
                                                buf_pos += snprintf(supported_channels_buffer + buf_pos,
                                                                    buf_len - buf_pos, "%d ", (chan_start + k));
                                                k = k + increment;
+#endif
                                        }
                                        sdev->enabled_channel_count += chan_count;
                                }
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+                               SLSI_DBG1(sdev, SLSI_CFG80211, "Value for Supported Channels mib: %s\n",
+                                         supported_channels_buffer);
+                               kfree(supported_channels_buffer);
+#endif
                        }
-                       SLSI_DBG1(sdev, SLSI_CFG80211, "Value for Supported Channels mib: %s\n",
-                                 supported_channels_buffer);
-                       kfree(supported_channels_buffer);
                }
 
                if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) /* HT enabled? */
@@ -1941,9 +2002,13 @@ struct slsi_peer *slsi_peer_add(struct slsi_dev *sdev, struct net_device *dev, u
 
        /* MUST only be called from the control path that has acquired the lock */
        WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+       if (ndev_vif->ifnum < SLSI_NAN_DATA_IFINDEX_START && WARN_ON(!ndev_vif->activated))
+               return NULL;
+#else
        if (WARN_ON(!ndev_vif->activated))
                return NULL;
-
+#endif
        if (!peer_address) {
                SLSI_NET_WARN(dev, "Peer without address\n");
                return NULL;
@@ -3295,7 +3360,7 @@ int  slsi_set_arp_packet_filter(struct slsi_dev *sdev, struct net_device *dev)
        struct slsi_mlme_pattern_desc pattern_desc[SLSI_MAX_PATTERN_DESC];
        int num_pattern_desc = 0;
        u8 pkt_filters_len = 0, num_filters = 0;
-       struct slsi_mlme_pkt_filter_elem pkt_filter_elem[3];
+       struct slsi_mlme_pkt_filter_elem pkt_filter_elem[2];
        int ret;
        struct netdev_vif *ndev_vif = netdev_priv(dev);
        struct slsi_peer *peer = slsi_get_peer_from_qs(sdev, dev, SLSI_STA_PEER_QUEUESET);
@@ -3333,14 +3398,12 @@ int  slsi_set_arp_packet_filter(struct slsi_dev *sdev, struct net_device *dev)
 
        slsi_create_packet_filter_element(SLSI_ALL_ARP_FILTER_ID,
                                          FAPI_PACKETFILTERMODE_OPT_OUT | FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP,
-                                         num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len);
+                                         num_pattern_desc, pattern_desc,
+                                         &pkt_filter_elem[num_filters],
+                                         &pkt_filters_len);
        num_filters++;
 
-       ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem);
-       if (ret)
-               return ret;
-
-       /*Opt-in arp pakcet for device IP address*/
+       /*Opt-in arp packet for device IP address*/
        num_pattern_desc = 0;
        SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], ETH_P_ARP);
        num_pattern_desc++;
@@ -3353,7 +3416,9 @@ int  slsi_set_arp_packet_filter(struct slsi_dev *sdev, struct net_device *dev)
 
        slsi_create_packet_filter_element(SLSI_LOCAL_ARP_FILTER_ID,
                                          FAPI_PACKETFILTERMODE_OPT_IN | FAPI_PACKETFILTERMODE_OPT_IN_SLEEP,
-                                         num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len);
+                                         num_pattern_desc, pattern_desc,
+                                         &pkt_filter_elem[num_filters],
+                                         &pkt_filters_len);
        num_filters++;
 
        ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem);
@@ -3363,7 +3428,6 @@ int  slsi_set_arp_packet_filter(struct slsi_dev *sdev, struct net_device *dev)
 #ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6
        pkt_filters_len = 0;
        num_filters = 0;
-
        /*Opt in the multicast NS packets for Local IP address in active mode*/
        num_pattern_desc = 0;
        pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/
@@ -3512,105 +3576,72 @@ static int  slsi_set_opt_in_tcp6_packet_filter(struct slsi_dev *sdev, struct net
 }
 #endif
 
-#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
-int slsi_set_abnormal_multicast_pkt_filter(struct net_device *dev, u8 enabled)
-{
-       struct netdev_vif *netdev_vif = netdev_priv(dev);
-       struct slsi_dev   *sdev = netdev_vif->sdev;
-       int ret = 0;
-       int is_suspend = 0;
-
-       SLSI_MUTEX_LOCK(sdev->device_config_mutex);
-       is_suspend = sdev->device_config.user_suspend_mode;
-       SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
-
-       if (is_suspend) {
-               SLSI_ERR(sdev, "Host is in early suspend state.\n");
-               return -EPERM; /* set_enhanced_pkt_filter should not be called after suspend */
-       }
-
-       sdev->abnormal_multicast_pkt_filter_enabled = enabled;
-       SLSI_INFO(sdev, "Abnormal multicast packet filter is %s", (enabled ? "enabled" : "disabled"));
-       return ret;
-}
-
-static int slsi_set_opt_out_abnormal_multicast_packet_filter(struct slsi_dev *sdev, struct net_device *dev)
-{
-       struct slsi_mlme_pattern_desc pattern_desc[3];
-       u8 pkt_filters_len = 0;
-       int ret = 0;
-       struct slsi_mlme_pkt_filter_elem pkt_filter_elem;
-
-       /* IPv4 packet */
-       pattern_desc[0].offset = 0; /* destination mac address*/
-       pattern_desc[0].mask_length = ETH_ALEN;
-       memset(pattern_desc[0].mask, 0xff, ETH_ALEN);
-       memcpy(pattern_desc[0].pattern, sdev->hw_addr, ETH_ALEN);
-
-       pattern_desc[1].offset = ETH_ALEN + ETH_ALEN; /* ethhdr->h_proto == IPv4 */
-       pattern_desc[1].mask_length = 2;
-       pattern_desc[1].mask[0] = 0xff; /* Big endian 0xffff */
-       pattern_desc[1].mask[1] = 0xff;
-       pattern_desc[1].pattern[0] = 0x08; /* Big endian 0x0800 */
-       pattern_desc[1].pattern[1] = 0x00;
-
-       pattern_desc[2].offset = sizeof(struct ethhdr) + offsetof(struct iphdr, daddr); /* iphdr->daddr starts with 1110 */
-       pattern_desc[2].mask_length = 1;
-       pattern_desc[2].mask[0] = 0xf0;
-       pattern_desc[2].pattern[0] = 0xe0; /* 224 */
-
-       slsi_create_packet_filter_element(SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID,
-                                         FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP,
-                                         3, pattern_desc,
-                                         &pkt_filter_elem, &pkt_filters_len);
-
-       ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, 1, &pkt_filter_elem);
-
-       return ret;
-}
-#endif
-
 static int  slsi_set_multicast_packet_filters(struct slsi_dev *sdev, struct net_device *dev)
 {
-       struct slsi_mlme_pattern_desc pattern_desc;
+       struct slsi_mlme_pattern_desc pattern_desc[3];
        u8 pkt_filters_len = 0, i, num_filters = 0;
+       u8 num_pattern_desc = 0;
        int ret = 0;
        struct slsi_mlme_pkt_filter_elem *pkt_filter_elem = NULL;
        struct netdev_vif *ndev_vif = netdev_priv(dev);
        u8 mc_filter_id, mc_filter_count;
 
        /* Multicast packets for registered multicast addresses to be opted in on screen off*/
-       SLSI_NET_DBG2(dev, SLSI_MLME, "Set mc filters ,count =%d\n", ndev_vif->sta.regd_mc_addr_count);
+       SLSI_NET_DBG2(dev, SLSI_MLME, "Set mc filters ,regd mc addr count =%d\n", ndev_vif->sta.regd_mc_addr_count);
 
        mc_filter_count = ndev_vif->sta.regd_mc_addr_count;
-       if (!mc_filter_count)
-               return 0;
-
-       pkt_filter_elem = kmalloc((mc_filter_count * sizeof(struct slsi_mlme_pkt_filter_elem)), GFP_KERNEL);
+       pkt_filter_elem = kmalloc(((mc_filter_count + 1) * sizeof(struct slsi_mlme_pkt_filter_elem)), GFP_KERNEL);
        if (!pkt_filter_elem) {
                SLSI_NET_ERR(dev, "ERROR Memory allocation failure\n");
                return -ENOMEM;
        }
 
-       pattern_desc.offset = 0;
-       pattern_desc.mask_length = ETH_ALEN;
-       SLSI_ETHER_COPY(pattern_desc.mask, addr_mask);
+       /* Abnormal multicast filter */
+       pattern_desc[num_pattern_desc].offset = 0; /* destination mac address*/
+       pattern_desc[num_pattern_desc].mask_length = ETH_ALEN;
+       memset(pattern_desc[num_pattern_desc].mask, 0xff, ETH_ALEN);
+       memcpy(pattern_desc[num_pattern_desc].pattern, dev->dev_addr, ETH_ALEN);
+       num_pattern_desc++;
+
+       pattern_desc[num_pattern_desc].offset = ETH_ALEN + ETH_ALEN; /* ethhdr->h_proto == IPv4 */
+       pattern_desc[num_pattern_desc].mask_length = 2;
+       pattern_desc[num_pattern_desc].mask[0] = 0xff; /* Big endian 0xffff */
+       pattern_desc[num_pattern_desc].mask[1] = 0xff;
+       pattern_desc[num_pattern_desc].pattern[0] = 0x08; /* Big endian 0x0800 */
+       pattern_desc[num_pattern_desc].pattern[1] = 0x00;
+       num_pattern_desc++;
+
+       pattern_desc[num_pattern_desc].offset = sizeof(struct ethhdr) + offsetof(struct iphdr, daddr); /* iphdr->daddr starts with 1110 */
+       pattern_desc[num_pattern_desc].mask_length = 1;
+       pattern_desc[num_pattern_desc].mask[0] = 0xf0;
+       pattern_desc[num_pattern_desc].pattern[0] = 0xe0; /* 224 */
+       num_pattern_desc++;
+       slsi_create_packet_filter_element(SLSI_ABNORMAL_MULTICAST_ID,
+                                         FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP,
+                                         num_pattern_desc, pattern_desc,
+                                         &pkt_filter_elem[num_filters], &pkt_filters_len);
+       num_filters++;
+
+       /*Regd multicast addresses filter*/
+       pattern_desc[0].offset = 0;
+       pattern_desc[0].mask_length = ETH_ALEN;
+       SLSI_ETHER_COPY(pattern_desc[0].mask, addr_mask);
 
        for (i = 0; i < mc_filter_count; i++) {
-               SLSI_ETHER_COPY(pattern_desc.pattern, ndev_vif->sta.regd_mc_addr[i]);
+               SLSI_ETHER_COPY(pattern_desc[0].pattern, ndev_vif->sta.regd_mc_addr[i]);
                mc_filter_id = SLSI_REGD_MC_FILTER_ID + i;
 #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
                if (sdev->enhanced_pkt_filter_enabled)
                        slsi_create_packet_filter_element(mc_filter_id,
                                                          FAPI_PACKETFILTERMODE_OPT_IN,
-                                                         1, &pattern_desc,
+                                                         1, &pattern_desc[0],
                                                          &pkt_filter_elem[num_filters], &pkt_filters_len);
                else
 #endif
                        slsi_create_packet_filter_element(mc_filter_id,
                                                          FAPI_PACKETFILTERMODE_OPT_IN |
                                                          FAPI_PACKETFILTERMODE_OPT_IN_SLEEP,
-                                                         1, &pattern_desc,
+                                                         1, &pattern_desc[0],
                                                          &pkt_filter_elem[num_filters], &pkt_filters_len);
                num_filters++;
        }
@@ -3642,8 +3673,8 @@ int  slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev)
 
        SLSI_NET_DBG2(dev, SLSI_MLME, "Clear filters on Screen on");
 
-       /*calculate number of filters*/
-       num_filters = ndev_vif->sta.regd_mc_addr_count + SLSI_SCREEN_OFF_FILTERS_COUNT;
+       /* calculate number of filters (regd_mc_addr_count + abnormal_multicast filter + SLSI_SCREEN_OFF_FILTERS_COUNT) */
+       num_filters = ndev_vif->sta.regd_mc_addr_count + 1 + SLSI_SCREEN_OFF_FILTERS_COUNT;
        if ((slsi_is_proxy_arp_supported_on_ap(peer->assoc_resp_ie)) == false) {
                num_filters++;
                num_filters++;
@@ -3658,10 +3689,6 @@ int  slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev)
                num_filters++; /*TCP IPv4 OPT IN*/
                num_filters++; /*TCP IPv6 OPT IN*/
        }
-#endif
-#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
-       if (sdev->abnormal_multicast_pkt_filter_enabled)
-               num_filters++;/* clear abnormal multicast packet */
 #endif
        pkt_filter_elem = kmalloc((num_filters * sizeof(struct slsi_mlme_pkt_filter_elem)), GFP_KERNEL);
        if (!pkt_filter_elem) {
@@ -3702,13 +3729,9 @@ int  slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev)
                num_filters++;
        }
 #endif
-#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
-       if (sdev->abnormal_multicast_pkt_filter_enabled) {
-               slsi_create_packet_filter_element(SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID, 0, 0, NULL,
-                                                 &pkt_filter_elem[num_filters], &pkt_filters_len);
-               num_filters++;
-       }
-#endif
+       slsi_create_packet_filter_element(SLSI_ABNORMAL_MULTICAST_ID, 0, 0, NULL,
+                                         &pkt_filter_elem[num_filters], &pkt_filters_len);
+       num_filters++;
        ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem);
        kfree(pkt_filter_elem);
        return ret;
@@ -3743,14 +3766,6 @@ int  slsi_update_packet_filters(struct slsi_dev *sdev, struct net_device *dev)
                if (ret)
                        return ret;
        }
-#endif
-       /* install abnormal multicast packet filter */
-#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
-       if (sdev->abnormal_multicast_pkt_filter_enabled) {
-               ret = slsi_set_opt_out_abnormal_multicast_packet_filter(sdev, dev);
-               if (ret)
-                       return ret;
-       }
 #endif
        return slsi_set_common_packet_filters(sdev, dev);
 }
@@ -3811,57 +3826,60 @@ void slsi_set_packet_filters(struct slsi_dev *sdev, struct net_device *dev)
        if (ie) {
                SLSI_NET_DBG1(dev, SLSI_CFG80211, "Connected to HS2 AP ");
 
-       if (slsi_is_proxy_arp_supported_on_ap(peer->assoc_resp_ie)) {
-               SLSI_NET_DBG1(dev, SLSI_CFG80211, "Proxy ARP service supported on HS2 AP ");
+               if (slsi_is_proxy_arp_supported_on_ap(peer->assoc_resp_ie)) {
+                       SLSI_NET_DBG1(dev, SLSI_CFG80211, "Proxy ARP service supported on HS2 AP ");
 
-               /* Opt out Gratuitous ARP packets (ARP Announcement) in active and suspended mode.
-                * For suspended mode, gratituous ARP is dropped by "opt out all broadcast" that will be
-                * set  in slsi_set_common_packet_filters on screen off
-                */
-               num_pattern_desc = 0;
-               pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/
-               pattern_desc[num_pattern_desc].mask_length = ETH_ALEN;
-               SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask);
-               SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, addr_mask);
-               num_pattern_desc++;
+                       /* Opt out Gratuitous ARP packets (ARP Announcement) in active and suspended mode.
+                        * For suspended mode, gratituous ARP is dropped by "opt out all broadcast" that will be
+                        * set  in slsi_set_common_packet_filters on screen off
+                        */
+                       num_pattern_desc = 0;
+                       pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/
+                       pattern_desc[num_pattern_desc].mask_length = ETH_ALEN;
+                       SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask);
+                       SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, addr_mask);
+                       num_pattern_desc++;
 
-               SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], ETH_P_ARP);
-               num_pattern_desc++;
+                       SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], ETH_P_ARP);
+                       num_pattern_desc++;
 
-               slsi_create_packet_filter_element(SLSI_PROXY_ARP_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT,
-                                                 num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len);
-               num_filters++;
+                       slsi_create_packet_filter_element(SLSI_PROXY_ARP_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT,
+                                                         num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters],
+                                                         &pkt_filters_len);
+                       num_filters++;
 
 #ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6
-               /* Opt out unsolicited Neighbor Advertisement packets .For suspended mode, NA is dropped by
-                * "opt out all IPv6 multicast" already set in slsi_create_common_packet_filters
-                */
-               num_pattern_desc = 0;
-               
-               pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/
-               pattern_desc[num_pattern_desc].mask_length = ETH_ALEN;
-               SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask);
-               SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, solicited_node_addr_mask);
-               num_pattern_desc++;
-
-               SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], 0x86DD);
-               num_pattern_desc++;
-
-               pattern_desc[num_pattern_desc].offset = 0x14; /*filtering on next header*/
-               pattern_desc[num_pattern_desc].mask_length = 1;
-               pattern_desc[num_pattern_desc].mask[0] = 0xff;
-               pattern_desc[num_pattern_desc].pattern[0] = 0x3a;
-               num_pattern_desc++;
-
-               pattern_desc[num_pattern_desc].offset = 0x36; /*filtering on ICMP6 packet type*/
-               pattern_desc[num_pattern_desc].mask_length = 1;
-               pattern_desc[num_pattern_desc].mask[0] = 0xff;
-               pattern_desc[num_pattern_desc].pattern[0] = 0x88; /* Neighbor Advertisement type in ICMPv6 */
-               num_pattern_desc++;
+                       /* Opt out unsolicited Neighbor Advertisement packets .For suspended mode, NA is dropped by
+                        * "opt out all IPv6 multicast" already set in slsi_create_common_packet_filters
+                        */
 
-               slsi_create_packet_filter_element(SLSI_PROXY_ARP_NA_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT,
-                                                 num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len);
-               num_filters++;
+                       num_pattern_desc = 0;
+
+                       pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/
+                       pattern_desc[num_pattern_desc].mask_length = ETH_ALEN;
+                       SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask);
+                       SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, solicited_node_addr_mask);
+                       num_pattern_desc++;
+
+                       SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], 0x86DD);
+                       num_pattern_desc++;
+
+                       pattern_desc[num_pattern_desc].offset = 0x14; /*filtering on next header*/
+                       pattern_desc[num_pattern_desc].mask_length = 1;
+                       pattern_desc[num_pattern_desc].mask[0] = 0xff;
+                       pattern_desc[num_pattern_desc].pattern[0] = 0x3a;
+                       num_pattern_desc++;
+
+                       pattern_desc[num_pattern_desc].offset = 0x36; /*filtering on ICMP6 packet type*/
+                       pattern_desc[num_pattern_desc].mask_length = 1;
+                       pattern_desc[num_pattern_desc].mask[0] = 0xff;
+                       pattern_desc[num_pattern_desc].pattern[0] = 0x88; /* Neighbor Advertisement type in ICMPv6 */
+                       num_pattern_desc++;
+
+                       slsi_create_packet_filter_element(SLSI_PROXY_ARP_NA_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT,
+                                                         num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters],
+                                                         &pkt_filters_len);
+                       num_filters++;
 #endif
                }
        }
@@ -5163,6 +5181,55 @@ void slsi_reset_channel_flags(struct slsi_dev *sdev)
 }
 
 int slsi_read_regulatory_rules(struct slsi_dev *sdev, struct slsi_802_11d_reg_domain *domain_info, const char *alpha2)
+{
+       int i = 0;
+       int country_index = 0;
+       struct ieee80211_reg_rule *reg_rule = NULL;
+
+       if ((sdev->regdb.regdb_state == SLSI_REG_DB_NOT_SET) || (sdev->regdb.regdb_state == SLSI_REG_DB_ERROR)) {
+               SLSI_ERR(sdev, "Regulatory is not set!\n");
+               return slsi_read_regulatory_rules_fw(sdev, domain_info, alpha2);
+       }
+
+       for (i = 0; i < sdev->regdb.num_countries; i++) {
+               if ((sdev->regdb.country[i].alpha2[0] == alpha2[0]) && (sdev->regdb.country[i].alpha2[1] == alpha2[1])) {
+                       country_index = i;
+                       break;
+               }
+       }
+
+       domain_info->regdomain->alpha2[0] = sdev->regdb.country[country_index].alpha2[0];
+       domain_info->regdomain->alpha2[1] = sdev->regdb.country[country_index].alpha2[1];
+       domain_info->regdomain->dfs_region = sdev->regdb.country[country_index].dfs_region;
+
+       for (i = 0; i < sdev->regdb.country[country_index].collection->reg_rule_num; i++) {
+               reg_rule = &domain_info->regdomain->reg_rules[i];
+
+               /* start freq 2 bytes */
+               reg_rule->freq_range.start_freq_khz = (sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->start_freq * 1000);
+
+               /* end freq 2 bytes */
+               reg_rule->freq_range.end_freq_khz = (sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->end_freq * 1000);
+
+               /* Max Bandwidth 1 byte */
+               reg_rule->freq_range.max_bandwidth_khz = (sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->max_bandwidth * 1000);
+
+               /* max_antenna_gain is obsolete now. */
+               reg_rule->power_rule.max_antenna_gain = 0;
+
+               /* Max Power 1 byte */
+               reg_rule->power_rule.max_eirp = (sdev->regdb.country[country_index].collection->reg_rule[i]->max_eirp * 100);
+
+               /* Flags 1 byte */
+               reg_rule->flags = slsi_remap_reg_rule_flags(sdev->regdb.country[country_index].collection->reg_rule[i]->flags);
+       }
+
+       domain_info->regdomain->n_reg_rules = sdev->regdb.country[country_index].collection->reg_rule_num;
+
+       return 0;
+}
+
+int slsi_read_regulatory_rules_fw(struct slsi_dev *sdev, struct slsi_802_11d_reg_domain *domain_info, const char *alpha2)
 {
        struct slsi_mib_data mibreq = { 0, NULL };
        struct slsi_mib_data mibrsp = { 0, NULL };
@@ -5245,6 +5312,7 @@ static int slsi_country_to_index(struct slsi_802_11d_reg_domain *domain_info, co
        return -1;
 }
 
+
 /* Set the rssi boost value of a particular band as set in the SETJOINPREFER command*/
 int slsi_set_mib_rssi_boost(struct slsi_dev *sdev, struct net_device *dev, u16 psid, int index, int boost)
 {
@@ -5702,7 +5770,6 @@ int slsi_set_mac_randomisation_mask(struct slsi_dev *sdev, u8 *mac_address_mask)
 /* Set the new country code and read the regulatory parameters of updated country. */
 int slsi_set_country_update_regd(struct slsi_dev *sdev, const char *alpha2_code, int size)
 {
-       struct slsi_mib_data mib_data = { 0, NULL };
        char alpha2[4];
        int  error = 0;
 
@@ -5721,21 +5788,7 @@ int slsi_set_country_update_regd(struct slsi_dev *sdev, const char *alpha2_code,
        }
 
        SLSI_MUTEX_LOCK(sdev->device_config_mutex);
-
-       error = slsi_mib_encode_octet(&mib_data, SLSI_PSID_UNIFI_DEFAULT_COUNTRY, 3, alpha2, 0);
-       if (error != SLSI_MIB_STATUS_SUCCESS) {
-               error = -ENOMEM;
-               goto exit;
-       }
-
-       if (WARN_ON(mib_data.dataLength == 0)) {
-               error = -EINVAL;
-               goto exit;
-       }
-
-       error = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength);
-
-       kfree(mib_data.data);
+       error = slsi_mlme_set_country(sdev, alpha2);
 
        if (error) {
                SLSI_ERR(sdev, "Err setting country error = %d\n", error);
@@ -5750,7 +5803,6 @@ int slsi_set_country_update_regd(struct slsi_dev *sdev, const char *alpha2_code,
                slsi_update_supported_channels_regd_flags(sdev);
        }
 
-exit:
        SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
        return error;
 }
@@ -5919,13 +5971,6 @@ int slsi_read_unifi_countrylist(struct slsi_dev *sdev, u16 psid)
        return r;
 }
 
-void  slsi_regd_deinit(struct slsi_dev *sdev)
-{
-       SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "slsi_regd_deinit\n");
-
-       kfree(sdev->device_config.domain_info.countrylist);
-}
-
 void slsi_clear_offchannel_data(struct slsi_dev *sdev, bool acquire_lock)
 {
        struct net_device *dev = NULL;
@@ -6108,13 +6153,13 @@ void slsi_update_supported_channels_regd_flags(struct slsi_dev *sdev)
 
 int slsi_find_chan_idx(u16 chan, u8 hw_mode)
 {
-       int idx = 0, i = 0;
+       int idx = -1, i = 0;
        u16 slsi_5ghz_channels_list[25] = {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132,
                                136, 140, 144, 149, 153, 157, 161, 165};
 
        if (hw_mode == SLSI_ACS_MODE_IEEE80211B || hw_mode == SLSI_ACS_MODE_IEEE80211G) {
-               idx = chan - 1;
-               return idx;
+               if (chan <= MAX_24G_CHANNELS)
+                       idx = chan - 1;
        } else if (hw_mode == SLSI_ACS_MODE_IEEE80211A) {
                for (i = 0; i < MAX_5G_CHANNELS; i++) {
                        if (chan == slsi_5ghz_channels_list[i]) {
@@ -6122,21 +6167,19 @@ int slsi_find_chan_idx(u16 chan, u8 hw_mode)
                                break;
                        }
                }
-               return idx;
        } else {
-               if (chan <=MAX_24G_CHANNELS) {
-                       idx = chan -1;
-                       return idx;
+               if (chan <= MAX_24G_CHANNELS) {
+                       idx = chan - 1;
                } else {
                        for (i = 0; i < MAX_5G_CHANNELS; i++) {
                                if (chan == slsi_5ghz_channels_list[i]) {
-                                       idx = i;
+                                       idx = i + MAX_24G_CHANNELS;
                                        break;
                                }
                        }
-                       return (idx + MAX_24G_CHANNELS);
                }
        }
+       return idx;
 }
 
 #ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS
@@ -6214,45 +6257,13 @@ int slsi_set_latency_mode(struct net_device *dev, int latency_mode, int cmd_len)
 }
 
 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
-void slsi_ap_cleanup(struct slsi_dev *sdev, struct net_device *dev)
-{
-       struct netdev_vif *ndev_vif = netdev_priv(dev);
-       struct slsi_peer *peer;
-       int              j = 0;
-
-       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
-       while (j < SLSI_PEER_INDEX_MAX) {
-               peer = ndev_vif->peer_sta_record[j];
-
-               if (!peer)
-                       continue;
-               if (peer->connected_state == SLSI_STA_CONN_STATE_CONNECTING)
-                       continue;
-               slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED);
-               /* Even if we fail to disconnect cleanly, tidy up. */
-               if ((peer->connected_state == SLSI_STA_CONN_STATE_CONNECTED) ||
-                   (peer->connected_state == SLSI_STA_CONN_STATE_DOING_KEY_CONFIG))
-                       cfg80211_del_sta(dev, peer->address, GFP_KERNEL);
-
-               slsi_peer_remove(sdev, dev, peer);
-               ++j;
-       }
-       SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
-}
-
 void slsi_wlan_recovery_init(struct slsi_dev *sdev)
 {
-       int ret = 0;
        int i;
        struct netdev_vif *ndev_vif;
        struct net_device *dev;
 
-       ret = slsi_set_country_update_regd(sdev, sdev->device_config.domain_info.regdomain->alpha2,
-                                          SLSI_COUNTRY_CODE_LEN);
-       if (ret < 0) {
-               SLSI_ERR(sdev, "Set country failed ret:%d\n", ret);
-               return;
-       }
+       slsi_mlme_set_country_for_recovery(sdev);
        for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) {
                if (sdev->netdev[i]) {
                        dev = slsi_get_netdev(sdev, i);
@@ -6272,124 +6283,161 @@ void slsi_subsystem_reset(struct work_struct *work)
        struct slsi_dev *sdev = container_of(work, struct slsi_dev, recovery_work);
        int err = 0, i;
        int level;
+       struct netdev_vif *ndev_vif;
 #ifndef CONFIG_SCSC_DOWNLOAD_FILE
        const struct firmware *fw[SLSI_WLAN_MAX_MIB_FILE] = { NULL, NULL };
 #endif
+
        level = atomic_read(&sdev->cm_if.reset_level);
        SLSI_INFO_NODEV("Inside subsytem_reset\n");
        if (level < SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC) {
                err = slsi_sm_recovery_service_stop(sdev);
-               sdev->cm_if.recovery_state = 1;
+               sdev->cm_if.recovery_state = SLSI_RECOVERY_SERVICE_STOPPED;
                sdev->device_state = SLSI_DEVICE_STATE_STOPPED;
                slsi_hip_stop(sdev);
                level = atomic_read(&sdev->cm_if.reset_level);
                if (err != 0 || level == SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC)
                        return;
                err = slsi_sm_recovery_service_close(sdev);
-               sdev->mlme_blocked = false;
-               sdev->cm_if.recovery_state = 2;
+               sdev->cm_if.recovery_state = SLSI_RECOVERY_SERVICE_CLOSED;
                level = atomic_read(&sdev->cm_if.reset_level);
-               if (err != 0 || level == SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC || sdev->netdev_up_count == 0)
+               if (err != 0 || level == SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC || sdev->netdev_up_count == 0) {
+                       if (sdev->netdev_up_count == 0)
+                               sdev->mlme_blocked = false;
                        return;
+               }
+               SLSI_MUTEX_LOCK(sdev->start_stop_mutex);
                sdev->device_state = SLSI_DEVICE_STATE_STARTING;
                err = slsi_sm_recovery_service_open(sdev);
-               sdev->cm_if.recovery_state = 3;
+               sdev->cm_if.recovery_state = SLSI_RECOVERY_SERVICE_OPENED;
                level = atomic_read(&sdev->cm_if.reset_level);
-               if (err != 0 || level == SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC || sdev->netdev_up_count == 0)
+               if (err != 0 || level == SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC) {
+                       SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex);
                        return;
+               }
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
-       reinit_completion(&sdev->sig_wait.completion);
+               reinit_completion(&sdev->sig_wait.completion);
 #else
-       INIT_COMPLETION(sdev->sig_wait.completion);
+               INIT_COMPLETION(sdev->sig_wait.completion);
 #endif
 
 #ifndef CONFIG_SCSC_DOWNLOAD_FILE
-       /* The "_t" HCF is used in RF Test mode and wlanlite/production test mode */
-       if (slsi_is_rf_test_mode_enabled() || slsi_is_test_mode_enabled()) {
-               sdev->mib[0].mib_file_name = mib_file_t;
-               sdev->mib[1].mib_file_name = mib_file2_t;
-       } else {
-               sdev->mib[0].mib_file_name = slsi_mib_file;
-               sdev->mib[1].mib_file_name = slsi_mib_file2;
-       }
-       sdev->collect_mib.num_files = 0;
-       /* Place MIB files in shared memory */
-       for (i  = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++) {
-               err = slsi_mib_open_file(sdev, &sdev->mib[i], &fw[i]);
-
-               /* Only the first file is mandatory */
-               if (i == 0 && err) {
-                       SLSI_ERR(sdev, "mib: Mandatory wlan hcf missing. WLAN will not start (err=%d)\n", err);
-                       slsi_sm_recovery_service_close(sdev);
-                       sdev->device_state = SLSI_DEVICE_STATE_STOPPED;
-                       return;
+               /* The "_t" HCF is used in RF Test mode and wlanlite/production test mode */
+               if (slsi_is_rf_test_mode_enabled() || slsi_is_test_mode_enabled()) {
+                       sdev->mib[0].mib_file_name = mib_file_t;
+                       sdev->mib[1].mib_file_name = mib_file2_t;
+               } else {
+                       sdev->mib[0].mib_file_name = slsi_mib_file;
+                       sdev->mib[1].mib_file_name = slsi_mib_file2;
                }
-       }
-       err = slsi_sm_recovery_service_start(sdev);
-       if (err) {
-               SLSI_ERR(sdev, "slsi_sm_wlan_service_start failed: err=%d\n", err);
+               sdev->collect_mib.num_files = 0;
+               /* Place MIB files in shared memory */
+               for (i = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++) {
+                       err = slsi_mib_open_file(sdev, &sdev->mib[i], &fw[i]);
+
+                       /* Only the first file is mandatory */
+                       if (i == 0 && err) {
+                               SLSI_ERR(sdev, "mib: Mandatory wlan hcf missing. WLAN will not start (err=%d)\n", err);
+                               goto err_done;
+                       }
+               }
+               err = slsi_sm_recovery_service_start(sdev);
+               if (err) {
+                       SLSI_ERR(sdev, "slsi_sm_wlan_service_start failed: err=%d\n", err);
+                       for (i = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++)
+                               slsi_mib_close_file(sdev, fw[i]);
+                       goto err_done;
+               }
+
                for (i = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++)
                        slsi_mib_close_file(sdev, fw[i]);
-               slsi_sm_recovery_service_close(sdev);
-               sdev->device_state = SLSI_DEVICE_STATE_STOPPED;
-               return;
-       }
-       for (i = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++)
-               slsi_mib_close_file(sdev, fw[i]);
 #else
-       /* Download main MIB file via mlme_set */
-       err = slsi_sm_recovery_service_start(sdev);
-       if (err) {
-               SLSI_ERR(sdev, "slsi_sm_wlan_service_start failed: err=%d\n", err);
-               slsi_sm_recovery_service_close(sdev);
-               sdev->device_state = SLSI_DEVICE_STATE_STOPPED;
-               return;
-       }
-       SLSI_EC_GOTO(slsi_mib_download_file(sdev, &sdev->mib), err, err_hip_started);
+               /* Download main MIB file via mlme_set */
+               err = slsi_sm_recovery_service_start(sdev);
+               if (err) {
+                       SLSI_ERR(sdev, "slsi_sm_wlan_service_start failed: err=%d\n", err);
+                       goto err_done;
+               }
+               SLSI_EC_GOTO(slsi_mib_download_file(sdev, &sdev->mib), err, err_hip_started);
 #endif
                level = atomic_read(&sdev->cm_if.reset_level);
                if (level == SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC) {
                        SLSI_INFO_NODEV("slsi_sm_recovery_service_start failed subsytem error level changed:%d\n", level);
+                       SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex);
                        return;
                }
-               sdev->cm_if.recovery_state = 4;
                sdev->device_state = SLSI_DEVICE_STATE_STARTED;
+               sdev->mlme_blocked = false;
+               sdev->cm_if.recovery_state = SLSI_RECOVERY_SERVICE_STARTED;
+               for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) {
+                       if (sdev->netdev[i]) {
+                               ndev_vif = netdev_priv(sdev->netdev[i]);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
+                               reinit_completion(&ndev_vif->sig_wait.completion);
+#else
+                               INIT_COMPLETION(ndev_vif->sig_wait.completion);
+#endif
+                       }
+               }
 
                /*wlan system recovery actions*/
+               SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex);
                slsi_wlan_recovery_init(sdev);
+               return;
+       } else {
+               return;
        }
 #ifdef CONFIG_SCSC_DOWNLOAD_FILE
 err_hip_started:
        slsi_sm_recovery_service_stop(sdev);
        slsi_hip_stop(sdev);
        slsi_sm_recovery_service_close(sdev);
+       SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex);
        return;
 #endif
+err_done:
+       slsi_sm_recovery_service_close(sdev);
+       sdev->device_state = SLSI_DEVICE_STATE_STOPPED;
+       SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex);
+       return;
 }
 
-void slsi_failure_reset(struct slsi_dev *sdev)
+void slsi_failure_reset(struct work_struct *work)
 {
+       struct slsi_dev *sdev = container_of(work, struct slsi_dev, recovery_work_on_stop);
        int r = 0;
 
-       if (sdev->cm_if.recovery_state == 0) {
+       if (sdev->cm_if.recovery_state == SLSI_RECOVERY_SERVICE_STARTED) {
                r = slsi_sm_recovery_service_stop(sdev);
                sdev->device_state = SLSI_DEVICE_STATE_STOPPED;
                slsi_hip_stop(sdev);
-               sdev->cm_if.recovery_state = 1;
+               sdev->cm_if.recovery_state = SLSI_RECOVERY_SERVICE_STOPPED;
        }
-       if (sdev->cm_if.recovery_state == 1) {
+       if (sdev->cm_if.recovery_state == SLSI_RECOVERY_SERVICE_STOPPED) {
                r = slsi_sm_recovery_service_close(sdev);
+               sdev->cm_if.recovery_state = SLSI_RECOVERY_SERVICE_CLOSED;
+       }
+       if (sdev->netdev_up_count == 0) {
                sdev->mlme_blocked = false;
-               sdev->cm_if.recovery_state = 2;
+               if (work_pending(&sdev->recovery_work_on_start)) {
+                       SLSI_INFO(sdev, "Cancel work for chip recovery!!\n");
+                       cancel_work_sync(&sdev->recovery_work_on_start);
+               }
        }
 }
 
-void slsi_chip_recovery(struct slsi_dev *sdev)
+void slsi_chip_recovery(struct work_struct *work)
 {
-       int r = 0, err = 0;
+       struct slsi_dev *sdev = container_of(work, struct slsi_dev, recovery_work_on_start);
+       int r = 0, err = 0, i;
+       struct netdev_vif *ndev_vif;
+#ifndef CONFIG_SCSC_DOWNLOAD_FILE
+       const struct firmware *fw[SLSI_WLAN_MAX_MIB_FILE] = { NULL, NULL };
+#endif
 
        slsi_wakelock(&sdev->wlan_wl);
-       if (sdev->cm_if.recovery_state == 2 && sdev->netdev_up_count > 0) {
+       SLSI_MUTEX_LOCK(sdev->start_stop_mutex);
+       if (sdev->cm_if.recovery_state == SLSI_RECOVERY_SERVICE_CLOSED && sdev->netdev_up_count > 0) {
                if (sdev->recovery_status) {
                        r = wait_for_completion_timeout(&sdev->recovery_completed,
                                                        msecs_to_jiffies(sdev->recovery_timeout));
@@ -6408,17 +6456,90 @@ void slsi_chip_recovery(struct slsi_dev *sdev)
                INIT_COMPLETION(sdev->sig_wait.completion);
 #endif
                SLSI_EC_GOTO(slsi_sm_wlan_service_open(sdev), err, err_done); //separate function is not required.
-               sdev->cm_if.recovery_state = 3;
+               sdev->cm_if.recovery_state = SLSI_RECOVERY_SERVICE_OPENED;
+       } else if (sdev->netdev_up_count == 0) {
+               sdev->mlme_blocked = false;
+               goto err_done;
        }
-       if (sdev->cm_if.recovery_state == 3 && sdev->netdev_up_count > 0) {
-               r = slsi_sm_recovery_service_start(sdev);
-               sdev->cm_if.recovery_state = 4;
+       if (sdev->cm_if.recovery_state == SLSI_RECOVERY_SERVICE_OPENED && sdev->netdev_up_count > 0) {
+#ifndef CONFIG_SCSC_DOWNLOAD_FILE
+               /* The "_t" HCF is used in RF Test mode and wlanlite/production test mode */
+               if (slsi_is_rf_test_mode_enabled() || slsi_is_test_mode_enabled()) {
+                       sdev->mib[0].mib_file_name = mib_file_t;
+                       sdev->mib[1].mib_file_name = mib_file2_t;
+               } else {
+                       sdev->mib[0].mib_file_name = slsi_mib_file;
+                       sdev->mib[1].mib_file_name = slsi_mib_file2;
+               }
+               sdev->collect_mib.num_files = 0;
+               /* Place MIB files in shared memory */
+               for (i = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++) {
+                       err = slsi_mib_open_file(sdev, &sdev->mib[i], &fw[i]);
+
+                       /* Only the first file is mandatory */
+                       if (i == 0 && err) {
+                               SLSI_ERR(sdev, "mib: Mandatory wlan hcf missing. WLAN will not start (err=%d)\n", err);
+                               slsi_sm_recovery_service_close(sdev);
+                               goto err_done;
+                       }
+               }
+               err = slsi_sm_recovery_service_start(sdev);
+               if (err) {
+                       SLSI_ERR(sdev, "slsi_sm_wlan_service_start failed: err=%d\n", err);
+                       for (i = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++)
+                               slsi_mib_close_file(sdev, fw[i]);
+                       slsi_sm_recovery_service_close(sdev);
+                       goto err_done;
+               }
+
+               for (i = 0; i < SLSI_WLAN_MAX_MIB_FILE; i++)
+                       slsi_mib_close_file(sdev, fw[i]);
+#else
+               /* Download main MIB file via mlme_set */
+               err = slsi_sm_recovery_service_start(sdev);
+               if (err) {
+                       SLSI_ERR(sdev, "slsi_sm_wlan_service_start failed: err=%d\n", err);
+                       slsi_sm_recovery_service_close(sdev);
+                       goto err_done;
+               }
+               SLSI_EC_GOTO(slsi_mib_download_file(sdev, &sdev->mib), err, err_hip_started);
+#endif
                sdev->device_state = SLSI_DEVICE_STATE_STARTED;
+
+               /*wlan system recovery actions*/
+               sdev->mlme_blocked = false;
+               sdev->cm_if.recovery_state = SLSI_RECOVERY_SERVICE_STARTED;
+               for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++) {
+                       if (sdev->netdev[i]) {
+                               ndev_vif = netdev_priv(sdev->netdev[i]);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
+                               reinit_completion(&ndev_vif->sig_wait.completion);
+#else
+                               INIT_COMPLETION(ndev_vif->sig_wait.completion);
+#endif
+                       }
+               }
+               SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex);
                slsi_wlan_recovery_init(sdev);
+               slsi_wakeunlock(&sdev->wlan_wl);
+               return;
+       } else {
+               SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex);
+               slsi_wakeunlock(&sdev->wlan_wl);
+               return;
        }
-
+#ifdef CONFIG_SCSC_DOWNLOAD_FILE
+err_hip_started:
+       slsi_sm_recovery_service_stop(sdev);
+       slsi_hip_stop(sdev);
+       slsi_sm_recovery_service_close(sdev);
+       slsi_wakeunlock(&sdev->wlan_wl);
+       SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex);
+       return;
+#endif
 err_done:
        sdev->device_state = SLSI_DEVICE_STATE_STOPPED;
+       SLSI_MUTEX_UNLOCK(sdev->start_stop_mutex);
        slsi_wakeunlock(&sdev->wlan_wl);
 }
 #endif
index 0023c6c8dd2db18790136f95d691a02f87983dfb..ad30608867d4892e03e186ef732094d31b40a436 100755 (executable)
@@ -10,6 +10,7 @@
 #include <linux/mutex.h>
 
 #include "dev.h"
+#include "reg_info.h"
 #include "debug.h"
 
 /* For 3.4.11 kernel support */
        #define WLAN_CATEGORY_WNM 10
 #endif
 
+#ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
+#define SLSI_RECOVERY_SERVICE_STARTED   0
+#define SLSI_RECOVERY_SERVICE_STOPPED    1
+#define SLSI_RECOVERY_SERVICE_CLOSED   2
+#define SLSI_RECOVERY_SERVICE_OPENED    3
+#endif
+
 enum slsi_dhcp_tx {
        SLSI_TX_IS_NOT_DHCP,
        SLSI_TX_IS_DHCP_SERVER,
@@ -277,7 +285,27 @@ static inline struct slsi_peer *slsi_get_peer_from_mac(struct slsi_dev *sdev, st
                        if (ndev_vif->peer_sta_record[i] && ndev_vif->peer_sta_record[i]->valid &&
                            compare_ether_addr(ndev_vif->peer_sta_record[i]->address, mac) == 0)
                                return ndev_vif->peer_sta_record[i];
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+       } else if (ndev_vif->ifnum >= SLSI_NAN_DATA_IFINDEX_START) {
+               int i = 0;
+
+               for (i = 0; i < SLSI_PEER_INDEX_MAX; i++) {
+                       if (ndev_vif->peer_sta_record[i] && ndev_vif->peer_sta_record[i]->valid &&
+                           compare_ether_addr(ndev_vif->peer_sta_record[i]->address, mac) == 0)
+                               return ndev_vif->peer_sta_record[i];
+               }
+
+               if (is_multicast_ether_addr(mac)) {
+                       for (i = 0; i < SLSI_PEER_INDEX_MAX; i++)
+                       if (ndev_vif->peer_sta_record[i] && ndev_vif->peer_sta_record[i]->valid) {
+                               SLSI_NET_DBG1(dev, SLSI_TX, "multicast/broadcast packet on NAN netif (dest:%pM, change to peer: %pM)\n", mac, ndev_vif->peer_sta_record[i]->address);
+                               return ndev_vif->peer_sta_record[i];
+                       }
+               }
        }
+#else
+       }
+#endif
        return NULL;
 }
 
@@ -486,9 +514,6 @@ int slsi_is_tcp_sync_packet(struct net_device *dev, struct sk_buff *skb);
 #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
 int slsi_set_enhanced_pkt_filter(struct net_device *dev, u8 pkt_filter_enable);
 #endif
-#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
-int slsi_set_abnormal_multicast_pkt_filter(struct net_device *dev, u8 enabled);
-#endif
 void slsi_set_packet_filters(struct slsi_dev *sdev, struct net_device *dev);
 int  slsi_update_packet_filters(struct slsi_dev *sdev, struct net_device *dev);
 int  slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev);
@@ -496,6 +521,7 @@ int slsi_ap_prepare_add_info_ies(struct netdev_vif *ndev_vif, const u8 *ies, siz
 int slsi_set_mib_roam(struct slsi_dev *dev, struct net_device *ndev, u16 psid, int value);
 #ifdef CONFIG_SCSC_WLAN_SET_PREFERRED_ANTENNA
 int slsi_set_mib_preferred_antenna(struct slsi_dev *dev, u16 value);
+bool slsi_read_preferred_antenna_from_file(struct slsi_dev *sdev, char *ant_file);
 #endif
 void slsi_reset_throughput_stats(struct net_device *dev);
 int slsi_set_mib_rssi_boost(struct slsi_dev *sdev, struct net_device *dev, u16 psid, int index, int boost);
@@ -536,6 +562,7 @@ int slsi_read_unifi_countrylist(struct slsi_dev *sdev, u16 psid);
 int slsi_read_default_country(struct slsi_dev *sdev, u8 *alpha2, u16 index);
 int slsi_read_disconnect_ind_timeout(struct slsi_dev *sdev, u16 psid);
 int slsi_read_regulatory_rules(struct slsi_dev *sdev, struct slsi_802_11d_reg_domain *domain_info, const char *alpha2);
+int slsi_read_regulatory_rules_fw(struct slsi_dev *sdev, struct slsi_802_11d_reg_domain *domain_info, const char *alpha2);
 int slsi_send_acs_event(struct slsi_dev *sdev, struct slsi_acs_selected_channels acs_selected_channels);
 #ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION
 int slsi_set_mac_randomisation_mask(struct slsi_dev *sdev, u8 *mac_address_mask);
@@ -576,9 +603,8 @@ int slsi_set_latency_mode(struct net_device *dev, int latency_mode, int cmd_len)
 int slsi_start_ap(struct wiphy *wiphy, struct net_device *dev,
                  struct cfg80211_ap_settings *settings);
 void slsi_subsystem_reset(struct work_struct *work);
-void slsi_failure_reset(struct slsi_dev *sdev);
-void slsi_chip_recovery(struct slsi_dev *sdev);
-void slsi_ap_cleanup(struct slsi_dev *sdev, struct net_device *dev);
+void slsi_failure_reset(struct work_struct *work);
+void slsi_chip_recovery(struct work_struct *work);
 #endif
 
 #endif /*__SLSI_MGT_H__*/
index 0ed3c0bfa5772a51baf6061897e48ca6c6fb9320..337196effb8773bd5b95190162dafea6cc4efa18 100755 (executable)
@@ -2491,8 +2491,6 @@ void slsi_calc_max_data_rate(struct net_device *dev, u8 bandwidth, u8 antenna_mo
                        mcs_index = 9;
                ndev_vif->sta.max_rate_mbps = (unsigned long)(slsi_rates_table[bandwidth_index][1][mcs_index] * (antenna_mode + 1)) / 10;
        }
-       SLSI_NET_INFO(dev, "sta_mode : %u, freq : %u, bandwidth : %u, antenna_mode : %u, max_rate_mbps : %u\n",
-                       sta_mode, ndev_vif->sta.sta_bss->channel->center_freq, bandwidth, antenna_mode, ndev_vif->sta.max_rate_mbps);
 }
 
 void slsi_decode_fw_rate(u16 fw_rate, struct rate_info *rate, unsigned long *data_rate_mbps)
@@ -4447,5 +4445,116 @@ int slsi_test_sap_configure_monitor_mode(struct slsi_dev *sdev, struct net_devic
        slsi_kfree_skb(cfm);
        return r;
 }
+#endif
+
+int slsi_mlme_set_country(struct slsi_dev *sdev, char *alpha2)
+{
+       struct slsi_mib_data mib_data = { 0, NULL };
+       struct sk_buff    *req;
+       struct sk_buff    *cfm;
+       int country_index = 0;
+       u32 rules_len = 0;
+       u16 country_code = 0;
+       u8 append_byte = 0;
+       u8 dfs_region = 0;
+       int i = 0;
+       int error = 0;
+
+       if (sdev->regdb.regdb_state == SLSI_REG_DB_SET) {
+               for (i = 0; i < sdev->regdb.num_countries; i++) {
+                       if ((sdev->regdb.country[i].alpha2[0] == alpha2[0]) && (sdev->regdb.country[i].alpha2[1] == alpha2[1])) {
+                               country_index = i;
+                               break;
+                       }
+               }
+
+               /* 7 octets for each rule */
+               rules_len = 7 * sdev->regdb.country[country_index].collection->reg_rule_num;
+               dfs_region = sdev->regdb.country[country_index].dfs_region;
+       }
+
+       /* last parameter should be length of bulk data */
+       req = fapi_alloc(mlme_set_country_req, MLME_SET_COUNTRY_REQ, 0, rules_len);
+       if (!req)
+               return -ENOMEM;
+
+       country_code = (((u16)alpha2[0] << 8) | (u16)alpha2[1]);
+       fapi_set_u16(req, u.mlme_set_country_req.country_code, country_code);
+       fapi_set_u16(req, u.mlme_set_country_req.dfs_regulatory_domain, dfs_region);
+       if (rules_len) {
+               for (i = 0; i < sdev->regdb.country[country_index].collection->reg_rule_num; i++) {
+                       append_byte = (sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->start_freq * 2) & 0xFF;
+                       fapi_append_data(req, &append_byte, 1);
+                       append_byte = ((sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->start_freq * 2) >> 8) & 0xFF;
+                       fapi_append_data(req, &append_byte, 1);
+                       append_byte = (sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->end_freq * 2) & 0xFF;
+                       fapi_append_data(req, &append_byte, 1);
+                       append_byte = ((sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->end_freq * 2) >> 8) & 0xFF;
+                       fapi_append_data(req, &append_byte, 1);
+                       append_byte = sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->max_bandwidth & 0xFF;
+                       fapi_append_data(req, &append_byte, 1);
+                       append_byte = sdev->regdb.country[country_index].collection->reg_rule[i]->max_eirp & 0xFF;
+                       fapi_append_data(req, &append_byte, 1);
+                       append_byte = sdev->regdb.country[country_index].collection->reg_rule[i]->flags & 0xFF;
+                       fapi_append_data(req, &append_byte, 1);
+               }
+       }
+
+       SLSI_DBG2(sdev, SLSI_MLME, "mlme_set_country_req(country:%c%c, dfs_regulatory_domain:%x)\n", alpha2[0], alpha2[1], dfs_region);
+       cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_SET_COUNTRY_CFM);
+       if (!cfm)
+               return -EIO;
+
+       if (fapi_get_u16(cfm, u.mlme_set_country_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
+               SLSI_ERR(sdev, "mlme_set_country_cfm(result:0x%04x) ERROR\n",
+                        fapi_get_u16(cfm, u.mlme_set_country_cfm.result_code));
+               slsi_kfree_skb(cfm);
+               error = slsi_mib_encode_octet(&mib_data, SLSI_PSID_UNIFI_DEFAULT_COUNTRY, 3, alpha2, 0);
+               if (error != SLSI_MIB_STATUS_SUCCESS)
+                       return -ENOMEM;
 
+               if (WARN_ON(mib_data.dataLength == 0))
+                       return -EINVAL;
+
+               error = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength);
+               if (error)
+                       return -EINVAL;
+
+               kfree(mib_data.data);
+               return 0;
+       }
+
+       slsi_kfree_skb(cfm);
+       return 0;
+}
+
+#ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
+void slsi_mlme_set_country_for_recovery(struct slsi_dev *sdev)
+{
+       int ret = 0;
+       struct slsi_mib_data mib_data = { 0, NULL };
+
+       SLSI_MUTEX_LOCK(sdev->device_config_mutex);
+       ret = slsi_mib_encode_octet(&mib_data, SLSI_PSID_UNIFI_DEFAULT_COUNTRY, 3, sdev->device_config.domain_info.regdomain->alpha2, 0);
+       if (ret != SLSI_MIB_STATUS_SUCCESS) {
+               ret = -ENOMEM;
+               SLSI_ERR(sdev, "Err setting country error = %d\n", ret);
+               SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
+               return ;
+       }
+
+       if (mib_data.dataLength == 0) {
+               ret = -EINVAL;
+               SLSI_ERR(sdev, "Err setting country error = %d\n", ret);
+               SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
+               return ;
+       }
+
+       ret = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength);
+       kfree(mib_data.data);
+
+       if (ret)
+               SLSI_ERR(sdev, "Err setting country error = %d\n", ret);
+       SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
+}
 #endif
index 9a08f56b9719f2acae1741e7acf840caaa271c55..d54590b360d631b08b5437310f74bd7b5d6332c1 100755 (executable)
@@ -246,6 +246,7 @@ int slsi_mlme_set_pno_list(struct slsi_dev *sdev, int count,
                           struct slsi_epno_param *epno_param, struct slsi_epno_hs2_param *epno_hs2_param);
 int slsi_mlme_start_link_stats_req(struct slsi_dev *sdev, u16 mpdu_size_threshold, bool aggressive_statis_enabled);
 int slsi_mlme_stop_link_stats_req(struct slsi_dev *sdev, u16 stats_stop_mask);
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
 int slsi_mlme_nan_enable(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_enable_req *hal_req);
 int slsi_mlme_nan_publish(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_publish_req *hal_req,
                          u16 publish_id);
@@ -254,6 +255,12 @@ int slsi_mlme_nan_subscribe(struct slsi_dev *sdev, struct net_device *dev, struc
 int slsi_mlme_nan_tx_followup(struct slsi_dev *sdev, struct net_device *dev,
                              struct slsi_hal_nan_transmit_followup_req *hal_req);
 int slsi_mlme_nan_set_config(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_config_req *hal_req);
+int slsi_mlme_ndp_request(struct slsi_dev *sdev, struct net_device *dev,
+                         struct slsi_hal_nan_data_path_initiator_req *hal_req, u32 ndp_id, u16 ndl_vif_id);
+int slsi_mlme_ndp_response(struct slsi_dev *sdev, struct net_device *dev,
+                         struct slsi_hal_nan_data_path_indication_response *hal_req, u16 local_ndp_id);
+int slsi_mlme_ndp_terminate(struct slsi_dev *sdev, struct net_device *dev, u16 ndp_id);
+#endif
 #endif
 
 int slsi_mlme_set_ext_capab(struct slsi_dev *sdev, struct net_device *dev, struct slsi_mib_value *mib_val);
@@ -277,5 +284,10 @@ void slsi_decode_fw_rate(u16 fw_rate, struct rate_info *rate, unsigned long *dat
 int slsi_test_sap_configure_monitor_mode(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_chan_def *chandef);
 
 struct sk_buff *slsi_mlme_req_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 cfm_id);
+int slsi_mlme_set_country(struct slsi_dev *sdev, char *alpha2);
+
+#ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
+void slsi_mlme_set_country_for_recovery(struct slsi_dev *sdev);
+#endif
 
 #endif /*__SLSI_MLME_H__*/
index b22459b4adc121e5a2e4e2fdb284d273d09c9c85..9c6f498668269015b51fe2c4a2b28bf5105b5fa8 100755 (executable)
@@ -6,6 +6,7 @@
 
 #include "debug.h"
 #include "mlme.h"
+#include "nl80211_vendor_nan.h"
 
 #define SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, val) \
        { \
@@ -239,7 +240,7 @@ static u32 slsi_mlme_nan_append_ranging(struct sk_buff *req, struct slsi_nan_ran
        u8 *p;
 
        p = fapi_append_data_u16(req, SLSI_NAN_TLV_TAG_RANGING);
-       p = fapi_append_data_u16(req, 0x0007);
+       p = fapi_append_data_u16(req, 0x0009);
        p = fapi_append_data_u32(req, ranging_cfg->ranging_interval_msec);
        p = fapi_append_data_u8(req, ranging_cfg->config_ranging_indications);
        p = fapi_append_data_u16(req, ranging_cfg->distance_ingress_mm / 10);
@@ -249,7 +250,27 @@ static u32 slsi_mlme_nan_append_ranging(struct sk_buff *req, struct slsi_nan_ran
        return 1;
 }
 
-static u32 slsi_mlme_nan_enable_fapi_data(struct sk_buff *req, struct slsi_hal_nan_enable_req *hal_req)
+static int slsi_mlme_nan_append_ipv6_link_tlv(struct sk_buff *req, u8 *local_ndi)
+{
+       u8 *p;
+       u8 interface_identifier[8];
+
+       memcpy(&interface_identifier[0], &local_ndi[0], 3);
+       interface_identifier[3] = 0xFF;
+       interface_identifier[4] = 0xFE;
+       memcpy(&interface_identifier[5], &local_ndi[3], 3);
+
+       p = fapi_append_data_u16(req, SLSI_NAN_TLV_WFA_IPV6_LOCAL_LINK);
+       p = fapi_append_data_u16(req, 0x0008);
+       p = fapi_append_data(req, interface_identifier, 8);
+
+       if (p)
+               return 0;
+       return 1;
+}
+
+static u32 slsi_mlme_nan_enable_fapi_data(struct netdev_vif *ndev_vif, struct sk_buff *req, struct slsi_hal_nan_enable_req *hal_req,
+                                         u8 cluster_merge)
 {
        u16 publish_id_inc, service_id_inc;
        u8  publish_id_inc_count = 0;
@@ -267,7 +288,7 @@ static u32 slsi_mlme_nan_enable_fapi_data(struct sk_buff *req, struct slsi_hal_n
                service_id_inc_count = hal_req->subscribe_sid_beacon_val >> 1;
        ret = slsi_mlme_nan_append_config_tlv(req, hal_req->master_pref, publish_id_inc, publish_id_inc_count,
                                              service_id_inc, service_id_inc_count, rssi_window,
-                                             hal_req->disc_mac_addr_rand_interval_sec, 1);
+                                             hal_req->disc_mac_addr_rand_interval_sec, cluster_merge);
        if (ret) {
                SLSI_WARN_NODEV("Error append config TLV\n");
                return ret;
@@ -306,6 +327,27 @@ static u32 slsi_mlme_nan_enable_fapi_data(struct sk_buff *req, struct slsi_hal_n
        return ret;
 }
 
+void slsi_mlme_nan_store_config(struct netdev_vif *ndev_vif, struct slsi_hal_nan_enable_req *hal_req)
+{
+       ndev_vif->nan.config.config_rssi_proximity = hal_req->config_2dot4g_rssi_proximity;
+       ndev_vif->nan.config.rssi_close_2dot4g_val = hal_req->rssi_close_2dot4g_val;
+       ndev_vif->nan.config.rssi_middle_2dot4g_val = hal_req->rssi_middle_2dot4g_val;
+       ndev_vif->nan.config.rssi_proximity = hal_req->rssi_proximity_2dot4g_val;
+       ndev_vif->nan.config.scan_params_val.dwell_time[0] =  hal_req->scan_params_val.dwell_time[0];
+       ndev_vif->nan.config.scan_params_val.scan_period[0] = hal_req->scan_params_val.scan_period[0];
+       ndev_vif->nan.config.config_2dot4g_dw_band = (u16)hal_req->config_2dot4g_dw_band;
+       ndev_vif->nan.config.dw_2dot4g_interval_val = hal_req->dw_2dot4g_interval_val;
+
+       ndev_vif->nan.config.config_5g_rssi_close_proximity = hal_req->config_5g_rssi_close_proximity;
+       ndev_vif->nan.config.rssi_close_5g_val = hal_req->rssi_close_5g_val;
+       ndev_vif->nan.config.rssi_middle_5g_val = hal_req->rssi_middle_5g_val;
+       ndev_vif->nan.config.rssi_close_proximity_5g_val = hal_req->rssi_close_proximity_5g_val;
+       ndev_vif->nan.config.scan_params_val.dwell_time[1] =  hal_req->scan_params_val.dwell_time[1];
+       ndev_vif->nan.config.scan_params_val.scan_period[1] = hal_req->scan_params_val.scan_period[1];
+       ndev_vif->nan.config.config_5g_dw_band = (u16)hal_req->config_5g_dw_band;
+       ndev_vif->nan.config.dw_5g_interval_val = hal_req->dw_5g_interval_val;
+}
+
 int slsi_mlme_nan_enable(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_enable_req *hal_req)
 {
        struct netdev_vif *ndev_vif = netdev_priv(dev);
@@ -323,12 +365,9 @@ int slsi_mlme_nan_enable(struct slsi_dev *sdev, struct net_device *dev, struct s
                return -ENOMEM;
        }
 
-       nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT |
-                        FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT;
-
        fapi_set_u16(req, u.mlme_nan_start_req.nan_operation_control_flags, nan_oper_ctrl);
 
-       r = slsi_mlme_nan_enable_fapi_data(req, hal_req);
+       r = slsi_mlme_nan_enable_fapi_data(ndev_vif, req, hal_req, !ndev_vif->nan.disable_cluster_merge);
        if (r) {
                SLSI_NET_ERR(dev, "Failed to construct mbulkdata\n");
                slsi_kfree_skb(req);
@@ -341,10 +380,11 @@ int slsi_mlme_nan_enable(struct slsi_dev *sdev, struct net_device *dev, struct s
 
        if (fapi_get_u16(cfm, u.mlme_nan_start_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
                SLSI_NET_ERR(dev, "MLME_NAN_START_CFM(result:0x%04x) ERROR\n",
-                            fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
+                            fapi_get_u16(cfm, u.mlme_nan_start_cfm.result_code));
                r = -EINVAL;
        }
-
+       if (!r)
+               slsi_mlme_nan_store_config(ndev_vif, hal_req);
        slsi_kfree_skb(cfm);
        return r;
 }
@@ -452,6 +492,8 @@ int slsi_mlme_nan_publish(struct slsi_dev *sdev, struct net_device *dev, struct
                        nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT;
                if (hal_req->recv_indication_cfg & BIT(2))
                        nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT;
+               /* Store the SDF Flags */
+               ndev_vif->nan.nan_sdf_flags[publish_id] = nan_sdf_flags;
        } else {
                req = fapi_alloc(mlme_nan_publish_req, MLME_NAN_PUBLISH_REQ, ndev_vif->ifnum, 0);
                if (!req) {
@@ -460,8 +502,8 @@ int slsi_mlme_nan_publish(struct slsi_dev *sdev, struct net_device *dev, struct
                }
        }
 
-       fapi_set_u16(req, u.mlme_nan_publish_req.publish_id, publish_id);
-       fapi_set_u16(req, u.mlme_nan_publish_req.nan_sdf_flags, nan_sdf_flags);
+       fapi_set_u16(req, u.mlme_nan_publish_req.session_id, publish_id);
+       fapi_set_u16(req, u.mlme_nan_publish_req.nan_sdf_flags, 0);
 
        if (hal_req) {
                r = slsi_mlme_nan_publish_fapi_data(req, hal_req);
@@ -478,14 +520,14 @@ int slsi_mlme_nan_publish(struct slsi_dev *sdev, struct net_device *dev, struct
 
        if (fapi_get_u16(cfm, u.mlme_nan_publish_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
                SLSI_NET_ERR(dev, "MLME_NAN_PUBLISH_CFM(result:0x%04x) ERROR\n",
-                            fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
+                            fapi_get_u16(cfm, u.mlme_nan_publish_cfm.result_code));
                r = -EINVAL;
        }
 
        if (hal_req && !r)
-               ndev_vif->nan.publish_id_map |= (u32)BIT(publish_id);
+               ndev_vif->nan.service_id_map |= (u32)BIT(publish_id);
        else
-               ndev_vif->nan.publish_id_map &= (u32)~BIT(publish_id);
+               ndev_vif->nan.service_id_map &= (u32)~BIT(publish_id);
        slsi_kfree_skb(cfm);
        return r;
 }
@@ -610,6 +652,7 @@ int slsi_mlme_nan_subscribe(struct slsi_dev *sdev, struct net_device *dev, struc
                        nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT;
                if (hal_req->recv_indication_cfg & BIT(2))
                        nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT;
+               ndev_vif->nan.nan_sdf_flags[subscribe_id] = nan_sdf_flags;
        } else {
                req = fapi_alloc(mlme_nan_subscribe_req, MLME_NAN_SUBSCRIBE_REQ, ndev_vif->ifnum, 0);
                if (!req) {
@@ -618,8 +661,8 @@ int slsi_mlme_nan_subscribe(struct slsi_dev *sdev, struct net_device *dev, struc
                }
        }
 
-       fapi_set_u16(req, u.mlme_nan_subscribe_req.subscribe_id, subscribe_id);
-       fapi_set_u16(req, u.mlme_nan_subscribe_req.nan_sdf_flags, nan_sdf_flags);
+       fapi_set_u16(req, u.mlme_nan_subscribe_req.session_id, subscribe_id);
+       fapi_set_u16(req, u.mlme_nan_subscribe_req.nan_sdf_flags, 0);
 
        if (hal_req) {
                r = slsi_mlme_nan_subscribe_fapi_data(req, hal_req);
@@ -636,14 +679,14 @@ int slsi_mlme_nan_subscribe(struct slsi_dev *sdev, struct net_device *dev, struc
 
        if (fapi_get_u16(cfm, u.mlme_nan_subscribe_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
                SLSI_NET_ERR(dev, "MLME_NAN_SUBSCRIBE_CFM(res:0x%04x)\n",
-                            fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
+                            fapi_get_u16(cfm, u.mlme_nan_subscribe_cfm.result_code));
                r = -EINVAL;
        }
 
        if (hal_req && !r)
-               ndev_vif->nan.subscribe_id_map |= (u32)BIT(subscribe_id);
+               ndev_vif->nan.service_id_map |= (u32)BIT(subscribe_id);
        else
-               ndev_vif->nan.subscribe_id_map &= (u32)~BIT(subscribe_id);
+               ndev_vif->nan.service_id_map &= (u32)~BIT(subscribe_id);
        slsi_kfree_skb(cfm);
        return r;
 }
@@ -688,7 +731,7 @@ int slsi_mlme_nan_tx_followup(struct slsi_dev *sdev, struct net_device *dev,
                return -ENOMEM;
        }
 
-       fapi_set_u16(req, u.mlme_nan_followup_req.publish_subscribe_id, hal_req->publish_subscribe_id);
+       fapi_set_u16(req, u.mlme_nan_followup_req.session_id, hal_req->publish_subscribe_id);
        fapi_set_u16(req, u.mlme_nan_followup_req.match_id, hal_req->requestor_instance_id);
        fapi_set_u16(req, u.mlme_nan_followup_req.nan_sdf_flags, nan_sdf_flags);
 
@@ -705,27 +748,37 @@ int slsi_mlme_nan_tx_followup(struct slsi_dev *sdev, struct net_device *dev,
 
        if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
                SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n",
-                            fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
-               r = -EINVAL;
+                            fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code));
+               if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) ==
+                   FAPI_RESULTCODE_TOO_MANY_SIMULTANEOUS_REQUESTS)
+                       r = SLSI_HAL_NAN_STATUS_FOLLOWUP_QUEUE_FULL;
+               else
+                       r = -EINVAL;
        }
 
        slsi_kfree_skb(cfm);
        return r;
 }
 
-static u32 slsi_mlme_nan_config_fapi_data(struct sk_buff *req, struct slsi_hal_nan_config_req *hal_req)
+static u32 slsi_mlme_nan_config_fapi_data(struct netdev_vif *ndev_vif, struct sk_buff *req, struct slsi_hal_nan_config_req *hal_req, u8 cluster_merge)
 {
        u16 rssi_window = hal_req->config_rssi_window_size ? hal_req->rssi_window_size_val : 8;
        u32 ret;
-       u8  rssi_close = 0, rssi_middle = 0, rssi_proximity = 0;
+       u8  rssi_close = hal_req->rssi_close_2dot4g_val;
+       u8  rssi_middle = hal_req->rssi_middle_2dot4g_val;
+       u8  rssi_proximity = 0;
+
        u16 is_sid_in_beacon = hal_req->config_subscribe_sid_beacon && (hal_req->subscribe_sid_beacon_val & 0x01);
        u8  sid_count_in_beacon = hal_req->config_subscribe_sid_beacon ? hal_req->subscribe_sid_beacon_val >> 1 : 0;
 
+       if (!hal_req->master_pref)
+               hal_req->master_pref = ndev_vif->nan.master_pref_value;
+
        ret = slsi_mlme_nan_append_config_tlv(req, hal_req->master_pref,
                                              hal_req->config_sid_beacon && (hal_req->sid_beacon & 0x01),
                                              hal_req->config_sid_beacon ? hal_req->sid_beacon >> 1 : 0,
                                              is_sid_in_beacon, sid_count_in_beacon, rssi_window,
-                                             hal_req->disc_mac_addr_rand_interval_sec, 1);
+                                             hal_req->disc_mac_addr_rand_interval_sec, cluster_merge);
        if (ret) {
                SLSI_WARN_NODEV("Error append config TLV\n");
                return ret;
@@ -733,6 +786,7 @@ static u32 slsi_mlme_nan_config_fapi_data(struct sk_buff *req, struct slsi_hal_n
 
        /* 2.4G NAN band specific config*/
        rssi_proximity = hal_req->config_rssi_proximity ? hal_req->rssi_proximity : 0;
+
        ret = slsi_mlme_nan_append_2g4_band_specific_config(req, rssi_close, rssi_middle, rssi_proximity,
                                                            hal_req->scan_params_val.dwell_time[0],
                                                            hal_req->scan_params_val.scan_period[0],
@@ -744,7 +798,10 @@ static u32 slsi_mlme_nan_config_fapi_data(struct sk_buff *req, struct slsi_hal_n
        }
 
        /* 5G NAN band specific config*/
+       rssi_close = hal_req->rssi_close_5g_val;
+       rssi_middle = hal_req->rssi_middle_5g_val;
        rssi_proximity = hal_req->config_5g_rssi_close_proximity ? hal_req->rssi_close_proximity_5g_val : 0;
+
        ret = slsi_mlme_nan_append_5g_band_specific_config(req, rssi_close, rssi_middle, rssi_proximity,
                                                           hal_req->scan_params_val.dwell_time[1],
                                                           hal_req->scan_params_val.scan_period[1],
@@ -771,11 +828,9 @@ int slsi_mlme_nan_set_config(struct slsi_dev *sdev, struct net_device *dev, stru
                return -ENOMEM;
        }
 
-       nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT |
-                       FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT;
        fapi_set_u16(req, u.mlme_nan_config_req.nan_operation_control_flags, nan_oper_ctrl);
 
-       r = slsi_mlme_nan_config_fapi_data(req, hal_req);
+       r = slsi_mlme_nan_config_fapi_data(ndev_vif, req, hal_req, !ndev_vif->nan.disable_cluster_merge);
        if (r) {
                SLSI_NET_ERR(dev, "Failed to construct mbulkdata\n");
                slsi_kfree_skb(req);
@@ -786,12 +841,239 @@ int slsi_mlme_nan_set_config(struct slsi_dev *sdev, struct net_device *dev, stru
        if (!cfm)
                return -EIO;
 
-       if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
+       if (fapi_get_u16(cfm, u.mlme_nan_config_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
                SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n",
-                            fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
+                            fapi_get_u16(cfm, u.mlme_nan_config_cfm.result_code));
+               r = -EINVAL;
+       }
+
+       slsi_kfree_skb(cfm);
+       return r;
+}
+
+static int slsi_mlme_ndp_request_fapi_data(struct sk_buff *req,
+                                          struct slsi_hal_nan_data_path_initiator_req *hal_req,
+                                          bool include_ipv6_addr_tlv, u8 *local_ndi)
+{
+       int ret;
+
+       ret = slsi_mlme_nan_append_data_path_sec(req, &hal_req->key_info);
+       if (ret) {
+               SLSI_WARN_NODEV("Error data_path sec TLV\n");
+               return ret;
+       }
+
+       if (hal_req->app_info.ndp_app_info_len) {
+               ret = slsi_mlme_nan_append_tlv(req, SLSI_NAN_TLV_TAG_APP_INFO, hal_req->app_info.ndp_app_info_len,
+                                              hal_req->app_info.ndp_app_info);
+               if (ret) {
+                       SLSI_WARN_NODEV("Error app info TLV\n");
+                       return ret;
+               }
+       }
+
+       if (include_ipv6_addr_tlv) {
+               ret = slsi_mlme_nan_append_ipv6_link_tlv(req, local_ndi);
+               if (ret) {
+                       SLSI_WARN_NODEV("Error ipv6 link tlv\n");
+                       return ret;
+               }
+       }
+       return ret;
+}
+
+int slsi_mlme_ndp_request(struct slsi_dev *sdev, struct net_device *dev,
+                         struct slsi_hal_nan_data_path_initiator_req *hal_req, u32 ndp_id, u16 ndl_vif_id)
+{
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+       struct sk_buff    *req;
+       struct sk_buff    *cfm;
+       int               r = 0, data_len;
+       bool              include_ipv6_link_tlv;
+       u8                *local_ndi;
+       struct net_device *data_dev;
+
+       SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
+
+       data_dev = slsi_get_netdev_by_ifname(sdev, hal_req->ndp_iface);
+       if (!data_dev) {
+               SLSI_NET_ERR(dev, "no net_device for %s\n", hal_req->ndp_iface);
+               return -EINVAL;
+       }
+       local_ndi = data_dev->dev_addr;
+
+       include_ipv6_link_tlv = slsi_dev_nan_is_ipv6_link_tlv_include();
+
+       data_len = 74; /* for datapath security tlv */
+       data_len += hal_req->app_info.ndp_app_info_len ? 4 + hal_req->app_info.ndp_app_info_len : 0;
+       data_len += include_ipv6_link_tlv ? 4 + 8 : 0;
+
+       req = fapi_alloc(mlme_ndp_request_req, MLME_NDP_REQUEST_REQ, ndev_vif->ifnum, data_len);
+       if (!req) {
+               SLSI_NET_ERR(dev, "fapi alloc failure\n");
+               return -ENOMEM;
+       }
+
+       fapi_set_u16(req, u.mlme_ndp_request_req.ndl_vif_index, ndl_vif_id);
+       fapi_set_u16(req, u.mlme_ndp_request_req.match_id, hal_req->requestor_instance_id);
+       fapi_set_memcpy(req, u.mlme_ndp_request_req.local_ndp_interface_address, local_ndi);
+
+       r = slsi_mlme_ndp_request_fapi_data(req, hal_req, include_ipv6_link_tlv, local_ndi);
+       if (r) {
+               SLSI_NET_ERR(dev, "Failed to construct mbulkdata\n");
+               slsi_kfree_skb(req);
+               return -EINVAL;
+       }
+
+       cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NDP_REQUEST_CFM);
+       if (!cfm)
+               return -EIO;
+
+       if (fapi_get_u16(cfm, u.mlme_ndp_request_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
+               SLSI_NET_ERR(dev, "MLME_NDP_REQUEST_CFM(res:0x%04x)\n",
+                            fapi_get_u16(cfm, u.mlme_ndp_request_cfm.result_code));
                r = -EINVAL;
+       } else {
+               if (slsi_nan_ndp_new_entry(sdev, dev, ndp_id, ndl_vif_id, local_ndi, hal_req->peer_disc_mac_addr))
+                       SLSI_NET_ERR(dev, "invalid ndl_vifid:%d ndp_id:%d\n", ndl_vif_id, ndp_id);
        }
 
        slsi_kfree_skb(cfm);
        return r;
 }
+
+static int slsi_mlme_ndp_response_fapi_data(struct sk_buff *req,
+                                           struct slsi_hal_nan_data_path_indication_response *hal_req,
+                                           bool include_ipv6_link_tlv, u8 *local_ndi)
+{
+       int ret;
+
+       ret = slsi_mlme_nan_append_data_path_sec(req, &hal_req->key_info);
+       if (ret) {
+               SLSI_WARN_NODEV("Error data_path sec TLV\n");
+               return ret;
+       }
+
+       if (hal_req->app_info.ndp_app_info_len) {
+               ret = slsi_mlme_nan_append_tlv(req, SLSI_NAN_TLV_TAG_APP_INFO, hal_req->app_info.ndp_app_info_len,
+                                              hal_req->app_info.ndp_app_info);
+               if (ret) {
+                       SLSI_WARN_NODEV("Error app info TLV\n");
+                       return ret;
+               }
+       }
+
+       if (include_ipv6_link_tlv) {
+               ret = slsi_mlme_nan_append_ipv6_link_tlv(req, local_ndi);
+               if (ret) {
+                       SLSI_WARN_NODEV("Error ipv6 link tlv\n");
+                       return ret;
+               }
+       }
+       return ret;
+}
+
+int slsi_mlme_ndp_response(struct slsi_dev *sdev, struct net_device *dev,
+                          struct slsi_hal_nan_data_path_indication_response *hal_req, u16 local_ndp_id)
+{
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+       struct sk_buff    *req;
+       struct sk_buff    *cfm;
+       int               r = 0, data_len;
+       bool              include_ipv6_link_tlv;
+       u8                *local_ndi;
+       u16               ndl_vif_id, rsp_code;
+       struct net_device *data_dev;
+       u8                nomac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
+
+       SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
+       data_dev = slsi_get_netdev_by_ifname(sdev, hal_req->ndp_iface);
+       if (!data_dev)
+               local_ndi = nomac;
+       else
+               local_ndi = data_dev->dev_addr;
+
+       include_ipv6_link_tlv = slsi_dev_nan_is_ipv6_link_tlv_include();
+
+       data_len = 74; /* for datapath security tlv */
+       data_len += hal_req->app_info.ndp_app_info_len ? 4 + hal_req->app_info.ndp_app_info_len : 0;
+       data_len += include_ipv6_link_tlv ? 4 + 8 : 0;
+
+       req = fapi_alloc(mlme_ndp_response_req, MLME_NDP_RESPONSE_REQ, ndev_vif->ifnum, data_len);
+       if (!req) {
+               SLSI_NET_ERR(dev, "fapi alloc failure\n");
+               return -ENOMEM;
+       }
+       if (hal_req->ndp_instance_id)
+               ndl_vif_id = ndev_vif->nan.ndp_id2ndl_vif[hal_req->ndp_instance_id - 1];
+       else
+               ndl_vif_id = 0;
+       fapi_set_u16(req, u.mlme_ndp_response_req.ndl_vif_index, ndl_vif_id);
+       fapi_set_u16(req, u.mlme_ndp_response_req.request_id, local_ndp_id);
+       fapi_set_memcpy(req, u.mlme_ndp_response_req.local_ndp_interface_address, local_ndi);
+       rsp_code = hal_req->rsp_code == NAN_DP_REQUEST_ACCEPT ? FAPI_REASONCODE_NDP_ACCEPTED :
+                  FAPI_REASONCODE_NDP_REJECTED;
+       fapi_set_u16(req, u.mlme_ndp_response_req.reason_code, rsp_code);
+       r = slsi_mlme_ndp_response_fapi_data(req, hal_req, include_ipv6_link_tlv, local_ndi);
+       if (r) {
+               SLSI_NET_ERR(dev, "Failed to construct mbulkdata\n");
+               slsi_kfree_skb(req);
+               return -EINVAL;
+       }
+
+       cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NDP_RESPONSE_CFM);
+       if (!cfm)
+               return -EIO;
+
+       if (fapi_get_u16(cfm, u.mlme_ndp_response_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
+               SLSI_NET_ERR(dev, "MLME_NDP_RESPONSE_CFM(res:0x%04x)\n",
+                            fapi_get_u16(cfm, u.mlme_ndp_request_cfm.result_code));
+               r = -EINVAL;
+       } else {
+               /* new ndp entry was made when received mlme-ndp-requested.ind
+                * but local_ndi is decided now.
+                */
+               ether_addr_copy(ndev_vif->nan.ndp_ndi[hal_req->ndp_instance_id - 1], local_ndi);
+       }
+
+       slsi_kfree_skb(cfm);
+       return r;
+}
+
+int slsi_mlme_ndp_terminate(struct slsi_dev *sdev, struct net_device *dev, u16 ndp_id)
+{
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+       struct sk_buff    *req;
+       struct sk_buff    *cfm;
+       u16               ndl_vif_id;
+
+       if (ndev_vif->nan.ndp_state[ndp_id - 1] != ndp_slot_status_in_use) {
+               slsi_nan_ndp_termination_handler(sdev, dev, ndp_id, ndl_vif_id, ndev_vif->nan.ndp_ndi[ndp_id - 1]);
+               return 0;
+       }
+
+       req = fapi_alloc(mlme_ndp_terminate_req, MLME_NDP_TERMINATE_REQ, ndev_vif->ifnum, 0);
+       if (!req) {
+               SLSI_NET_ERR(dev, "fapi alloc failure\n");
+               return -ENOMEM;
+       }
+
+       ndl_vif_id = ndev_vif->nan.ndp_id2ndl_vif[ndp_id - 1];
+       fapi_set_u16(req, u.mlme_ndp_terminate_req.ndl_vif_index, ndl_vif_id);
+       fapi_set_memcpy(req, u.mlme_ndp_terminate_req.local_ndp_interface_address, ndev_vif->nan.ndp_ndi[ndp_id - 1]);
+
+       cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NDP_TERMINATE_CFM);
+       if (!cfm) {
+               slsi_nan_ndp_termination_handler(sdev, dev, ndp_id, ndl_vif_id, ndev_vif->nan.ndp_ndi[ndp_id - 1]);
+               return -EIO;
+       }
+
+       if (fapi_get_u16(cfm, u.mlme_ndp_terminate_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
+               SLSI_NET_ERR(dev, "MLME_NDP_TERMINATE_CFM(res:0x%04x)\n",
+                            fapi_get_u16(cfm, u.mlme_ndp_terminate_cfm.result_code));
+               slsi_nan_ndp_termination_handler(sdev, dev, ndp_id, ndl_vif_id, ndev_vif->nan.ndp_ndi[ndp_id - 1]);
+       }
+
+       slsi_kfree_skb(cfm);
+       return 0;
+}
index 4d2a8f9da7d3d1e889b7f23d6ef7bb660a8131fb..e2583313038ab5d6543d918116b5ebacd74092b3 100755 (executable)
@@ -133,6 +133,40 @@ static int slsi_netif_tcp_ack_suppression_stop(struct net_device *dev);
 static struct sk_buff *slsi_netif_tcp_ack_suppression_pkt(struct net_device *dev, struct sk_buff *skb);
 #endif
 
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+void slsi_net_randomize_nmi_ndi(struct slsi_dev *sdev)
+{
+       int               exor_base = 1, exor_byte = 5, i;
+       u8                random_mac[ETH_ALEN];
+
+       /* Randomize mac address */
+       SLSI_ETHER_COPY(random_mac, sdev->hw_addr);
+       /* If random number is same as actual bytes in hw_address
+        * try random again. hope 2nd random will not be same as
+        * bytes in hw_address
+        */
+       slsi_get_random_bytes(&random_mac[3], 3);
+       if (!memcmp(&random_mac[3], &sdev->hw_addr[3], 3))
+               slsi_get_random_bytes(&random_mac[3], 3);
+       SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_NAN], random_mac);
+       /* Set the local bit */
+       sdev->netdev_addresses[SLSI_NET_INDEX_NAN][0] |= 0x02;
+       /* EXOR 4th byte with 0x80 */
+       sdev->netdev_addresses[SLSI_NET_INDEX_NAN][3] ^= 0x80;
+       for (i = SLSI_NAN_DATA_IFINDEX_START; i < CONFIG_SCSC_WLAN_MAX_INTERFACES + 1; i++) {
+               SLSI_ETHER_COPY(sdev->netdev_addresses[i], random_mac);
+               sdev->netdev_addresses[i][0] |= 0x02;
+               sdev->netdev_addresses[i][exor_byte] ^= exor_base;
+               exor_base++;
+               /* currently supports upto 15 mac address for nan
+                * data interface
+                */
+               if (exor_base > 0xf)
+                       break;
+       }
+}
+#endif
+
 /* Net Device callback operations */
 static int slsi_net_open(struct net_device *dev)
 {
@@ -166,15 +200,16 @@ static int slsi_net_open(struct net_device *dev)
                SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_WLAN], sdev->hw_addr);
 
                SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_P2P],  sdev->hw_addr);
-               sdev->netdev_addresses[SLSI_NET_INDEX_P2P][0] |= 0x02; /* Set the local bit */
+               /* Set the local bit */
+               sdev->netdev_addresses[SLSI_NET_INDEX_P2P][0] |= 0x02;
 
                SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_P2PX_SWLAN], sdev->hw_addr);
-               sdev->netdev_addresses[SLSI_NET_INDEX_P2PX_SWLAN][0] |= 0x02; /* Set the local bit */
-               sdev->netdev_addresses[SLSI_NET_INDEX_P2PX_SWLAN][4] ^= 0x80; /* EXOR 5th byte with 0x80 */
-#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4
-               SLSI_ETHER_COPY(sdev->netdev_addresses[SLSI_NET_INDEX_NAN], sdev->hw_addr);
-               sdev->netdev_addresses[SLSI_NET_INDEX_NAN][0] |= 0x02; /* Set the local bit */
-               sdev->netdev_addresses[SLSI_NET_INDEX_NAN][3] ^= 0x80; /* EXOR 4th byte with 0x80 */
+               /* Set the local bit */
+               sdev->netdev_addresses[SLSI_NET_INDEX_P2PX_SWLAN][0] |= 0x02;
+               /* EXOR 5th byte with 0x80 */
+               sdev->netdev_addresses[SLSI_NET_INDEX_P2PX_SWLAN][4] ^= 0x80;
+#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 && defined(CONFIG_SCSC_WIFI_NAN_ENABLE)
+               slsi_net_randomize_nmi_ndi(sdev);
 #endif
                sdev->initial_scan = true;
        }
@@ -214,6 +249,11 @@ static int slsi_net_open(struct net_device *dev)
 #ifndef CONFIG_ARM
        slsi_netif_tcp_ack_suppression_start(dev);
 #endif
+
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+       if (ndev_vif->ifnum >= SLSI_NAN_DATA_IFINDEX_START)
+               netif_carrier_on(dev);
+#endif
        SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
 
        netif_tx_start_all_queues(dev);
@@ -507,8 +547,9 @@ static void slsi_net_downgrade_pri(struct net_device *dev, struct slsi_peer *pee
        }
        SLSI_NET_DBG4(dev, SLSI_NETDEV, "To UP:%d\n", skb->priority);
 }
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
+static u16 slsi_net_select_queue(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev, select_queue_fallback_t fallback)
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
 static u16 slsi_net_select_queue(struct net_device *dev, struct sk_buff *skb, void *accel_priv, select_queue_fallback_t fallback)
 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
 static u16 slsi_net_select_queue(struct net_device *dev, struct sk_buff *skb, void *accel_priv)
@@ -522,8 +563,9 @@ static u16 slsi_net_select_queue(struct net_device *dev, struct sk_buff *skb)
        struct ethhdr     *ehdr = (struct ethhdr *)skb->data;
        int               proto = 0;
        struct slsi_peer  *peer;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
+       (void)sb_dev;
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
        (void)accel_priv;
 #endif
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
@@ -694,9 +736,17 @@ void slsi_tdls_move_packets(struct slsi_dev *sdev, struct net_device *dev,
                        for (j = 0; j < num_pkts; j++) {
                                qd = dev->_tx[staq + i].qdisc;
                                /* Dequeue the pkt form STAQ. This logic is similar to kernel API dequeue_skb() */
-                               skb = qd->gso_skb;
+                               #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
+                                       skb = skb_peek(&qd->gso_skb);
+                               #else
+                                       skb = qd->gso_skb;
+                               #endif
                                if (skb) {
+                               #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
+                                       skb = __skb_dequeue(&qd->gso_skb);
+                               #else
                                        qd->gso_skb = NULL;
+                               #endif
                                        qd->q.qlen--;
                                } else {
                                        skb = qd->dequeue(qd);
@@ -731,9 +781,17 @@ void slsi_tdls_move_packets(struct slsi_dev *sdev, struct net_device *dev,
                        for (j = 0; j < num_pkts; j++) {
                                /* Dequeue the pkt form TDLS_Q. This logic is similar to kernel API dequeue_skb() */
                                qd = dev->_tx[tdlsq + i].qdisc;
-                               skb = qd->gso_skb;
+                               #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
+                                       skb = skb_peek(&qd->gso_skb);
+                               #else
+                                       skb = qd->gso_skb;
+                               #endif
                                if (skb) {
+                               #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
+                                       skb = __skb_dequeue(&qd->gso_skb);
+                               #else
                                        qd->gso_skb = NULL;
+                               #endif
                                        qd->q.qlen--;
                                } else {
                                        skb = qd->dequeue(qd);
@@ -873,11 +931,17 @@ static netdev_tx_t slsi_net_hw_xmit(struct sk_buff *skb, struct net_device *dev)
 
        SLSI_NET_DBG3(dev, SLSI_TX, "Proto 0x%.4X\n", be16_to_cpu(eth_hdr(skb)->h_proto));
 
-       if (!ndev_vif->is_available) {
-               SLSI_NET_WARN(dev, "vif NOT available\n");
-               r = -EFAULT;
-               goto evaluate;
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+       if (ndev_vif->ifnum < SLSI_NAN_DATA_IFINDEX_START) {
+#endif
+               if (!ndev_vif->is_available) {
+                       SLSI_NET_WARN(dev, "vif NOT available\n");
+                       r = -EFAULT;
+                       goto evaluate;
+               }
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
        }
+#endif
        if (skb->queue_mapping == SLSI_NETIF_Q_DISCARD) {
                SLSI_NET_WARN(dev, "Discard Queue :: Packet Dropped\n");
                r = -EIO;
@@ -1063,12 +1127,11 @@ static int  slsi_set_mac_address(struct net_device *dev, void *addr)
        SLSI_NET_DBG1(dev, SLSI_NETDEV, "slsi_set_mac_address %pM\n", sa->sa_data);
        SLSI_ETHER_COPY(dev->dev_addr, sa->sa_data);
 
-       // Setting of MAC Address is called, when the Mac Address is changed.
-       // And Mac Address is changed during the Mac Randomization Cases.
-       // During Connected Mac Randomization, enabling the initial scan for faster reconnection.
+       /* Interface is pulled down before mac address is changed.
+        * First scan initiated after interface is brought up again, should be treated as initial scan, for faster reconnection.
+        */
        if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) {
                sdev->initial_scan = true;
-               SLSI_NET_DBG1(dev, SLSI_NETDEV, "slsi_set_mac_address : Value of initial_scan is %d\n", sdev->initial_scan);
        }
        return 0;
 }
@@ -1393,7 +1456,7 @@ int slsi_netif_init(struct slsi_dev *sdev)
        return 0;
 }
 
-static int slsi_netif_register_locked(struct slsi_dev *sdev, struct net_device *dev)
+int slsi_netif_register_locked(struct slsi_dev *sdev, struct net_device *dev)
 {
        struct netdev_vif *ndev_vif = netdev_priv(dev);
        int               err;
@@ -1912,7 +1975,11 @@ static struct sk_buff *slsi_netif_tcp_ack_suppression_pkt(struct net_device *dev
        if (be16_to_cpu(ip_hdr(skb)->tot_len) > ((ip_hdr(skb)->ihl * 4) + (tcp_hdr(skb)->doff * 4))) {
                SCSC_HIP4_SAMPLER_TCP_DATA(ndev_vif->sdev->minor_prof, tcp_ack->stream_id, be32_to_cpu(tcp_hdr(skb)->seq));
                SCSC_HIP4_SAMPLER_TCP_CWND(ndev_vif->sdev->minor_prof, tcp_ack->stream_id, (skb->sk) ? tcp_sk(skb->sk)->snd_cwnd : 0);
-               SCSC_HIP4_SAMPLER_TCP_SEND_BUF(ndev_vif->sdev->minor_prof, tcp_ack->stream_id, sysctl_tcp_wmem[2]);
+       #if KERNEL_VERSION(4, 14, 0) >= LINUX_VERSION_CODE
+               SCSC_HIP4_SAMPLER_TCP_SEND_BUG(ndev_vif->sdev->minor_prof, tcp_ack->stream_id, sysctl_tcp_wmem[2]);
+       #else
+               SCSC_HIP4_SAMPLER_TCP_SEND_BUF(ndev_vif->sdev->minor_prof, tcp_ack->stream_id, sysctl_tcp_mem[2]);
+       #endif
                ndev_vif->tcp_ack_stats.tack_hasdata++;
                forward_now = 1;
                goto _forward_now;
index 3a59c9458173fdc73d3f1f1ff685aca7e8f124a4..fa8623b4e8f75abab6bd7c32a3ef0b6609b79bfe 100755 (executable)
@@ -1,6 +1,6 @@
 /*****************************************************************************
  *
- * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved
+ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
  *
  ****************************************************************************/
 
@@ -101,5 +101,10 @@ void slsi_netif_deinit(struct slsi_dev *sdev);
 void slsi_tdls_move_packets(struct slsi_dev *sdev, struct net_device *dev,
                            struct slsi_peer *sta_peer, struct slsi_peer *tdls_peer, bool connection);
 void slsi_netif_remove_locked(struct slsi_dev *sdev, struct net_device *dev);
+int slsi_netif_add_locked(struct slsi_dev *sdev, const char *name, int ifnum);
+int slsi_netif_register_locked(struct slsi_dev *sdev, struct net_device *dev);
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+void slsi_net_randomize_nmi_ndi(struct slsi_dev *sdev);
+#endif
 
 #endif /*__SLSI_NETIF_H__*/
index 27d62b7cd4ddcf815672c255536bd75a0251c1e0..4d59ad8c55654450a3023ff3089d57c9ac785ddf 100755 (executable)
@@ -107,6 +107,12 @@ char *slsi_print_event_name(int event_id)
                return "SLSI_NL80211_VENDOR_ACS_EVENT";
        case SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS:
                return "SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS";
+       case SLSI_NAN_EVENT_NDP_REQ:
+               return "SLSI_NAN_EVENT_NDP_REQ";
+       case SLSI_NAN_EVENT_NDP_CFM:
+               return "SLSI_NAN_EVENT_NDP_CFM";
+       case SLSI_NAN_EVENT_NDP_END:
+               return "SLSI_NAN_EVENT_NDP_END";
        default:
                return "UNKNOWN_EVENT";
        }
@@ -221,6 +227,8 @@ static int slsi_gscan_get_capabilities(struct wiphy *wiphy,
        struct slsi_dev                   *sdev = SDEV_FROM_WIPHY(wiphy);
 
        SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_GET_GSCAN_CAPABILITIES\n");
+        if (!slsi_dev_gscan_supported())
+               return -ENOTSUPP;
 
        memset(&nl_cap, 0, sizeof(struct slsi_nl_gscan_capabilities));
 
@@ -1341,7 +1349,7 @@ static int slsi_set_bssid_blacklist(struct wiphy *wiphy, struct wireless_dev *wd
                                goto exit;
                        }
                        num_bssids = nla_get_u32(attr);
-                       if (num_bssids == 0 || (num_bssids > (u32)(0xFFFFFFFF / (sizeof(*acl_data) + sizeof(struct mac_address))))) {
+                       if (num_bssids == 0 || (num_bssids > (u32)((ULONG_MAX - sizeof(*acl_data)) / (sizeof(struct mac_address))))) {
                                ret = -EINVAL;
                                goto exit;
                        }
@@ -1449,6 +1457,10 @@ static int slsi_start_keepalive_offload(struct wiphy *wiphy, struct wireless_dev
 
                switch (type) {
                case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN:
+                       if (nla_len(attr) != (SLSI_NL_ATTRIBUTE_U16_LEN - NLA_HDRLEN)) {
+                               r = -EINVAL;
+                               goto exit;
+                       }
                        ip_pkt_len = nla_get_u16(attr);
                        break;
 
@@ -1457,6 +1469,10 @@ static int slsi_start_keepalive_offload(struct wiphy *wiphy, struct wireless_dev
                        break;
 
                case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC:
+                       if (nla_len(attr) != (SLSI_NL_ATTRIBUTE_U32_LEN - NLA_HDRLEN)) {
+                               r = -EINVAL;
+                               goto exit;
+                       }
                        period = nla_get_u32(attr);
                        break;
 
@@ -1469,7 +1485,15 @@ static int slsi_start_keepalive_offload(struct wiphy *wiphy, struct wireless_dev
                        break;
 
                case MKEEP_ALIVE_ATTRIBUTE_ID:
+                       if (nla_len(attr) != (SLSI_NL_ATTRIBUTE_U8_LEN - NLA_HDRLEN)) {
+                               r = -EINVAL;
+                               goto exit;
+                       }
                        index = nla_get_u8(attr);
+                       if (index > SLSI_MAX_KEEPALIVE_ID) {
+                               r = -EINVAL;
+                               goto exit;
+                       }
                        break;
 
                default:
@@ -1579,7 +1603,15 @@ static int slsi_stop_keepalive_offload(struct wiphy *wiphy, struct wireless_dev
 
                switch (type) {
                case MKEEP_ALIVE_ATTRIBUTE_ID:
+                       if (nla_len(attr) != (SLSI_NL_ATTRIBUTE_U8_LEN - NLA_HDRLEN)) {
+                               r = -EINVAL;
+                               goto exit;
+                       }
                        index = nla_get_u8(attr);
+                       if (index > SLSI_MAX_KEEPALIVE_ID) {
+                               r = -EINVAL;
+                               goto exit;
+                       }
                        break;
 
                default:
@@ -2575,6 +2607,12 @@ static int slsi_get_feature_set(struct wiphy *wiphy,
 
        SLSI_DBG3_NODEV(SLSI_GSCAN, "\n");
 
+       feature_set |= SLSI_WIFI_HAL_FEATURE_INFRA;
+       feature_set |= SLSI_WIFI_HAL_FEATURE_INFRA_5G;
+#ifndef CONFIG_SCSC_WLAN_STA_ONLY
+       feature_set |= SLSI_WIFI_HAL_FEATURE_P2P;
+       feature_set |= SLSI_WIFI_HAL_FEATURE_SOFT_AP;
+#endif
        feature_set |= SLSI_WIFI_HAL_FEATURE_RSSI_MONITOR;
        feature_set |= SLSI_WIFI_HAL_FEATURE_CONTROL_ROAMING;
        feature_set |= SLSI_WIFI_HAL_FEATURE_TDLS | SLSI_WIFI_HAL_FEATURE_TDLS_OFFCHANNEL;
@@ -2598,6 +2636,18 @@ static int slsi_get_feature_set(struct wiphy *wiphy,
                feature_set |= SLSI_WIFI_HAL_FEATURE_D2AP_RTT;
        }
 
+       feature_set |= SLSI_WIFI_HAL_FEATURE_BATCH_SCAN;
+       feature_set |= SLSI_WIFI_HAL_FEATURE_PNO;
+#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING
+       feature_set |= SLSI_WIFI_HAL_FEATURE_AP_STA;
+#endif
+       feature_set |= SLSI_WIFI_HAL_FEATURE_CONFIG_NDO;
+#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION
+       feature_set |= SLSI_WIFI_HAL_FEATURE_SCAN_RAND;
+#endif
+       feature_set |= SLSI_WIFI_HAL_FEATURE_LOW_LATENCY;
+       feature_set |= SLSI_WIFI_HAL_FEATURE_P2P_RAND_MAC;
+
        ret = slsi_vendor_cmd_reply(wiphy, &feature_set, sizeof(feature_set));
 
        return ret;
@@ -3027,13 +3077,17 @@ void slsi_rx_range_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_
        u32 tmac = fapi_get_u32(skb, u.mlme_range_ind.spare_3);
        int data_len = fapi_get_datalen(skb);
        u8                *ip_ptr, *start_ptr;
-       u16 tx_data, rx_data;
+       u16 tx_data = 0, rx_data = 0;
        struct sk_buff *nl_skb;
        int res = 0;
        struct nlattr *nlattr_nested;
        struct timespec          ts;
        u64 tkernel;
        u8 rep_cnt = 0;
+       __le16 *le16_ptr = NULL;
+       __le32 *le32_ptr = NULL;
+       u16 value;
+       u32 temp_value;
 
        SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
@@ -3069,41 +3123,78 @@ void slsi_rx_range_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_
                ip_ptr += 7;             /*skip first 7 bytes for fapi_ie_generic */
                res |= nla_put(nl_skb, SLSI_RTT_EVENT_ATTR_ADDR, ETH_ALEN, ip_ptr);
                ip_ptr += 6;
-               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_BURST_NUM, *ip_ptr);
+
+               le16_ptr = (__le16 *)&ip_ptr[i];
+               value = le16_to_cpu(*le16_ptr);
+               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_BURST_NUM, value);
                ip_ptr += 2;
+
                res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_MEASUREMENT_NUM, *ip_ptr++);
                res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_SUCCESS_NUM, *ip_ptr++);
                res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_NUM_PER_BURST_PEER, *ip_ptr++);
-               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_STATUS, *ip_ptr);
+
+               le16_ptr = (__le16 *)&ip_ptr[i];
+               value = le16_to_cpu(*le16_ptr);
+               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_STATUS, value);
                ip_ptr += 2;
                res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_RETRY_AFTER_DURATION, *ip_ptr++);
-               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_TYPE, *ip_ptr);
+
+               le16_ptr = (__le16 *)&ip_ptr[i];
+               value = le16_to_cpu(*le16_ptr);
+               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_TYPE, value);
                ip_ptr += 2;
-               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RSSI, *ip_ptr);
+
+               le16_ptr = (__le16 *)&ip_ptr[i];
+               value = le16_to_cpu(*le16_ptr);
+               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RSSI, value);
                ip_ptr += 2;
-               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RSSI_SPREAD, *ip_ptr);
+
+               le16_ptr = (__le16 *)&ip_ptr[i];
+               value = le16_to_cpu(*le16_ptr);
+               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RSSI_SPREAD, value);
                ip_ptr += 2;
+
                memcpy(&tx_data, ip_ptr, 2);
                res = slsi_tx_rate_calc(nl_skb, tx_data, res, 1);
                ip_ptr += 2;
+
                memcpy(&rx_data, ip_ptr, 2);
                res = slsi_tx_rate_calc(nl_skb, rx_data, res, 0);
                ip_ptr += 2;
-               res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_RTT, *ip_ptr);
+
+               le32_ptr = (__le32 *)&ip_ptr[i];
+               temp_value = le32_to_cpu(*le32_ptr);
+               res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_RTT, temp_value);
                ip_ptr += 4;
-               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RTT_SD, *ip_ptr);
+
+               le16_ptr = (__le16 *)&ip_ptr[i];
+               value = le16_to_cpu(*le16_ptr);
+               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RTT_SD, value);
                ip_ptr += 2;
-               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RTT_SPREAD, *ip_ptr);
+
+               le16_ptr = (__le16 *)&ip_ptr[i];
+               value = le16_to_cpu(*le16_ptr);
+               res |= nla_put_u16(nl_skb, SLSI_RTT_EVENT_ATTR_RTT_SPREAD, value);
                ip_ptr += 2;
+
                get_monotonic_boottime(&ts);
                tkernel = (u64)TIMESPEC_TO_US(ts);
-               tm = *ip_ptr;
+               le32_ptr = (__le32 *)&ip_ptr[i];
+               temp_value = le32_to_cpu(*le32_ptr);
+               tm = temp_value;
                res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_TIMESTAMP_US, tkernel - (tmac - tm));
                ip_ptr += 4;
-               res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_DISTANCE_MM, *ip_ptr);
+
+               le32_ptr = (__le32 *)&ip_ptr[i];
+               temp_value = le32_to_cpu(*le32_ptr);
+               res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_DISTANCE_MM, temp_value);
                ip_ptr += 4;
-               res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_DISTANCE_SD_MM, *ip_ptr);
+
+               le32_ptr = (__le32 *)&ip_ptr[i];
+               temp_value = le32_to_cpu(*le32_ptr);
+               res |= nla_put_u32(nl_skb, SLSI_RTT_EVENT_ATTR_DISTANCE_SD_MM, temp_value);
                ip_ptr += 4;
+
                res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_BURST_DURATION_MSN, *ip_ptr++);
                res |= nla_put_u8(nl_skb, SLSI_RTT_EVENT_ATTR_NEGOTIATED_BURST_NUM, *ip_ptr++);
                for (rep_cnt = 0; rep_cnt < 2; rep_cnt++) {
@@ -4639,7 +4730,10 @@ static const struct  nl80211_vendor_cmd_info slsi_vendor_events[] = {
        { OUI_SAMSUNG, SLSI_NL80211_VENDOR_ACS_EVENT},
        { OUI_SAMSUNG, SLSI_NL80211_VENDOR_FORWARD_BEACON},
        { OUI_SAMSUNG, SLSI_NL80211_VENDOR_FORWARD_BEACON_ABORT},
-       { OUI_GOOGLE,  SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS}
+       { OUI_GOOGLE,  SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS},
+       { OUI_GOOGLE,  SLSI_NAN_EVENT_NDP_REQ},
+       { OUI_GOOGLE,  SLSI_NAN_EVENT_NDP_CFM},
+       { OUI_GOOGLE,  SLSI_NAN_EVENT_NDP_END}
 };
 
 static const struct wiphy_vendor_command     slsi_vendor_cmd[] = {
@@ -4992,6 +5086,47 @@ static const struct wiphy_vendor_command     slsi_vendor_cmd[] = {
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
                .doit = slsi_nan_get_capabilities
        },
+
+       {
+               {
+                       .vendor_id = OUI_GOOGLE,
+                       .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_DATA_INTERFACE_CREATE
+               },
+               .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+               .doit = slsi_nan_data_iface_create
+       },
+       {
+               {
+                       .vendor_id = OUI_GOOGLE,
+                       .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_DATA_INTERFACE_DELETE
+               },
+               .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+               .doit = slsi_nan_data_iface_delete
+       },
+       {
+               {
+                       .vendor_id = OUI_GOOGLE,
+                       .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_DATA_REQUEST_INITIATOR
+               },
+               .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+               .doit = slsi_nan_ndp_initiate
+       },
+       {
+               {
+                       .vendor_id = OUI_GOOGLE,
+                       .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_DATA_INDICATION_RESPONSE
+               },
+               .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+               .doit = slsi_nan_ndp_respond
+       },
+       {
+               {
+                       .vendor_id = OUI_GOOGLE,
+                       .subcmd = SLSI_NL80211_VENDOR_SUBCMD_NAN_DATA_END
+               },
+               .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+               .doit = slsi_nan_ndp_end
+       },
 #endif
        {
                {
index b33464f6a9c706d690f2018ca991cb9ac1d13ad9..2217ae50443361e48331bb6ef65de99eb01e0ec0 100755 (executable)
 #define SLSI_WIFI_HAL_FEATURE_HAL_EPNO           0x040000      /* WiFi PNO enhanced */
 #define SLSI_WIFI_HAL_FEATURE_RSSI_MONITOR       0x080000      /* RSSI Monitor */
 #define SLSI_WIFI_HAL_FEATURE_MKEEP_ALIVE        0x100000      /* WiFi mkeep_alive */
+#define SLSI_WIFI_HAL_FEATURE_CONFIG_NDO         0x200000      /* ND offload */
 #define SLSI_WIFI_HAL_FEATURE_CONTROL_ROAMING    0x800000      /* Enable/Disable firmware roaming macro */
+#define SLSI_WIFI_HAL_FEATURE_SCAN_RAND          0x2000000     /* Random MAC & Probe seq */
+#define SLSI_WIFI_HAL_FEATURE_LOW_LATENCY        0x40000000    /* Low Latency modes */
+#define SLSI_WIFI_HAL_FEATURE_P2P_RAND_MAC       0x80000000    /* Random P2P MAC */
 
 enum slsi_wifi_attr {
        SLSI_NL_ATTRIBUTE_ND_OFFLOAD_VALUE = 0,
@@ -339,6 +343,11 @@ enum slsi_hal_vendor_subcmds {
        SLSI_NL80211_VENDOR_SUBCMD_NAN_TXFOLLOWUP,
        SLSI_NL80211_VENDOR_SUBCMD_NAN_CONFIG,
        SLSI_NL80211_VENDOR_SUBCMD_NAN_CAPABILITIES,
+       SLSI_NL80211_VENDOR_SUBCMD_NAN_DATA_INTERFACE_CREATE,
+       SLSI_NL80211_VENDOR_SUBCMD_NAN_DATA_INTERFACE_DELETE,
+       SLSI_NL80211_VENDOR_SUBCMD_NAN_DATA_REQUEST_INITIATOR,
+       SLSI_NL80211_VENDOR_SUBCMD_NAN_DATA_INDICATION_RESPONSE,
+       SLSI_NL80211_VENDOR_SUBCMD_NAN_DATA_END,
        SLSI_NL80211_VENDOR_SUBCMD_RTT_GET_CAPABILITIES = SLSI_NL80211_RTT_SUBCMD_RANGE_START,
        SLSI_NL80211_VENDOR_SUBCMD_RTT_RANGE_START,
        SLSI_NL80211_VENDOR_SUBCMD_RTT_RANGE_CANCEL,
@@ -368,7 +377,7 @@ enum slsi_vendor_event_values {
        SLSI_NL80211_VENDOR_HANGED_EVENT,
        SLSI_NL80211_EPNO_EVENT,
        SLSI_NL80211_HOTSPOT_MATCH,
-       SLSI_NL80211_RSSI_REPORT_EVENT,
+       SLSI_NL80211_RSSI_REPORT_EVENT = 10,
        SLSI_NL80211_LOGGER_RING_EVENT,
        SLSI_NL80211_LOGGER_FW_DUMP_EVENT,
        SLSI_NL80211_NAN_RESPONSE_EVENT,
@@ -378,13 +387,16 @@ enum slsi_vendor_event_values {
        SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT,
        SLSI_NL80211_NAN_FOLLOWUP_EVENT,
        SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT,
-       SLSI_NL80211_NAN_DISABLED_EVENT,
+       SLSI_NL80211_NAN_DISABLED_EVENT = 20,
        SLSI_NL80211_RTT_RESULT_EVENT,
        SLSI_NL80211_RTT_COMPLETE_EVENT,
        SLSI_NL80211_VENDOR_ACS_EVENT,
        SLSI_NL80211_VENDOR_FORWARD_BEACON,
        SLSI_NL80211_VENDOR_FORWARD_BEACON_ABORT,
        SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS,
+       SLSI_NAN_EVENT_NDP_REQ,
+       SLSI_NAN_EVENT_NDP_CFM,
+       SLSI_NAN_EVENT_NDP_END
 };
 
 enum slsi_lls_interface_mode {
@@ -956,12 +968,11 @@ struct slsi_rtt_config {
        u16 LCR_request;              /* 1: request LCR, 0: do not request LCR */
 };
 
-#define MAX_CHAN_VALUE_ACS 39  /*Max number of supported channel is 39*/
 #define MAX_24G_CHANNELS 14  /*Max number of 2.4G channels*/
 #define MAX_5G_CHANNELS 25  /*Max number of 5G channels*/
+#define MAX_CHAN_VALUE_ACS MAX_24G_CHANNELS + MAX_5G_CHANNELS
 #define MAX_AP_THRESHOLD 10  /*Max AP threshold in ACS*/
 
-
 struct slsi_acs_chan_info {
        u16 chan;
        u8 num_ap;
index cf538980a0da443b0d6fcdf06adce319d58e407d..b91fa9705789d7a79cba3fe5c16c3620c2e4dc5c 100755 (executable)
@@ -12,6 +12,8 @@
 struct net_device *slsi_nan_get_netdev(struct slsi_dev *sdev)
 {
 #if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4
+       if (sdev->recovery_status)
+               return slsi_get_netdev_locked(sdev, SLSI_NET_INDEX_NAN);
        return slsi_get_netdev(sdev, SLSI_NET_INDEX_NAN);
 #else
        return NULL;
@@ -31,22 +33,132 @@ static int slsi_nan_get_new_id(u32 id_map, int max_ids)
 
 static int slsi_nan_get_new_publish_id(struct netdev_vif *ndev_vif)
 {
-       return slsi_nan_get_new_id(ndev_vif->nan.publish_id_map, SLSI_NAN_MAX_PUBLISH_ID);
+       WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
+       return slsi_nan_get_new_id(ndev_vif->nan.service_id_map, SLSI_NAN_MAX_SERVICE_ID);
 }
 
 static int slsi_nan_get_new_subscribe_id(struct netdev_vif *ndev_vif)
 {
-       return slsi_nan_get_new_id(ndev_vif->nan.subscribe_id_map, SLSI_NAN_MAX_SUBSCRIBE_ID);
+       WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
+       return slsi_nan_get_new_id(ndev_vif->nan.service_id_map, SLSI_NAN_MAX_SERVICE_ID);
 }
 
 static bool slsi_nan_is_publish_id_active(struct netdev_vif *ndev_vif, u32 id)
 {
-       return ndev_vif->nan.publish_id_map & BIT(id);
+       WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
+       return ndev_vif->nan.service_id_map & BIT(id);
 }
 
 static bool slsi_nan_is_subscribe_id_active(struct netdev_vif *ndev_vif, u32 id)
 {
-       return ndev_vif->nan.subscribe_id_map & BIT(id);
+       WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
+       return ndev_vif->nan.service_id_map & BIT(id);
+}
+
+static int slsi_nan_get_new_ndp_id(struct netdev_vif *ndev_vif)
+{
+       WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
+       return slsi_nan_get_new_id(ndev_vif->nan.ndp_id_map, SLSI_NAN_MAX_NDP_INSTANCES);
+}
+
+static void slsi_nan_pre_check(struct slsi_dev *sdev, struct net_device *dev, int *ret, int *reply_status)
+{
+       *ret = WIFI_HAL_SUCCESS;
+       *reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+       if (!dev) {
+               SLSI_ERR(sdev, "No NAN interface\n");
+               *ret = -WIFI_HAL_ERROR_NOT_SUPPORTED;
+               *reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+       }
+
+       if (!slsi_dev_nan_supported(sdev)) {
+               SLSI_ERR(sdev, "NAN not allowed(mib:%d)\n", sdev->nan_enabled);
+               *ret = WIFI_HAL_ERROR_NOT_SUPPORTED;
+               *reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+       }
+}
+
+int slsi_nan_ndp_new_entry(struct slsi_dev *sdev, struct net_device *dev, u32 ndp_id,
+                          u16 ndl_vif_id, u8 *local_ndi, u8 *peer_nmi)
+{
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+       u16 ndl_id;
+
+       WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
+
+       if (ndl_vif_id < SLSI_NAN_DATA_IFINDEX_START ||
+           ndl_vif_id >= SLSI_NAN_DATA_IFINDEX_START + SLSI_NAN_MAX_NDP_INSTANCES) {
+               SLSI_ERR(sdev, "Invalid ndl_vif:%d\n", ndl_vif_id);
+               return 1;
+       }
+
+       if (ndp_id == 0 || ndp_id > SLSI_NAN_MAX_NDP_INSTANCES) {
+               SLSI_ERR(sdev, "Invalid ndp:%d\n", ndp_id);
+               return 1;
+       }
+
+       ndl_id = ndl_vif_id - SLSI_NAN_DATA_IFINDEX_START;
+       if (ndev_vif->nan.ndl_list[ndl_id].ndp_count < 0 ||
+           ndev_vif->nan.ndl_list[ndl_id].ndp_count > SLSI_NAN_MAX_NDP_INSTANCES) {
+               SLSI_WARN(sdev, "improper ndp count(%d) for vif_id(%d)\n",
+                         ndev_vif->nan.ndl_list[ndl_id].ndp_count, ndl_vif_id);
+       }
+
+       ndev_vif->nan.ndp_id_map |= (u32)BIT(ndp_id);
+       if (peer_nmi)
+               ether_addr_copy(ndev_vif->nan.ndl_list[ndl_id].peer_nmi, peer_nmi);
+       ndev_vif->nan.ndl_list[ndl_id].ndp_count++;
+       if (local_ndi)
+               ether_addr_copy(ndev_vif->nan.ndp_ndi[ndp_id - 1], local_ndi);
+       ndev_vif->nan.ndp_id2ndl_vif[ndp_id - 1] = ndl_vif_id;
+       ndev_vif->nan.ndp_state[ndp_id - 1] = ndp_slot_status_in_use;
+       return 0;
+}
+
+void slsi_nan_ndp_del_entry(struct slsi_dev *sdev, struct net_device *dev, u32 ndp_id)
+{
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+       u16 ndl_vif_id, ndl_id;
+
+       WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
+
+       if (ndp_id == 0 || ndp_id > SLSI_NAN_MAX_NDP_INSTANCES) {
+               SLSI_WARN(sdev, "Invalid ndp:%d\n", ndp_id);
+               return;
+       }
+
+       ndl_vif_id = ndev_vif->nan.ndp_id2ndl_vif[ndp_id - 1];
+       if (ndl_vif_id < SLSI_NAN_DATA_IFINDEX_START ||
+           ndl_vif_id >= SLSI_NAN_DATA_IFINDEX_START + SLSI_NAN_MAX_NDP_INSTANCES) {
+               SLSI_WARN(sdev, "Invalid ndl_vif:%d\n", ndl_vif_id);
+               return;
+       }
+
+       ndl_id = ndl_vif_id - SLSI_NAN_DATA_IFINDEX_START;
+       ndev_vif->nan.ndp_id_map &= ~(u32)BIT(ndp_id);
+       ndev_vif->nan.ndl_list[ndl_id].ndp_count--;
+       if (ndev_vif->nan.ndl_list[ndl_id].ndp_count == 0)
+               slsi_eth_zero_addr(ndev_vif->nan.ndl_list[ndl_id].peer_nmi);
+       ndev_vif->nan.ndp_id2ndl_vif[ndp_id - 1] = 0;
+       slsi_eth_zero_addr(ndev_vif->nan.ndp_ndi[ndp_id - 1]);
+       if (ndev_vif->nan.ndl_list[ndl_id].ndp_count < 0)
+               SLSI_WARN(sdev, "ndp_count is negative %d for ndl idx %d\n",
+                         ndev_vif->nan.ndl_list[ndl_id].ndp_count, ndl_id);
+       ndev_vif->nan.ndp_state[ndp_id - 1] = ndp_slot_status_free;
+}
+
+u16 slsi_nan_ndp_get_ndl_vif_id(u8 *peer_mni, struct slsi_nan_ndl_info *ndl_list)
+{
+       u16 i, free_idx = SLSI_NAN_MAX_NDP_INSTANCES + SLSI_NAN_DATA_IFINDEX_START;
+
+       for (i = 0; i < SLSI_NAN_MAX_NDP_INSTANCES; i++) {
+               if (ether_addr_equal(peer_mni, ndl_list[i].peer_nmi))
+                       return i + SLSI_NAN_DATA_IFINDEX_START;
+               if (free_idx == SLSI_NAN_MAX_NDP_INSTANCES + SLSI_NAN_DATA_IFINDEX_START &&
+                   ndl_list[i].ndp_count == 0)
+                       free_idx = i + SLSI_NAN_DATA_IFINDEX_START;
+       }
+       return free_idx;
 }
 
 void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr)
@@ -59,7 +171,7 @@ void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr)
 }
 
 static void slsi_vendor_nan_command_reply(struct wiphy *wiphy, u32 status, u32 error, u32 response_type,
-                                         u16 publish_subscribe_id, struct slsi_hal_nan_capabilities *capabilities)
+                                         u16 id, struct slsi_hal_nan_capabilities *capabilities, u16 req_id)
 {
        int reply_len;
        struct sk_buff  *reply;
@@ -75,6 +187,7 @@ static void slsi_vendor_nan_command_reply(struct wiphy *wiphy, u32 status, u32 e
        nla_put_u32(reply, NAN_REPLY_ATTR_STATUS_TYPE, status);
        nla_put_u32(reply, NAN_REPLY_ATTR_VALUE, error);
        nla_put_u32(reply, NAN_REPLY_ATTR_RESPONSE_TYPE, response_type);
+       nla_put_u16(reply, NAN_REPLY_ATTR_HAL_TRANSACTION_ID, req_id);
 
        if (capabilities) {
                nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER,
@@ -92,8 +205,11 @@ static void slsi_vendor_nan_command_reply(struct wiphy *wiphy, u32 status, u32 e
                nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES, capabilities->max_ndi_interfaces);
                nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS, capabilities->max_ndp_sessions);
                nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN, capabilities->max_app_info_len);
-       } else if (publish_subscribe_id) {
-               nla_put_u16(reply, NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE, publish_subscribe_id);
+       } else if (id) {
+               if (response_type < NAN_DP_INTERFACE_CREATE)
+                       nla_put_u16(reply, NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE, id);
+               else
+                       nla_put_u16(reply, NAN_REPLY_ATTR_NDP_INSTANCE_ID, id);
        }
 
        if (cfg80211_vendor_cmd_reply(reply))
@@ -182,6 +298,8 @@ static int slsi_nan_get_security_info_nl(struct slsi_dev *sdev, struct slsi_nan_
                sec_info->scid_len = nla_get_u32(iter);
                break;
        case NAN_REQ_ATTR_SCID:
+               if (sec_info->scid_len > sizeof(sec_info->scid))
+                       sec_info->scid_len = sizeof(sec_info->scid);
                memcpy(sec_info->scid, nla_data(iter), sec_info->scid_len);
                break;
        default:
@@ -216,6 +334,8 @@ static int slsi_nan_get_range_resp_cfg_nl(struct slsi_dev *sdev, struct slsi_nan
        return 0;
 }
 
+/* NAN HAL REQUESTS */
+
 static int slsi_nan_enable_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_enable_req *hal_req,
                                         const void *data, int len)
 {
@@ -382,9 +502,12 @@ static int slsi_nan_enable_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_
                        hal_req->disc_mac_addr_rand_interval_sec = nla_get_u32(iter);
                        break;
 
+               case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+                       hal_req->transaction_id = nla_get_u16(iter);
+                       break;
+
                default:
                        SLSI_ERR(sdev, "Unexpected NAN enable attribute TYPE:%d\n", type);
-                       return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
                }
        }
        return SLSI_HAL_NAN_STATUS_SUCCESS;
@@ -401,19 +524,10 @@ int slsi_nan_enable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *
        u8 broadcast_mac[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
        u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
 
-       if (!dev) {
-               SLSI_ERR(sdev, "No NAN interface\n");
-               ret = -ENOTSUPP;
-               reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
-               goto exit;
-       }
-
-       if (!slsi_dev_nan_supported(sdev)) {
-               SLSI_ERR(sdev, "NAN not allowed(mib:%d)\n", sdev->nan_enabled);
-               ret = WIFI_HAL_ERROR_NOT_SUPPORTED;
-               reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+       hal_req.transaction_id = 0;
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
                goto exit;
-       }
 
        ndev_vif = netdev_priv(dev);
 
@@ -431,6 +545,8 @@ int slsi_nan_enable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *
        }
        ndev_vif->vif_type = FAPI_VIFTYPE_NAN;
 
+       slsi_net_randomize_nmi_ndi(sdev);
+
        if (hal_req.config_intf_addr)
                ether_addr_copy(nan_vif_mac_address, hal_req.intf_addr_val);
        else
@@ -447,17 +563,32 @@ int slsi_nan_enable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *
                        reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
                        slsi_mlme_del_vif(sdev, dev);
                        ndev_vif->activated = false;
-                       ndev_vif->nan.subscribe_id_map = 0;
-                       ndev_vif->nan.publish_id_map = 0;
+                       ndev_vif->nan.service_id_map = 0;
                } else {
                        slsi_vif_activated(sdev, dev);
+                       ndev_vif->nan.master_pref_value = hal_req.master_pref;
+                       ether_addr_copy(ndev_vif->nan.local_nmi, nan_vif_mac_address);
+                       ndev_vif->nan.state = 1;
+                       if (hal_req.config_24g_channel)
+                               ndev_vif->nan.operating_channel[0] = hal_req.channel_24g_val;
+                       if (hal_req.config_5g_channel)
+                               ndev_vif->nan.operating_channel[1] = hal_req.channel_5g_val;
+                       if (hal_req.config_hop_count_limit)
+                               ndev_vif->nan.hopcount = hal_req.hop_count_limit_val;
+                       slsi_eth_zero_addr(ndev_vif->nan.cluster_id);
+                       ndev_vif->nan.random_mac_interval_sec = hal_req.disc_mac_addr_rand_interval_sec;
+                       SLSI_INFO(sdev,
+                                 "trans_id:%d master_pref:%d 2gChan:%d 5gChan:%d mac_random_interval:%d\n",
+                                 hal_req.transaction_id, hal_req.master_pref, hal_req.channel_24g_val,
+                                 hal_req.channel_5g_val, hal_req.disc_mac_addr_rand_interval_sec);
                }
        }
+       ether_addr_copy(ndev_vif->nan.local_nmi, nan_vif_mac_address);
 
 exit_with_mutex:
        SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
 exit:
-       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_ENABLED, 0, NULL);
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_ENABLED, 0, NULL, hal_req.transaction_id);
        return ret;
 }
 
@@ -465,25 +596,52 @@ int slsi_nan_disable(struct wiphy *wiphy, struct wireless_dev *wdev, const void
 {
        struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
        struct net_device *dev = slsi_nan_get_netdev(sdev);
-       struct netdev_vif *ndev_vif;
+       struct net_device *data_dev;
+       struct netdev_vif *ndev_vif, *data_ndev_vif;
+       u8 disable_cluster_merge, i;
+       int type, tmp;
+       const struct nlattr *iter;
+       u16 transaction_id = 0;
+
+       nla_for_each_attr(iter, data, len, tmp) {
+               type = nla_type(iter);
+               switch (type) {
+               case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+                       transaction_id = nla_get_u16(iter);
+                       break;
+               default:
+                       break;
+               }
+       }
 
+       SLSI_INFO(sdev, "transaction_id:%d\n", transaction_id);
        if (dev) {
                ndev_vif = netdev_priv(dev);
                SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
                if (ndev_vif->activated) {
                        slsi_mlme_del_vif(sdev, dev);
                        ndev_vif->activated = false;
-                       ndev_vif->nan.subscribe_id_map = 0;
-                       ndev_vif->nan.publish_id_map = 0;
                } else {
                        SLSI_WARN(sdev, "NAN FWif not active!!");
                }
+               for (i = SLSI_NAN_DATA_IFINDEX_START; i < CONFIG_SCSC_WLAN_MAX_INTERFACES + 1; i++) {
+                       data_dev = slsi_get_netdev(sdev, i);
+                       if (data_dev) {
+                               data_ndev_vif = netdev_priv(data_dev);
+                               SLSI_MUTEX_LOCK(data_ndev_vif->vif_mutex);
+                               slsi_vif_cleanup(sdev, data_dev, true);
+                               SLSI_MUTEX_UNLOCK(data_ndev_vif->vif_mutex);
+                       }
+               }
+               disable_cluster_merge = ndev_vif->nan.disable_cluster_merge;
+               memset(&ndev_vif->nan, 0, sizeof(ndev_vif->nan));
+               ndev_vif->nan.disable_cluster_merge = disable_cluster_merge;
                SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
        } else {
                SLSI_WARN(sdev, "No NAN interface!!");
        }
 
-       slsi_vendor_nan_command_reply(wiphy, SLSI_HAL_NAN_STATUS_SUCCESS, 0, NAN_RESPONSE_DISABLED, 0, NULL);
+       slsi_vendor_nan_command_reply(wiphy, SLSI_HAL_NAN_STATUS_SUCCESS, 0, NAN_RESPONSE_DISABLED, 0, NULL, transaction_id);
 
        return 0;
 }
@@ -582,6 +740,10 @@ static int slsi_nan_publish_get_nl_params(struct slsi_dev *sdev, struct slsi_hal
                        hal_req->ranging_auto_response = nla_get_u8(iter);
                        break;
 
+               case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+                       hal_req->transaction_id = nla_get_u16(iter);
+                       break;
+
                default:
                        r = slsi_nan_get_sdea_params_nl(sdev, &hal_req->sdea_params, iter, type);
                        if (r)
@@ -608,13 +770,11 @@ int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void
        int ret;
        u32 reply_status;
        u32 publish_id = 0;
+       u16 transaction_id = 0;
 
-       if (!dev) {
-               SLSI_ERR(sdev, "NAN netif not active!!\n");
-               ret = -EINVAL;
-               reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
                goto exit;
-       }
 
        hal_req = kmalloc(sizeof(*hal_req), GFP_KERNEL);
        if (!hal_req) {
@@ -631,6 +791,7 @@ int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void
                ret = -EINVAL;
                goto exit;
        }
+       transaction_id = hal_req->transaction_id;
 
        SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
 
@@ -645,7 +806,7 @@ int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void
                hal_req->publish_id = slsi_nan_get_new_publish_id(ndev_vif);
        } else if (!slsi_nan_is_publish_id_active(ndev_vif, hal_req->publish_id)) {
                SLSI_WARN(sdev, "Publish id %d not found. map:%x\n", hal_req->publish_id,
-                         ndev_vif->nan.publish_id_map);
+                         ndev_vif->nan.service_id_map);
                reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
                ret = -EINVAL;
                goto exit_with_lock;
@@ -653,21 +814,26 @@ int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void
 
        if (hal_req->publish_id) {
                ret = slsi_mlme_nan_publish(sdev, dev, hal_req, hal_req->publish_id);
-               if (ret)
+               if (ret) {
                        reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
-               else
+               } else {
                        publish_id = hal_req->publish_id;
+                       SLSI_INFO(sdev,
+                                 "trans_id:%d, publish_id:%d type:%d rec_ind_cfg:0x%x\n",
+                                 hal_req->transaction_id, hal_req->publish_id, hal_req->publish_type,
+                                 hal_req->recv_indication_cfg);
+               }
        } else {
                reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
                SLSI_WARN(sdev, "Too Many concurrent PUBLISH REQ(map:%x)\n",
-                         ndev_vif->nan.publish_id_map);
+                         ndev_vif->nan.service_id_map);
                ret = -ENOTSUPP;
        }
 exit_with_lock:
        SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
        kfree(hal_req);
 exit:
-       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH, publish_id, NULL);
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH, publish_id, NULL, transaction_id);
        return ret;
 }
 
@@ -678,16 +844,13 @@ int slsi_nan_publish_cancel(struct wiphy *wiphy, struct wireless_dev *wdev,
        struct net_device *dev = slsi_nan_get_netdev(sdev);
        struct netdev_vif *ndev_vif;
        int type, tmp, ret = 0;
-       u16 publish_id = 0;
+       u16 publish_id = 0, transaction_id = 0;
        const struct nlattr *iter;
        u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
 
-       if (!dev) {
-               SLSI_ERR(sdev, "NAN netif not active!!");
-               reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
-               ret = -EINVAL;
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
                goto exit;
-       }
 
        ndev_vif = netdev_priv(dev);
        nla_for_each_attr(iter, data, len, tmp) {
@@ -696,11 +859,15 @@ int slsi_nan_publish_cancel(struct wiphy *wiphy, struct wireless_dev *wdev,
                case NAN_REQ_ATTR_PUBLISH_ID:
                        publish_id = nla_get_u16(iter);
                        break;
+               case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+                       transaction_id = nla_get_u16(iter);
+                       break;
+
                default:
                        SLSI_ERR(sdev, "Unexpected NAN publishcancel attribute TYPE:%d\n", type);
                }
        }
-
+       SLSI_INFO(sdev, "transaction_id:%d publish_id:%d\n", transaction_id, publish_id);
        SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
        if (!ndev_vif->activated) {
                reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
@@ -710,7 +877,7 @@ int slsi_nan_publish_cancel(struct wiphy *wiphy, struct wireless_dev *wdev,
        if (!publish_id || !slsi_nan_is_publish_id_active(ndev_vif, publish_id)) {
                reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
                SLSI_WARN(sdev, "Publish_id(%d) not active. map:%x\n",
-                         publish_id, ndev_vif->nan.publish_id_map);
+                         publish_id, ndev_vif->nan.service_id_map);
        } else {
                ret = slsi_mlme_nan_publish(sdev, dev, NULL, publish_id);
                if (ret)
@@ -719,7 +886,7 @@ int slsi_nan_publish_cancel(struct wiphy *wiphy, struct wireless_dev *wdev,
 exit_with_lock:
        SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
 exit:
-       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH_CANCEL, publish_id, NULL);
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH_CANCEL, publish_id, NULL, transaction_id);
        return ret;
 }
 
@@ -838,6 +1005,10 @@ static int slsi_nan_subscribe_get_nl_params(struct slsi_dev *sdev, struct slsi_h
                        hal_req->ranging_auto_response = nla_get_u8(iter);
                        break;
 
+               case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+                       hal_req->transaction_id = nla_get_u16(iter);
+                       break;
+
                default:
                        r = slsi_nan_get_sdea_params_nl(sdev, &hal_req->sdea_params, iter, type);
                        if (r)
@@ -864,13 +1035,11 @@ int slsi_nan_subscribe(struct wiphy *wiphy, struct wireless_dev *wdev, const voi
        int ret;
        u32 reply_status;
        u32 subscribe_id = 0;
+       u16 transaction_id = 0;
 
-       if (!dev) {
-               SLSI_ERR(sdev, "NAN netif not active!!\n");
-               reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
-               ret = -EINVAL;
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
                goto exit;
-       }
 
        hal_req = kmalloc(sizeof(*hal_req), GFP_KERNEL);
        if (!hal_req) {
@@ -887,7 +1056,7 @@ int slsi_nan_subscribe(struct wiphy *wiphy, struct wireless_dev *wdev, const voi
                ret = -EINVAL;
                goto exit;
        }
-
+       transaction_id = hal_req->transaction_id;
        SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
        if (!ndev_vif->activated) {
                SLSI_WARN(sdev, "NAN vif not activated\n");
@@ -900,23 +1069,26 @@ int slsi_nan_subscribe(struct wiphy *wiphy, struct wireless_dev *wdev, const voi
                hal_req->subscribe_id = slsi_nan_get_new_subscribe_id(ndev_vif);
        } else if (!slsi_nan_is_subscribe_id_active(ndev_vif, hal_req->subscribe_id)) {
                SLSI_WARN(sdev, "Subscribe id %d not found. map:%x\n", hal_req->subscribe_id,
-                         ndev_vif->nan.subscribe_id_map);
+                         ndev_vif->nan.service_id_map);
                reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
                ret = -EINVAL;
                goto exit_with_lock;
        }
 
        ret = slsi_mlme_nan_subscribe(sdev, dev, hal_req, hal_req->subscribe_id);
-       if (ret)
+       if (ret) {
                reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
-       else
+       } else {
+               SLSI_INFO(sdev, "trans_id:%d subscribe_id:%d type:%d\n",
+                         hal_req->transaction_id, hal_req->subscribe_id, hal_req->subscribe_type);
                subscribe_id = hal_req->subscribe_id;
+       }
 
 exit_with_lock:
        SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
        kfree(hal_req);
 exit:
-       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE, subscribe_id, NULL);
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE, subscribe_id, NULL, transaction_id);
        return ret;
 }
 
@@ -926,16 +1098,13 @@ int slsi_nan_subscribe_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, co
        struct net_device *dev = slsi_nan_get_netdev(sdev);
        struct netdev_vif *ndev_vif;
        int type, tmp, ret = WIFI_HAL_ERROR_UNKNOWN;
-       u16 subscribe_id = 0;
+       u16 subscribe_id = 0, transaction_id = 0;
        const struct nlattr *iter;
        u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
 
-       if (!dev) {
-               SLSI_ERR(sdev, "NAN netif not active!!");
-               reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
-               ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
                goto exit;
-       }
 
        ndev_vif = netdev_priv(dev);
 
@@ -945,18 +1114,21 @@ int slsi_nan_subscribe_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, co
                case NAN_REQ_ATTR_SUBSCRIBE_ID:
                        subscribe_id = nla_get_u16(iter);
                        break;
+               case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+                       transaction_id = nla_get_u16(iter);
+                       break;
                default:
                        SLSI_ERR(sdev, "Unexpected NAN subscribecancel attribute TYPE:%d\n", type);
                        reply_status = SLSI_HAL_NAN_STATUS_INVALID_PARAM;
                        goto exit;
                }
        }
-
+       SLSI_INFO(sdev, "trans_id:%d subscribe_id:%d\n", transaction_id, subscribe_id);
        SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
        if (ndev_vif->activated) {
                if (!subscribe_id || !slsi_nan_is_subscribe_id_active(ndev_vif, subscribe_id)) {
                        SLSI_WARN(sdev, "subscribe_id(%d) not active. map:%x\n",
-                                 subscribe_id, ndev_vif->nan.subscribe_id_map);
+                                 subscribe_id, ndev_vif->nan.service_id_map);
                        reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
                } else {
                        ret = slsi_mlme_nan_subscribe(sdev, dev, NULL, subscribe_id);
@@ -970,7 +1142,7 @@ int slsi_nan_subscribe_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, co
        }
        SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
 exit:
-       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE_CANCEL, subscribe_id, NULL);
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE_CANCEL, subscribe_id, NULL, transaction_id);
        return ret;
 }
 
@@ -1025,6 +1197,10 @@ static int slsi_nan_followup_get_nl_params(struct slsi_dev *sdev, struct slsi_ha
                               hal_req->sdea_service_specific_info_len);
                        break;
 
+               case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+                       hal_req->transaction_id = nla_get_u16(iter);
+                       break;
+
                default:
                        SLSI_ERR(sdev, "Unexpected NAN followup attribute TYPE:%d\n", type);
                        return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
@@ -1039,15 +1215,13 @@ int slsi_nan_transmit_followup(struct wiphy *wiphy, struct wireless_dev *wdev, c
        struct net_device *dev = slsi_nan_get_netdev(sdev);
        struct netdev_vif *ndev_vif;
        struct slsi_hal_nan_transmit_followup_req hal_req;
-       int ret;
+       int ret = 0;
        u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
 
-       if (!dev) {
-               SLSI_ERR(sdev, "NAN netif not active!!");
-               ret = -EINVAL;
-               reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+       hal_req.transaction_id = 0;
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
                goto exit;
-       }
 
        ndev_vif = netdev_priv(dev);
        reply_status = slsi_nan_followup_get_nl_params(sdev, &hal_req, data, len);
@@ -1068,20 +1242,31 @@ int slsi_nan_transmit_followup(struct wiphy *wiphy, struct wireless_dev *wdev, c
            !(slsi_nan_is_subscribe_id_active(ndev_vif, hal_req.publish_subscribe_id) ||
            slsi_nan_is_publish_id_active(ndev_vif, hal_req.publish_subscribe_id))) {
                SLSI_WARN(sdev, "publish/Subscribe id %d not found. map:%x\n", hal_req.publish_subscribe_id,
-                         ndev_vif->nan.subscribe_id_map);
+                         ndev_vif->nan.service_id_map);
                reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
                ret = -EINVAL;
                goto exit_with_lock;
        }
 
        ret = slsi_mlme_nan_tx_followup(sdev, dev, &hal_req);
-       if (ret)
-               reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+       if (ret) {
+               if (ret == SLSI_HAL_NAN_STATUS_FOLLOWUP_QUEUE_FULL) {
+                       reply_status = ret;
+                       ret = 0;
+               } else {
+                       reply_status = ret == SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+               }
+       } else {
+               SLSI_INFO(sdev,
+                         "transId:%d serviceId:%d instanceId:%d\n",
+                         hal_req.transaction_id, hal_req.publish_subscribe_id, hal_req.requestor_instance_id);
+               ndev_vif->nan.followup_trans_id = hal_req.transaction_id;
+       }
 
 exit_with_lock:
        SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
 exit:
-       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_TRANSMIT_FOLLOWUP, 0, NULL);
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_TRANSMIT_FOLLOWUP, 0, NULL, hal_req.transaction_id);
        return ret;
 }
 
@@ -1093,7 +1278,6 @@ static int slsi_nan_config_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_
        struct slsi_hal_nan_post_discovery_param *disc_attr;
        struct slsi_hal_nan_further_availability_channel *famchan;
 
-       memset(hal_req, 0, sizeof(*hal_req));
        nla_for_each_attr(iter, data, len, tmp) {
                type = nla_type(iter);
                switch (type) {
@@ -1307,6 +1491,10 @@ static int slsi_nan_config_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_
                        hal_req->disc_mac_addr_rand_interval_sec = nla_get_u8(iter);
                        break;
 
+               case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+                       hal_req->transaction_id = nla_get_u16(iter);
+                       break;
+
                default:
                        SLSI_ERR(sdev, "Unexpected NAN config attribute TYPE:%d\n", type);
                        return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
@@ -1320,37 +1508,43 @@ int slsi_nan_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const vo
        struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
        struct net_device *dev = slsi_nan_get_netdev(sdev);
        struct netdev_vif *ndev_vif;
-       struct slsi_hal_nan_config_req hal_req;
+       u16 transaction_id = 0;
        int ret;
        u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
 
-       if (!dev) {
-               SLSI_ERR(sdev, "NAN netif not active!!");
-               ret = -EINVAL;
-               reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
                goto exit;
-       }
 
        ndev_vif = netdev_priv(dev);
-       reply_status = slsi_nan_config_get_nl_params(sdev, &hal_req, data, len);
+
+       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+       reply_status = slsi_nan_config_get_nl_params(sdev, &ndev_vif->nan.config, data, len);
        if (reply_status) {
+               SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
                ret = -EINVAL;
                goto exit;
        }
-
-       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+       transaction_id = ndev_vif->nan.config.transaction_id;
        if (!ndev_vif->activated) {
                SLSI_WARN(sdev, "NAN vif not activated\n");
                reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
                ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
        } else {
-               ret = slsi_mlme_nan_set_config(sdev, dev, &hal_req);
-               if (ret)
+               ret = slsi_mlme_nan_set_config(sdev, dev, &ndev_vif->nan.config);
+               if (ret) {
                        reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+               } else {
+                       if (ndev_vif->nan.config.config_master_pref)
+                               ndev_vif->nan.master_pref_value = ndev_vif->nan.config.master_pref;
+                       ndev_vif->nan.random_mac_interval_sec = ndev_vif->nan.config.disc_mac_addr_rand_interval_sec;
+                       SLSI_INFO(sdev, "transId:%d masterPref:%d\n",
+                                 ndev_vif->nan.config.transaction_id, ndev_vif->nan.config.master_pref);
+               }
        }
        SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
 exit:
-       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_CONFIG, 0, NULL);
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_CONFIG, 0, NULL, transaction_id);
        return ret;
 }
 
@@ -1377,23 +1571,34 @@ int slsi_nan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, co
                                                  { SLSI_PSID_UNIFI_NAN_MAX_NDP_SESSIONS, { 0, 0 } },
                                                  { SLSI_PSID_UNIFI_NAN_MAX_APP_INFO_LENGTH, { 0, 0 } } };
        u32 *capabilities_mib_val[] = { &nan_capabilities.max_concurrent_nan_clusters,
-                                                                       &nan_capabilities.max_publishes,
-                                                                       &nan_capabilities.max_subscribes,
-                                                                       &nan_capabilities.max_service_name_len,
-                                                                       &nan_capabilities.max_match_filter_len,
-                                                                       &nan_capabilities.max_total_match_filter_len,
-                                                                       &nan_capabilities.max_service_specific_info_len,
-                                                                       &nan_capabilities.max_vsa_data_len,
-                                                                       &nan_capabilities.max_mesh_data_len,
-                                                                       &nan_capabilities.max_ndi_interfaces,
-                                                                       &nan_capabilities.max_ndp_sessions,
-                                                                       &nan_capabilities.max_app_info_len };
+                                       &nan_capabilities.max_publishes,
+                                       &nan_capabilities.max_subscribes,
+                                       &nan_capabilities.max_service_name_len,
+                                       &nan_capabilities.max_match_filter_len,
+                                       &nan_capabilities.max_total_match_filter_len,
+                                       &nan_capabilities.max_service_specific_info_len,
+                                       &nan_capabilities.max_vsa_data_len,
+                                       &nan_capabilities.max_mesh_data_len,
+                                       &nan_capabilities.max_ndi_interfaces,
+                                       &nan_capabilities.max_ndp_sessions,
+                                       &nan_capabilities.max_app_info_len };
+       int type, tmp;
+       const struct nlattr *iter;
+       u16 transaction_id = 0;
 
-       if (!dev) {
-               SLSI_ERR(sdev, "NAN netif not active!!");
-               reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
-               ret = -EINVAL;
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
                goto exit;
+
+       nla_for_each_attr(iter, data, len, tmp) {
+               type = nla_type(iter);
+               switch (type) {
+               case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+                       transaction_id = nla_get_u16(iter);
+                       break;
+               default:
+                       break;
+               }
        }
 
        ndev_vif = netdev_priv(dev);
@@ -1420,7 +1625,7 @@ int slsi_nan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, co
        for (i = 0; i < (int)ARRAY_SIZE(get_values); i++) {
                if (values[i].type == SLSI_MIB_TYPE_UINT) {
                        *capabilities_mib_val[i] = values[i].u.uintValue;
-                       SLSI_DBG2(sdev, SLSI_GSCAN, "MIB value = %ud\n", *capabilities_mib_val[i]);
+                       SLSI_DBG2(sdev, SLSI_GSCAN, "MIB value = %u\n", *capabilities_mib_val[i]);
                } else {
                        SLSI_ERR(sdev, "invalid type(%d). iter:%d\n", values[i].type, i);
                        ret = 0xFFFFFFFF;
@@ -1429,118 +1634,602 @@ int slsi_nan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, co
                }
        }
 
+       if (!nan_capabilities.max_ndi_interfaces)
+               nan_capabilities.max_ndi_interfaces = slsi_get_nan_max_ndi_ifaces();
+       if (!nan_capabilities.max_ndp_sessions)
+               nan_capabilities.max_ndi_interfaces = slsi_get_nan_max_ndp_instances();
+
+       if (nan_capabilities.max_ndi_interfaces > SLSI_NAN_MAX_NDP_INSTANCES) {
+               SLSI_ERR(sdev, "max ndp if's:%d but supported:%d\n", nan_capabilities.max_ndi_interfaces,
+                        SLSI_NAN_MAX_NDP_INSTANCES);
+               nan_capabilities.max_ndi_interfaces = SLSI_NAN_MAX_NDP_INSTANCES;
+       }
+
+       if (nan_capabilities.max_ndp_sessions > SLSI_NAN_MAX_NDP_INSTANCES) {
+               SLSI_ERR(sdev, "max ndp if's:%d but supported:%d\n", nan_capabilities.max_ndp_sessions,
+                        SLSI_NAN_MAX_NDP_INSTANCES);
+               nan_capabilities.max_ndi_interfaces = SLSI_NAN_MAX_NDP_INSTANCES;
+       }
+
+       SLSI_INFO(sdev, "transId:%d\n", transaction_id);
+
        kfree(values);
 exit_with_mibrsp:
        kfree(mibrsp.data);
        SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
 exit:
-       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_GET_CAPABILITIES, 0, &nan_capabilities);
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_GET_CAPABILITIES, 0, &nan_capabilities, transaction_id);
        return ret;
 }
 
-void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
+int slsi_nan_data_iface_create(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
 {
-       struct sk_buff *nl_skb = NULL;
-       int res = 0;
-       u16 event, identifier, evt_reason;
-       u8 *mac_addr;
-       u16 hal_event;
-       struct netdev_vif *ndev_vif;
-       enum slsi_nan_disc_event_type disc_event_type = 0;
+       struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+       u8 *iface_name = NULL;
+       int ret = 0, if_idx, type, tmp, err;
+       struct net_device *dev = slsi_nan_get_netdev(sdev);
+       struct net_device *dev_ndp = NULL;
+       u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+       const struct nlattr *iter;
+       u16 transaction_id = 0;
 
-       ndev_vif = netdev_priv(dev);
-       event = fapi_get_u16(skb, u.mlme_nan_event_ind.event);
-       identifier = fapi_get_u16(skb, u.mlme_nan_event_ind.identifier);
-       mac_addr = fapi_get_buff(skb, u.mlme_nan_event_ind.address_or_identifier);
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
+               goto exit;
 
-       switch (fapi_get_u16(skb, u.mlme_nan_event_ind.reason_code)) {
-       case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_TIMEOUT:
-       case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_COUNT_REACHED:
-       case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_DISCOVERY_SHUTDOWN:
-       case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_USER_REQUEST:
-       case FAPI_REASONCODE_NAN_TRANSMIT_FOLLOWUP_SUCCESS:
-               evt_reason = SLSI_HAL_NAN_STATUS_SUCCESS;
-               break;
-       case FAPI_REASONCODE_NAN_TRANSMIT_FOLLOWUP_FAILURE:
-               evt_reason = SLSI_HAL_NAN_STATUS_PROTOCOL_FAILURE;
-               break;
-       default:
-               evt_reason = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
-               break;
+       nla_for_each_attr(iter, data, len, tmp) {
+               type = nla_type(iter);
+               if (type == NAN_REQ_ATTR_DATA_INTERFACE_NAME)
+                       iface_name = nla_data(iter);
+               else if (type == NAN_REQ_ATTR_HAL_TRANSACTION_ID)
+                       transaction_id = nla_get_u16(iter);
        }
-
-       switch (event) {
-       case FAPI_EVENT_WIFI_EVENT_NAN_PUBLISH_TERMINATED:
-               hal_event = SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT;
-               break;
-       case FAPI_EVENT_WIFI_EVENT_NAN_MATCH_EXPIRED:
-               hal_event = SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT;
-               break;
-       case FAPI_EVENT_WIFI_EVENT_NAN_SUBSCRIBE_TERMINATED:
-               hal_event = SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT;
-               break;
-       case FAPI_EVENT_WIFI_EVENT_NAN_ADDRESS_CHANGED:
-               disc_event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
-               hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
-               break;
-       case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_STARTED:
-               disc_event_type = NAN_EVENT_ID_STARTED_CLUSTER;
-               hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
-               break;
-       case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_JOINED:
-               disc_event_type = NAN_EVENT_ID_JOINED_CLUSTER;
-               hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
-               break;
-       case FAPI_EVENT_WIFI_EVENT_NAN_TRANSMIT_FOLLOWUP:
-               hal_event = SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS;
-               break;
-       default:
-               return;
+       if (!iface_name) {
+               SLSI_ERR(sdev, "No NAN data interface name\n");
+               ret = WIFI_HAL_ERROR_INVALID_ARGS;
+               reply_status = SLSI_HAL_NAN_STATUS_INVALID_PARAM;
+               goto exit;
        }
 
-#ifdef CONFIG_SCSC_WLAN_DEBUG
-       SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n",
-                       slsi_print_event_name(hal_event), hal_event);
-#endif
-
-#if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE)
-       nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL);
-#else
-       nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL);
-#endif
-       if (!nl_skb) {
-               SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
-               return;
+       SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex);
+       /* Find unused netdev idx */
+       for (if_idx = SLSI_NAN_DATA_IFINDEX_START; if_idx < CONFIG_SCSC_WLAN_MAX_INTERFACES + 1; if_idx++) {
+               dev_ndp = slsi_get_netdev_locked(sdev, if_idx);
+               if (!dev_ndp)
+                       break;
        }
 
-       res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_STATUS, evt_reason);
-       switch (hal_event) {
-       case SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT:
-               res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, identifier);
-               ndev_vif->nan.publish_id_map &= (u32)~BIT(identifier);
-               break;
-       case SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT:
-               res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, identifier);
-               break;
-       case SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT:
-               res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_ID, identifier);
-               ndev_vif->nan.subscribe_id_map &= (u32)~BIT(identifier);
-               break;
-       case SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT:
-               res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE, disc_event_type);
-               res |= nla_put(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR, ETH_ALEN, mac_addr);
-               break;
+       if (if_idx >= CONFIG_SCSC_WLAN_MAX_INTERFACES + 1) {
+               SLSI_ERR(sdev, "NAN no free NAN data interfaces\n");
+               ret = WIFI_HAL_ERROR_TOO_MANY_REQUESTS;
+               reply_status = SLSI_HAL_NAN_STATUS_INVALID_PARAM;
+               goto exit_with_lock;
        }
 
-       if (res) {
-               SLSI_ERR(sdev, "Error in nla_put*:%x\n", res);
-               /* Dont use slsi skb wrapper for this free */
-               kfree_skb(nl_skb);
-               return;
+       err = slsi_netif_add_locked(sdev, iface_name, if_idx);
+       if (err) {
+               SLSI_ERR(sdev, "NAN fail net_if_add if_name:%s, if_idx:%d\n", iface_name, if_idx);
+               ret = WIFI_HAL_ERROR_OUT_OF_MEMORY;
+               reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+               goto exit_with_lock;
        }
 
-       cfg80211_vendor_event(nl_skb, GFP_KERNEL);
-}
+       dev_ndp = slsi_get_netdev_locked(sdev, if_idx);
+       err = slsi_netif_register_locked(sdev, dev_ndp);
+       if (err) {
+               SLSI_ERR(sdev, "NAN fail netdev err:%d if_name:%s, if_idx:%d\n", err);
+               ret = WIFI_HAL_ERROR_UNKNOWN;
+               reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+       } else {
+               SLSI_INFO(sdev, "trans_id:%d, if_name:%s, if_idx:%d\n", transaction_id, iface_name, if_idx);
+       }
+
+exit_with_lock:
+       SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex);
+exit:
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_DP_INTERFACE_CREATE, 0, NULL, transaction_id);
+       return ret;
+}
+
+int slsi_nan_data_iface_delete(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+       struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+       u8 *iface_name = NULL;
+       int ret = 0, if_idx, type, tmp;
+       struct net_device *dev = slsi_nan_get_netdev(sdev);
+       struct net_device *dev_ndp = NULL;
+       u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+       const struct nlattr *iter;
+       u16 transaction_id = 0;
+
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
+               goto exit;
+
+       nla_for_each_attr(iter, data, len, tmp) {
+               type = nla_type(iter);
+               if (type == NAN_REQ_ATTR_DATA_INTERFACE_NAME)
+                       iface_name = nla_data(iter);
+               else if (type == NAN_REQ_ATTR_HAL_TRANSACTION_ID)
+                       transaction_id = nla_get_u16(iter);
+       }
+       if (!iface_name) {
+               SLSI_ERR(sdev, "No NAN data interface name\n");
+               ret = WIFI_HAL_ERROR_INVALID_ARGS;
+               reply_status = SLSI_HAL_NAN_STATUS_INVALID_PARAM;
+               goto exit;
+       }
+
+       SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex);
+       for (if_idx = SLSI_NAN_DATA_IFINDEX_START; if_idx < CONFIG_SCSC_WLAN_MAX_INTERFACES + 1; if_idx++) {
+               dev_ndp = slsi_get_netdev_locked(sdev, if_idx);
+               if (dev_ndp && strcmp(iface_name, dev_ndp->name) == 0)
+                       break;
+               dev_ndp = NULL;
+       }
+
+       if (dev_ndp) {
+               slsi_netif_remove_locked(sdev, dev_ndp);
+               SLSI_INFO(sdev, "Success transId:%d ifaceName:%s\n", transaction_id, iface_name);
+       }
+
+       SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex);
+exit:
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_DP_INTERFACE_DELETE, 0, NULL, transaction_id);
+       return ret;
+}
+
+int slsi_nan_ndp_initiate_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_data_path_initiator_req *hal_req,
+                                       const void *data, int len)
+{
+       int type, tmp, r;
+       const struct nlattr *iter;
+
+       memset(hal_req, 0, sizeof(*hal_req));
+       nla_for_each_attr(iter, data, len, tmp) {
+               type = nla_type(iter);
+               switch (type) {
+               case NAN_REQ_ATTR_REQ_INSTANCE_ID:
+                       hal_req->requestor_instance_id = nla_get_u32(iter);
+                       break;
+
+               case NAN_REQ_ATTR_CHAN_REQ_TYPE:
+                       hal_req->channel_request_type = nla_get_u8(iter);
+                       break;
+
+               case NAN_REQ_ATTR_CHAN:
+                       hal_req->channel = nla_get_u32(iter);
+                       break;
+
+               case NAN_REQ_ATTR_MAC_ADDR_VAL:
+                       ether_addr_copy(hal_req->peer_disc_mac_addr, nla_data(iter));
+                       break;
+
+               case NAN_REQ_ATTR_DATA_INTERFACE_NAME:
+                       memcpy(hal_req->ndp_iface, nla_data(iter), IFNAMSIZ);
+                       break;
+
+               case NAN_REQ_ATTR_DATA_INTERFACE_NAME_LEN:
+                       break;
+
+               case NAN_REQ_ATTR_SDEA_PARAM_SECURITY_CFG:
+                       hal_req->ndp_cfg.security_cfg = nla_get_u8(iter);
+                       break;
+
+               case NAN_REQ_ATTR_SDEA_PARAM_QOS_CFG:
+                       hal_req->ndp_cfg.qos_cfg =  nla_get_u8(iter);
+                       break;
+
+               case NAN_REQ_ATTR_APP_INFO_LEN:
+                       hal_req->app_info.ndp_app_info_len = nla_get_u16(iter);
+                       break;
+
+               case NAN_REQ_ATTR_APP_INFO:
+                       memcpy(hal_req->app_info.ndp_app_info, nla_data(iter), hal_req->app_info.ndp_app_info_len);
+                       break;
+
+               case NAN_REQ_ATTR_SERVICE_NAME_LEN:
+                       hal_req->service_name_len = nla_get_u32(iter);
+                       break;
+
+               case NAN_REQ_ATTR_SERVICE_NAME:
+                       memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len);
+                       break;
+
+               case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+                       hal_req->transaction_id = nla_get_u16(iter);
+                       break;
+
+               default:
+                       r = slsi_nan_get_security_info_nl(sdev, &hal_req->key_info, iter, type);
+                       if (r)
+                               SLSI_ERR(sdev, "Unexpected NAN ndp attribute TYPE:%d\n", type);
+               }
+       }
+       return SLSI_HAL_NAN_STATUS_SUCCESS;
+}
+
+int slsi_nan_ndp_initiate(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+       struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+       struct net_device *dev = slsi_nan_get_netdev(sdev);
+       struct netdev_vif *ndev_vif;
+       struct slsi_hal_nan_data_path_initiator_req *hal_req = NULL;
+       int ret;
+       u32 ndp_id = 0;
+       u16 ndl_vif_id, transaction_id = 0;
+       u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
+               goto exit;
+
+       hal_req = kmalloc(sizeof(*hal_req), GFP_KERNEL);
+       if (!hal_req) {
+               SLSI_ERR(sdev, "Failed to alloc hal_req structure!!!\n");
+               reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+               ret = WIFI_HAL_ERROR_OUT_OF_MEMORY;
+               goto exit;
+       }
+
+       ndev_vif = netdev_priv(dev);
+       reply_status = slsi_nan_ndp_initiate_get_nl_params(sdev, hal_req, data, len);
+       if (reply_status) {
+               ret = WIFI_HAL_ERROR_INVALID_ARGS;
+               goto exit;
+       }
+       transaction_id = hal_req->transaction_id;
+
+       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+       if (!ndev_vif->activated) {
+               SLSI_WARN(sdev, "NAN vif not activated\n");
+               reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+               ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+               goto exit_with_lock;
+       }
+
+       ndp_id = slsi_nan_get_new_ndp_id(ndev_vif);
+       if (!ndp_id) {
+               SLSI_WARN(sdev, "NAN no free ndp slots\n");
+               reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+               ret = WIFI_HAL_ERROR_TOO_MANY_REQUESTS;
+               goto exit_with_lock;
+       }
+
+       ndl_vif_id = slsi_nan_ndp_get_ndl_vif_id(hal_req->peer_disc_mac_addr, ndev_vif->nan.ndl_list);
+       if (ndl_vif_id >= SLSI_NAN_MAX_NDP_INSTANCES + SLSI_NAN_DATA_IFINDEX_START) {
+               SLSI_WARN(sdev, "NAN no free ndl slots\n");
+               reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+               ret = WIFI_HAL_ERROR_TOO_MANY_REQUESTS;
+               goto exit_with_lock;
+       }
+       ret = slsi_mlme_ndp_request(sdev, dev, hal_req, ndp_id, ndl_vif_id);
+       if (ret) {
+               reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+               ret = WIFI_HAL_ERROR_UNKNOWN;
+       } else {
+               SLSI_INFO(sdev, "transId:%d ndpId:%d ndlVifId:%d iface:%s\n",
+                         hal_req->transaction_id, ndp_id, ndl_vif_id, hal_req->ndp_iface);
+               ret = WIFI_HAL_SUCCESS;
+       }
+
+exit_with_lock:
+       SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_DP_INITIATOR_RESPONSE, (u16)ndp_id, NULL, transaction_id);
+       kfree(hal_req);
+       return ret;
+}
+
+int slsi_nan_ndp_respond_get_nl_param(struct slsi_dev *sdev, struct slsi_hal_nan_data_path_indication_response *hal_req,
+                                     const void *data, int len)
+{
+       int type, tmp, r;
+       const struct nlattr *iter;
+
+       memset(hal_req, 0, sizeof(*hal_req));
+       nla_for_each_attr(iter, data, len, tmp) {
+               type = nla_type(iter);
+               switch (type) {
+               case NAN_REQ_ATTR_NDP_INSTANCE_ID:
+                       hal_req->ndp_instance_id = nla_get_u32(iter);
+                       break;
+
+               case NAN_REQ_ATTR_DATA_INTERFACE_NAME:
+                       memcpy(hal_req->ndp_iface, nla_data(iter), IFNAMSIZ);
+                       break;
+               case NAN_REQ_ATTR_DATA_INTERFACE_NAME_LEN:
+                       break;
+
+               case NAN_REQ_ATTR_SDEA_PARAM_SECURITY_CFG:
+                       hal_req->ndp_cfg.security_cfg = nla_get_u8(iter);
+                       break;
+
+               case NAN_REQ_ATTR_SDEA_PARAM_QOS_CFG:
+                       hal_req->ndp_cfg.qos_cfg =  nla_get_u8(iter);
+                       break;
+
+               case NAN_REQ_ATTR_APP_INFO_LEN:
+                       hal_req->app_info.ndp_app_info_len = nla_get_u16(iter);
+                       break;
+
+               case NAN_REQ_ATTR_APP_INFO:
+                       memcpy(hal_req->app_info.ndp_app_info, nla_data(iter), hal_req->app_info.ndp_app_info_len);
+                       break;
+
+               case NAN_REQ_ATTR_NDP_RESPONSE_CODE:
+                       hal_req->rsp_code = nla_get_u8(iter);
+                       break;
+
+               case NAN_REQ_ATTR_SERVICE_NAME_LEN:
+                       hal_req->service_name_len = nla_get_u32(iter);
+                       break;
+
+               case NAN_REQ_ATTR_SERVICE_NAME:
+                       memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len);
+                       break;
+
+               case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+                       hal_req->transaction_id = nla_get_u16(iter);
+                       break;
+
+               default:
+                       r = 0;
+                       r = slsi_nan_get_security_info_nl(sdev, &hal_req->key_info, iter, type);
+                       if (r)
+                               SLSI_ERR(sdev, "Unexpected NAN ndp attribute TYPE:%d\n", type);
+               }
+       }
+       return SLSI_HAL_NAN_STATUS_SUCCESS;
+}
+
+int slsi_nan_ndp_respond(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+       struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+       struct net_device *dev = slsi_nan_get_netdev(sdev);
+       struct netdev_vif *ndev_vif;
+       struct slsi_hal_nan_data_path_indication_response *hal_req = NULL;
+       int ret;
+       u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+       u16 transaction_id = 0, ndp_instance_id = 0;
+
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
+               goto exit;
+
+       hal_req = kmalloc(sizeof(*hal_req), GFP_KERNEL);
+       if (!hal_req) {
+               SLSI_ERR(sdev, "Failed to alloc hal_req structure!!!\n");
+               reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+               ret = WIFI_HAL_ERROR_OUT_OF_MEMORY;
+               goto exit;
+       }
+
+       ndev_vif = netdev_priv(dev);
+       reply_status = slsi_nan_ndp_respond_get_nl_param(sdev, hal_req, data, len);
+       transaction_id = hal_req->transaction_id;
+       ndp_instance_id = hal_req->ndp_instance_id;
+       if (reply_status) {
+               ret = WIFI_HAL_ERROR_INVALID_ARGS;
+               goto exit;
+       }
+
+       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+       if (!ndev_vif->activated) {
+               SLSI_WARN(sdev, "NAN vif not activated\n");
+               reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+               ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+               goto exit_with_lock;
+       }
+
+       ret = slsi_mlme_ndp_response(sdev, dev, hal_req, ndev_vif->nan.ndp_local_ndp_id[hal_req->ndp_instance_id - 1]);
+       if (ret) {
+               reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+               ret = WIFI_HAL_ERROR_UNKNOWN;
+       } else {
+               SLSI_INFO(sdev, "transId:%d ndpId:%d iface:%s\n",
+                         hal_req->transaction_id, hal_req->ndp_instance_id, hal_req->ndp_iface);
+               ret = WIFI_HAL_SUCCESS;
+       }
+
+exit_with_lock:
+       SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_DP_RESPONDER_RESPONSE,
+                                     ndp_instance_id, NULL, transaction_id);
+       kfree(hal_req);
+       return ret;
+}
+
+int slsi_nan_ndp_end_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_data_end *hal_req,
+                                  const void *data, int len)
+{
+       int type, tmp;
+       const struct nlattr *iter;
+
+       memset(hal_req, 0, sizeof(*hal_req));
+       nla_for_each_attr(iter, data, len, tmp) {
+               type = nla_type(iter);
+               if (type == NAN_REQ_ATTR_NDP_INSTANCE_ID && hal_req->num_ndp_instances < SLSI_NAN_MAX_NDP_INSTANCES)
+                       hal_req->ndp_instance_id[hal_req->num_ndp_instances++] = nla_get_u32(iter);
+               else if (type == NAN_REQ_ATTR_HAL_TRANSACTION_ID)
+                       hal_req->transaction_id = nla_get_u16(iter);
+       }
+       return SLSI_HAL_NAN_STATUS_SUCCESS;
+}
+
+int slsi_nan_ndp_end(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+       struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+       struct net_device *dev = slsi_nan_get_netdev(sdev);
+       struct netdev_vif *ndev_vif;
+       struct slsi_hal_nan_data_end hal_req;
+       int ret, i;
+       u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+
+       hal_req.transaction_id = 0;
+       slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+       if (ret != WIFI_HAL_SUCCESS)
+               goto exit;
+
+       ndev_vif = netdev_priv(dev);
+       reply_status = slsi_nan_ndp_end_get_nl_params(sdev, &hal_req, data, len);
+
+       if (reply_status) {
+               ret = WIFI_HAL_ERROR_INVALID_ARGS;
+               goto exit;
+       }
+
+       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+       if (!ndev_vif->activated) {
+               SLSI_WARN(sdev, "NAN vif not activated\n");
+               slsi_nan_ndp_termination_handler(sdev, dev, 0, 0, NULL);
+               ret = WIFI_HAL_SUCCESS;
+               goto exit_with_lock;
+       }
+       for (i = 0; i < hal_req.num_ndp_instances; i++)
+               if (hal_req.ndp_instance_id[i] > 0 && hal_req.ndp_instance_id[i] <= SLSI_NAN_MAX_NDP_INSTANCES) {
+                       ndev_vif->nan.ndp_state[hal_req.ndp_instance_id[i] - 1] = ndp_slot_status_terminating;
+                       slsi_mlme_ndp_terminate(sdev, dev, hal_req.ndp_instance_id[i]);
+                       SLSI_INFO(sdev, "transId:%d ndpId:%d [%d/%d]\n",
+                                 hal_req.transaction_id, hal_req.ndp_instance_id[i], i, hal_req.num_ndp_instances);
+               } else {
+                       SLSI_ERR(sdev, "Ignore invalid ndp_id:%d\n", hal_req.ndp_instance_id[i]);
+               }
+
+exit_with_lock:
+       SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+       slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_DP_END, 0, NULL, hal_req.transaction_id);
+       return ret;
+}
+
+/* NAN HAL EVENTS */
+
+void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
+{
+       struct sk_buff *nl_skb = NULL;
+       int res = 0;
+       u16 event, identifier, evt_reason;
+       u8 *mac_addr;
+       u16 hal_event;
+       struct netdev_vif *ndev_vif;
+       enum slsi_nan_disc_event_type disc_event_type = 0;
+
+       ndev_vif = netdev_priv(dev);
+       event = fapi_get_u16(skb, u.mlme_nan_event_ind.event);
+       identifier = fapi_get_u16(skb, u.mlme_nan_event_ind.identifier);
+       mac_addr = fapi_get_buff(skb, u.mlme_nan_event_ind.address_or_identifier);
+
+       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+
+       switch (fapi_get_u16(skb, u.mlme_nan_event_ind.reason_code)) {
+       case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_TIMEOUT:
+       case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_COUNT_REACHED:
+       case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_DISCOVERY_SHUTDOWN:
+       case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_USER_REQUEST:
+       case FAPI_REASONCODE_NAN_TRANSMIT_FOLLOWUP_SUCCESS:
+               evt_reason = SLSI_HAL_NAN_STATUS_SUCCESS;
+               break;
+       case FAPI_REASONCODE_NAN_TRANSMIT_FOLLOWUP_FAILURE:
+               evt_reason = SLSI_HAL_NAN_STATUS_PROTOCOL_FAILURE;
+               break;
+       default:
+               evt_reason = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+               break;
+       }
+
+       switch (event) {
+       case FAPI_EVENT_WIFI_EVENT_NAN_PUBLISH_TERMINATED:
+               ndev_vif->nan.service_id_map &= (u32)~BIT(identifier);
+               if (ndev_vif->nan.nan_sdf_flags[identifier] & FAPI_NANSDFCONTROL_PUBLISH_END_EVENT)
+                       goto exit;
+               hal_event = SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT;
+               break;
+       case FAPI_EVENT_WIFI_EVENT_NAN_MATCH_EXPIRED:
+               if (ndev_vif->nan.nan_sdf_flags[identifier] & FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT)
+                       goto exit;
+               hal_event = SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT;
+               break;
+       case FAPI_EVENT_WIFI_EVENT_NAN_SUBSCRIBE_TERMINATED:
+               ndev_vif->nan.service_id_map &= (u32)~BIT(identifier);
+               if (ndev_vif->nan.nan_sdf_flags[identifier] & FAPI_NANSDFCONTROL_SUBSCRIBE_END_EVENT)
+                       goto exit;
+               hal_event = SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT;
+               break;
+       case FAPI_EVENT_WIFI_EVENT_NAN_ADDRESS_CHANGED:
+               disc_event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
+               hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
+               ether_addr_copy(ndev_vif->nan.local_nmi, mac_addr);
+               break;
+       case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_STARTED:
+               disc_event_type = NAN_EVENT_ID_STARTED_CLUSTER;
+               hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
+               ether_addr_copy(ndev_vif->nan.cluster_id, mac_addr);
+               break;
+       case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_JOINED:
+               disc_event_type = NAN_EVENT_ID_JOINED_CLUSTER;
+               hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
+               ether_addr_copy(ndev_vif->nan.cluster_id, mac_addr);
+               break;
+       case FAPI_EVENT_WIFI_EVENT_NAN_TRANSMIT_FOLLOWUP:
+               if (ndev_vif->nan.nan_sdf_flags[identifier] & FAPI_NANSDFCONTROL_FOLLOWUP_TRANSMIT_STATUS)
+                       goto exit;
+               hal_event = SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS;
+               break;
+       default:
+               goto exit;
+       }
+
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+       SLSI_INFO(sdev, "Event: %s(%d)\n",
+                 slsi_print_event_name(hal_event), hal_event);
+#endif
+
+#if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE)
+       nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL);
+#else
+       nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL);
+#endif
+       if (!nl_skb) {
+               SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
+               goto exit;
+       }
+
+       res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_STATUS, evt_reason);
+       switch (hal_event) {
+       case SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT:
+               res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, identifier);
+               break;
+       case SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT:
+               res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, identifier);
+               break;
+       case SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT:
+               res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_ID, identifier);
+               break;
+       case SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT:
+               res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE, disc_event_type);
+               res |= nla_put(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR, ETH_ALEN, mac_addr);
+               break;
+       case SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS:
+               res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_HAL_TRANSACTION_ID, ndev_vif->nan.followup_trans_id);
+               ndev_vif->nan.followup_trans_id = 0;
+               break;
+       }
+
+       if (res) {
+               SLSI_ERR(sdev, "Error in nla_put*:%x\n", res);
+               /* Dont use slsi skb wrapper for this free */
+               kfree_skb(nl_skb);
+               goto exit;
+       }
+
+       cfg80211_vendor_event(nl_skb, GFP_KERNEL);
+
+exit:
+       SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+       slsi_kfree_skb(skb);
+}
 
 void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
 {
@@ -1550,59 +2239,59 @@ void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct
        struct sk_buff *nl_skb;
        int res;
        int sig_data_len;
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
 
        SLSI_DBG3(sdev, SLSI_GSCAN, "\n");
 
+       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
        sig_data_len = fapi_get_datalen(skb);
-       if (sig_data_len <= 4) {
-               SLSI_ERR(sdev, "Invalid data len(%d)\n", sig_data_len);
-               return;
-       }
 
        hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL);
        if (!hal_evt) {
                SLSI_ERR(sdev, "No memory for followup_ind\n");
-               return;
+               goto exit;
        }
        memset(hal_evt, 0, sizeof(*hal_evt));
 
-       hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.publish_subscribe_id);
+       hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.session_id);
        hal_evt->requestor_instance_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.match_id);
        ether_addr_copy(hal_evt->addr,
                        fapi_get_buff(skb, u.mlme_nan_followup_ind.peer_nan_management_interface_address));
 
        ptr = fapi_get_data(skb);
-       tag_id = le16_to_cpu(*(u16 *)ptr);
-       tag_len = le16_to_cpu(*(u16 *)(ptr + 2));
-
-       while (sig_data_len >= tag_len + 4) {
-               if (tag_id == SLSI_NAN_TLV_TAG_SERVICE_SPECIFIC_INFO) {
-                       hal_evt->service_specific_info_len = tag_len > SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN ?
-                                               SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN : tag_len;
-                       memcpy(hal_evt->service_specific_info, ptr + 4, hal_evt->service_specific_info_len);
-               } else if (tag_id == SLSI_NAN_TLV_TAG_EXT_SERVICE_SPECIFIC_INFO) {
-                       if (tag_len > SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN)
-                               hal_evt->sdea_service_specific_info_len = SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN;
-                       else
-                               hal_evt->sdea_service_specific_info_len = tag_len;
-                       memcpy(hal_evt->sdea_service_specific_info, ptr + 4, hal_evt->sdea_service_specific_info_len);
-               } else {
-                       SLSI_WARN(sdev, "Skip processing TLV %d\n", tag_id);
-               }
-               sig_data_len -= tag_len + 4;
-               ptr += tag_len + 4;
-               if (sig_data_len > 4) {
-                       tag_id = le16_to_cpu(*(u16 *)ptr);
-                       tag_len = le16_to_cpu(*(u16 *)(ptr + 2));
-               } else {
-                       tag_id = 0;
-                       tag_len = 0;
+       if (ptr) {
+               tag_id = le16_to_cpu(*(u16 *)ptr);
+               tag_len = le16_to_cpu(*(u16 *)(ptr + 2));
+
+               while (sig_data_len >= tag_len + 4) {
+                       if (tag_id == SLSI_NAN_TLV_TAG_SERVICE_SPECIFIC_INFO) {
+                               hal_evt->service_specific_info_len = tag_len > SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN ?
+                                                       SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN : tag_len;
+                               memcpy(hal_evt->service_specific_info, ptr + 4, hal_evt->service_specific_info_len);
+                       } else if (tag_id == SLSI_NAN_TLV_TAG_EXT_SERVICE_SPECIFIC_INFO) {
+                               if (tag_len > SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN)
+                                       hal_evt->sdea_service_specific_info_len = SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN;
+                               else
+                                       hal_evt->sdea_service_specific_info_len = tag_len;
+                               memcpy(hal_evt->sdea_service_specific_info, ptr + 4, hal_evt->sdea_service_specific_info_len);
+                       } else {
+                               SLSI_WARN(sdev, "Skip processing TLV %d\n", tag_id);
+                       }
+                       sig_data_len -= tag_len + 4;
+                       ptr += tag_len + 4;
+                       if (sig_data_len > 4) {
+                               tag_id = le16_to_cpu(*(u16 *)ptr);
+                               tag_len = le16_to_cpu(*(u16 *)(ptr + 2));
+                       } else {
+                               tag_id = 0;
+                               tag_len = 0;
+                       }
                }
        }
 
 #ifdef CONFIG_SCSC_WLAN_DEBUG
-       SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n",
-                       slsi_print_event_name(SLSI_NL80211_NAN_FOLLOWUP_EVENT), SLSI_NL80211_NAN_FOLLOWUP_EVENT);
+       SLSI_INFO(sdev, "Event: %s(%d)\n",
+                 slsi_print_event_name(SLSI_NL80211_NAN_FOLLOWUP_EVENT), SLSI_NL80211_NAN_FOLLOWUP_EVENT);
 #endif
 #if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE)
        nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_FOLLOWUP_EVENT,
@@ -1615,7 +2304,7 @@ void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct
        if (!nl_skb) {
                SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
                kfree(hal_evt);
-               return;
+               goto exit;
        }
 
        res = nla_put_be16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID,
@@ -1638,11 +2327,14 @@ void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct
                kfree(hal_evt);
                /* Dont use slsi skb wrapper for this free */
                kfree_skb(nl_skb);
-               return;
+               goto exit;
        }
 
        cfg80211_vendor_event(nl_skb, GFP_KERNEL);
        kfree(hal_evt);
+exit:
+       SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+       slsi_kfree_skb(skb);
 }
 
 void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
@@ -1654,23 +2346,24 @@ void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct
        struct slsi_hal_nan_match_ind *hal_evt;
        struct sk_buff *nl_skb;
        int res;
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
 
        SLSI_DBG3(sdev, SLSI_GSCAN, "\n");
-
+       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
        sig_data_len = fapi_get_datalen(skb);
        if (sig_data_len <= 4) {
                SLSI_ERR(sdev, "Invalid data len(%d)\n", sig_data_len);
-               return;
+               goto exit;
        }
 
        hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL);
        if (!hal_evt) {
                SLSI_ERR(sdev, "No memory for service_ind\n");
-               return;
+               goto exit;
        }
 
        memset(hal_evt, 0, sizeof(*hal_evt));
-       hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_service_ind.publish_subscribe_id);
+       hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_service_ind.session_id);
        hal_evt->requestor_instance_id = fapi_get_u16(skb, u.mlme_nan_service_ind.match_id);
        hal_evt->ranging_event_type = fapi_get_u16(skb, u.mlme_nan_service_ind.rangingindicationtype);
        hal_evt->range_measurement_mm = 10 * fapi_get_u16(skb, u.mlme_nan_service_ind.ranging_measurement);
@@ -1719,6 +2412,13 @@ void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct
                        hal_evt->sec_info.cipher_type = *tag_data_ptr;
                        tag_data_ptr++;
                        break;
+               case SLSI_NAN_TLV_TAG_MATCH_FILTER:
+                       if (tag_len > SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN)
+                               hal_evt->sdf_match_filter_len = SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN;
+                       else
+                               hal_evt->sdf_match_filter_len = tag_len;
+                       memcpy(hal_evt->sdf_match_filter, tag_data_ptr, hal_evt->sdf_match_filter_len);
+                       break;
                default:
                        SLSI_WARN(sdev, "Skip processing TLV %d\n", tag_id);
                        break;
@@ -1729,6 +2429,7 @@ void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct
                if (sig_data_len > 4) {
                        tag_id = le16_to_cpu(*(u16 *)ptr);
                        tag_len = le16_to_cpu(*(u16 *)(ptr + 2));
+                       tag_data_ptr = ptr + 4;
                } else {
                        tag_id = 0;
                        tag_len = 0;
@@ -1736,8 +2437,8 @@ void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct
        }
 
 #ifdef CONFIG_SCSC_WLAN_DEBUG
-       SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n",
-                       slsi_print_event_name(SLSI_NL80211_NAN_MATCH_EVENT), SLSI_NL80211_NAN_MATCH_EVENT);
+       SLSI_INFO(sdev, "Event: %s(%d)\n",
+                 slsi_print_event_name(SLSI_NL80211_NAN_MATCH_EVENT), SLSI_NL80211_NAN_MATCH_EVENT);
 #endif
 #if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE)
        nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_MATCH_EVENT,
@@ -1748,7 +2449,7 @@ void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct
        if (!nl_skb) {
                SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
                kfree(hal_evt);
-               return;
+               goto exit;
        }
        res = nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, hal_evt->publish_subscribe_id);
        res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, hal_evt->requestor_instance_id);
@@ -1778,9 +2479,389 @@ void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct
                /* Dont use slsi skb wrapper for this free */
                kfree_skb(nl_skb);
                kfree(hal_evt);
-               return;
+               goto exit;
        }
 
        cfg80211_vendor_event(nl_skb, GFP_KERNEL);
        kfree(hal_evt);
+exit:
+       SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+       slsi_kfree_skb(skb);
+}
+
+static void slsi_nan_get_resp_status_code(u16 fapi_result_code, u16 *resp_code, u16 *status_code)
+{
+       switch (fapi_result_code) {
+       case FAPI_RESULTCODE_SUCCESS:
+               *resp_code = NAN_DP_REQUEST_ACCEPT;
+               *status_code = SLSI_HAL_NAN_STATUS_SUCCESS;
+               break;
+       case FAPI_RESULTCODE_NDP_REJECTED:
+               *resp_code = NAN_DP_REQUEST_REJECT;
+               *status_code = SLSI_HAL_NAN_STATUS_SUCCESS;
+               break;
+       case FAPI_RESULTCODE_NAN_NO_OTA_ACK:
+               *resp_code = NAN_DP_REQUEST_REJECT;
+               *status_code = SLSI_HAL_NAN_STATUS_NO_OTA_ACK;
+               break;
+       case FAPI_RESULTCODE_NAN_INVALID_AVAILABILITY:
+       case FAPI_RESULTCODE_NAN_IMMUTABLE_UNACCEPTABLE:
+       case FAPI_RESULTCODE_NAN_REJECTED_SECURITY_POLICY:
+       case FAPI_RESULTCODE_NDL_UNACCEPTABLE:
+               *resp_code = NAN_DP_REQUEST_REJECT;
+               *status_code = SLSI_HAL_NAN_STATUS_PROTOCOL_FAILURE;
+               break;
+       case FAPI_RESULTCODE_TRANSMISSION_FAILURE:
+       default:
+               *resp_code = NAN_DP_REQUEST_REJECT;
+               *status_code = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+       }
+}
+
+u32 slsi_nan_get_ndp_from_ndl_local_ndi(struct net_device *dev, u16 ndl_vif_id, u8 *local_ndi)
+{
+       int i, j;
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+
+       for (i = 0; i < SLSI_NAN_MAX_NDP_INSTANCES; i++) {
+               if (ndev_vif->nan.ndp_id2ndl_vif[i] == ndl_vif_id) {
+                       for (j = 0; j < SLSI_NAN_MAX_NDP_INSTANCES; j++)
+                               if (ether_addr_equal(ndev_vif->nan.ndp_ndi[j], local_ndi))
+                                       return i + 1;
+               }
+       }
+       return SLSI_NAN_MAX_NDP_INSTANCES + 1;
+}
+
+static int slsi_nan_put_ndp_req_ind_params(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb,
+                                          struct sk_buff *nl_skb, u8 **peer_ndi, u16 *resp_code, u16 *ndp_id)
+{
+       int res;
+       u16 ndl_vif_id, status_code;
+       u8 *local_ndi;
+
+       ndl_vif_id = fapi_get_u16(skb, u.mlme_ndp_request_ind.ndl_vif_index);
+       *peer_ndi = fapi_get_buff(skb, u.mlme_ndp_request_ind.peer_ndp_interface_address);
+       local_ndi = fapi_get_buff(skb, u.mlme_ndp_request_ind.local_ndp_interface_address);
+       slsi_nan_get_resp_status_code(fapi_get_u16(skb, u.mlme_ndp_request_ind.result_code), resp_code, &status_code);
+       *ndp_id = slsi_nan_get_ndp_from_ndl_local_ndi(dev, ndl_vif_id, local_ndi);
+
+       res = nla_put_u32(nl_skb, NAN_EVT_ATTR_NDP_INSTANCE_ID, *ndp_id);
+       res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_ADDR, ETH_ALEN, *peer_ndi);
+
+       res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_NDP_RSP_CODE, *resp_code);
+       res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_STATUS_CODE, status_code);
+
+       return res;
+}
+
+static int slsi_nan_put_ndp_resp_ind_params(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb,
+                                           struct sk_buff *nl_skb, u8 **peer_ndi, u16 *resp_code, u16 *ndp_id)
+{
+       int res;
+       u16 ndl_vif_id, status_code;
+       u8 *local_ndi;
+
+       ndl_vif_id = fapi_get_u16(skb, u.mlme_ndp_response_ind.ndl_vif_index);
+       *peer_ndi = fapi_get_buff(skb, u.mlme_ndp_response_ind.peer_ndp_interface_address);
+       local_ndi = fapi_get_buff(skb, u.mlme_ndp_response_ind.local_ndp_interface_address);
+       slsi_nan_get_resp_status_code(fapi_get_u16(skb, u.mlme_ndp_response_ind.result_code), resp_code, &status_code);
+       *ndp_id = slsi_nan_get_ndp_from_ndl_local_ndi(dev, ndl_vif_id, local_ndi);
+
+       res = nla_put_u32(nl_skb, NAN_EVT_ATTR_NDP_INSTANCE_ID, *ndp_id);
+       res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_ADDR, ETH_ALEN, *peer_ndi);
+
+       res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_NDP_RSP_CODE, *resp_code);
+       res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_STATUS_CODE, status_code);
+
+       return res;
+}
+
+void slsi_nan_ndp_setup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, bool is_req_ind)
+{
+       u16 tag_id, tag_len;
+       u8  *ptr;
+       const u8 *tag_data_ptr;
+       int sig_data_len;
+       struct sk_buff *nl_skb;
+       int res;
+       u8 *peer_ndi;
+       u16 ndp_setup_response, ndp_id;
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+
+       SLSI_DBG3(sdev, SLSI_GSCAN, "\n");
+       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+       sig_data_len = fapi_get_datalen(skb);
+
+#if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE)
+       nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NAN_EVENT_NDP_CFM,
+                                            GFP_KERNEL);
+#else
+       nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NAN_EVENT_NDP_CFM, GFP_KERNEL);
+#endif
+       if (!nl_skb) {
+               SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
+               goto exit;
+       }
+
+       if (is_req_ind)
+               res = slsi_nan_put_ndp_req_ind_params(sdev, dev, skb, nl_skb, &peer_ndi, &ndp_setup_response, &ndp_id);
+       else
+               res = slsi_nan_put_ndp_resp_ind_params(sdev, dev, skb, nl_skb, &peer_ndi, &ndp_setup_response, &ndp_id);
+
+       if (ndp_setup_response != NAN_DP_REQUEST_ACCEPT)
+               slsi_nan_ndp_del_entry(sdev, dev, ndp_id);
+
+       ptr = fapi_get_data(skb);
+       if (ptr) {
+               tag_id = le16_to_cpu(*(u16 *)ptr);
+               tag_len = le16_to_cpu(*(u16 *)(ptr + 2));
+               tag_data_ptr = ptr + 4;
+
+               while (sig_data_len >= tag_len + 4) {
+                       if (tag_id == SLSI_NAN_TLV_TAG_APP_INFO) {
+                               res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_APP_INFO_LEN, tag_len);
+                               res |= nla_put(nl_skb, NAN_EVT_ATTR_APP_INFO, tag_len, tag_data_ptr);
+                               break;
+                       }
+                       sig_data_len -= tag_len + 4;
+                       ptr += tag_len + 4;
+                       if (sig_data_len > 4) {
+                               tag_id = le16_to_cpu(*(u16 *)ptr);
+                               tag_len = le16_to_cpu(*(u16 *)(ptr + 2));
+                               tag_data_ptr = ptr + 4;
+                       } else {
+                               tag_id = 0;
+                               tag_len = 0;
+                       }
+               }
+       }
+
+       if (res) {
+               SLSI_ERR(sdev, "Error in nla_put*:%x\n", res);
+               /* Dont use slsi skb wrapper for this free */
+               kfree_skb(nl_skb);
+               goto exit;
+       }
+
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+       SLSI_INFO(sdev, "Event: %s(%d)\n",
+                 slsi_print_event_name(SLSI_NAN_EVENT_NDP_CFM), SLSI_NAN_EVENT_NDP_CFM);
+#endif
+
+       cfg80211_vendor_event(nl_skb, GFP_KERNEL);
+       if (ndp_setup_response == NAN_DP_REQUEST_ACCEPT) {
+               struct netdev_vif *ndev_data_vif;
+               struct net_device *data_dev = slsi_get_netdev_by_mac_addr_locked(sdev, ndev_vif->nan.ndp_ndi[ndp_id],
+                                                                         SLSI_NAN_DATA_IFINDEX_START);
+               struct slsi_peer *peer = NULL;
+
+               if (ndp_id == 0 || ndp_id > SLSI_NAN_MAX_NDP_INSTANCES + 1) {
+                       SLSI_ERR(sdev, "Invalid ndp_id:%d\n", ndp_id);
+                       goto exit;
+               }
+
+               data_dev = slsi_get_netdev_by_mac_addr(sdev, ndev_vif->nan.ndp_ndi[ndp_id - 1],
+                                                      SLSI_NAN_DATA_IFINDEX_START);
+
+               if (!data_dev) {
+                       SLSI_ERR(sdev, "no data_dev for ndp:%d ndi[%pM]\n", ndp_id, ndev_vif->nan.ndp_ndi[ndp_id - 1]);
+                       goto exit;
+               }
+               ndev_data_vif = netdev_priv(data_dev);
+               SLSI_MUTEX_LOCK(ndev_data_vif->vif_mutex);
+               peer = slsi_peer_add(sdev, data_dev, peer_ndi, ndp_id);
+               if (peer) {
+                       peer->connected_state = SLSI_STA_CONN_STATE_CONNECTED;
+                       slsi_ps_port_control(sdev, data_dev, peer, SLSI_STA_CONN_STATE_CONNECTED);
+                       peer->ndl_vif = ndev_vif->nan.ndp_id2ndl_vif[ndp_id - 1];
+                       peer->qos_enabled = true;
+               } else {
+                       SLSI_ERR(sdev, "no peer for ndp:%d ndi[%d]\n", ndp_id, ndev_vif->nan.ndp_ndi[ndp_id - 1]);
+               }
+               SLSI_MUTEX_UNLOCK(ndev_data_vif->vif_mutex);
+       }
+exit:
+       SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+       slsi_kfree_skb(skb);
+}
+
+void slsi_nan_ndp_requested_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
+{
+       u16 tag_id, tag_len = 0, ndl_vif_id, local_ndp_id;
+       u8  *ptr, *peer_nmi;
+       const u8 *tag_data_ptr;
+       int sig_data_len, res;
+       struct sk_buff *nl_skb;
+       u32 ndp_id;
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+
+       SLSI_DBG3(sdev, SLSI_GSCAN, "\n");
+       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+       sig_data_len = fapi_get_datalen(skb);
+
+#if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE)
+       nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NAN_EVENT_NDP_REQ,
+                                            GFP_KERNEL);
+#else
+       nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NAN_EVENT_NDP_REQ, GFP_KERNEL);
+#endif
+       if (!nl_skb) {
+               SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
+               goto exit;
+       }
+
+       local_ndp_id = fapi_get_u16(skb, u.mlme_ndp_requested_ind.request_id);
+       ndp_id = slsi_nan_get_new_ndp_id(ndev_vif);
+       peer_nmi = fapi_get_buff(skb, u.mlme_ndp_requested_ind.peer_nan_management_interface_address);
+       res = nla_put_u16(nl_skb, NAN_EVT_ATTR_SERVICE_INSTANCE_ID,
+                         fapi_get_u16(skb, u.mlme_ndp_requested_ind.session_id));
+       res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_ADDR, ETH_ALEN, peer_nmi);
+       res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_NDP_INSTANCE_ID, ndp_id);
+       res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_SDEA_PARAM_SECURITY_CONFIG,
+                          fapi_get_u16(skb, u.mlme_ndp_requested_ind.security_required));
+
+       ptr = fapi_get_data(skb);
+       if (ptr) {
+               tag_id = le16_to_cpu(*(u16 *)ptr);
+               tag_len = le16_to_cpu(*(u16 *)(ptr + 2));
+               tag_data_ptr = ptr + 4;
+
+               while (sig_data_len >= tag_len + 4) {
+                       if (tag_id == SLSI_NAN_TLV_TAG_APP_INFO) {
+                               res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_APP_INFO_LEN, tag_len);
+                               res |= nla_put(nl_skb, NAN_EVT_ATTR_APP_INFO, tag_len, tag_data_ptr);
+                               break;
+                       }
+                       sig_data_len -= tag_len + 4;
+                       ptr += tag_len + 4;
+                       if (sig_data_len > 4) {
+                               tag_id = le16_to_cpu(*(u16 *)ptr);
+                               tag_len = le16_to_cpu(*(u16 *)(ptr + 2));
+                               tag_data_ptr = ptr + 4;
+                       } else {
+                               tag_id = 0;
+                               tag_len = 0;
+                       }
+               }
+       }
+
+       if (res) {
+               SLSI_ERR(sdev, "Error in nla_put*:%x\n", res);
+               /* Dont use slsi skb wrapper for this free */
+               kfree_skb(nl_skb);
+               goto exit;
+       }
+
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+       SLSI_INFO(sdev, "Event: %s(%d)\n",
+                 slsi_print_event_name(SLSI_NAN_EVENT_NDP_REQ), SLSI_NAN_EVENT_NDP_REQ);
+#endif
+       ndl_vif_id = slsi_nan_ndp_get_ndl_vif_id(peer_nmi, ndev_vif->nan.ndl_list);
+       if (slsi_nan_ndp_new_entry(sdev, dev, ndp_id, ndl_vif_id, NULL, peer_nmi) == 0) {
+               cfg80211_vendor_event(nl_skb, GFP_KERNEL);
+               ndev_vif->nan.ndp_local_ndp_id[ndp_id - 1] = local_ndp_id;
+       } else {
+               struct slsi_hal_nan_data_path_indication_response response_req;
+
+               kfree_skb(nl_skb);
+               SLSI_ERR(sdev, "invalid ndl_vifid:%d ndp_id:%d\n", ndl_vif_id, ndp_id);
+               memset(&response_req, 0, sizeof(response_req));
+               response_req.rsp_code = NAN_DP_REQUEST_REJECT;
+               slsi_mlme_ndp_response(sdev, dev, &response_req, local_ndp_id);
+       }
+
+exit:
+       SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+       slsi_kfree_skb(skb);
+}
+
+void slsi_nan_del_peer(struct slsi_dev *sdev, struct net_device *dev, u8 *local_ndi, u16 ndp_id)
+{
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+       struct net_device *data_dev;
+       struct netdev_vif *ndev_data_vif;
+       struct slsi_peer *peer = NULL;
+
+       WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
+
+       if (!local_ndi)
+               return;
+
+       data_dev = slsi_get_netdev_by_mac_addr_locked(sdev, local_ndi, SLSI_NAN_DATA_IFINDEX_START);
+       if (!data_dev)
+               return;
+
+       if (ndp_id == 0 || ndp_id > SLSI_NAN_MAX_NDP_INSTANCES)
+               return;
+
+       ndev_data_vif = netdev_priv(data_dev);
+       SLSI_MUTEX_LOCK(ndev_data_vif->vif_mutex);
+       peer = ndev_vif->peer_sta_record[ndp_id - 1];
+       if (peer) {
+               slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED);
+               slsi_spinlock_lock(&ndev_data_vif->peer_lock);
+               slsi_peer_remove(sdev, dev, peer);
+               slsi_spinlock_unlock(&ndev_data_vif->peer_lock);
+       } else {
+               SLSI_ERR(sdev, "no peer for ndp:%d ndi[%pM]\n", ndp_id, ndev_vif->nan.ndp_ndi[ndp_id - 1]);
+       }
+       SLSI_MUTEX_UNLOCK(ndev_data_vif->vif_mutex);
+}
+
+void slsi_nan_ndp_termination_handler(struct slsi_dev *sdev, struct net_device *dev, u16 ndp_id, u16 ndl_vif, u8 *ndi)
+{
+       struct sk_buff *nl_skb;
+
+       slsi_nan_ndp_del_entry(sdev, dev, ndp_id);
+       slsi_nan_del_peer(sdev, dev, ndi, ndp_id);
+
+#if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE)
+       nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NAN_EVENT_NDP_END,
+                                            GFP_KERNEL);
+#else
+       nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NAN_EVENT_NDP_END, GFP_KERNEL);
+#endif
+       if (!nl_skb) {
+               SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
+               return;
+       }
+
+       if (nla_put_u32(nl_skb, NAN_EVT_ATTR_NDP_INSTANCE_ID, ndp_id)) {
+               SLSI_ERR(sdev, "Error in nla_put_u32\n");
+               /* Dont use slsi skb wrapper for this free */
+               kfree_skb(nl_skb);
+               return;
+       }
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+       SLSI_INFO(sdev, "Event: %s(%d)\n",
+                 slsi_print_event_name(SLSI_NAN_EVENT_NDP_END), SLSI_NAN_EVENT_NDP_END);
+#endif
+       cfg80211_vendor_event(nl_skb, GFP_KERNEL);
+}
+
+void slsi_nan_ndp_termination_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb,
+                                 bool is_terminated_ind)
+{
+       u16 ndl_vif_id, ndp_id;
+       u8 *local_ndi;
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+
+       SLSI_DBG3(sdev, SLSI_GSCAN, "\n");
+       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+
+       if (is_terminated_ind) {
+               ndl_vif_id = fapi_get_u16(skb, u.mlme_ndp_terminated_ind.ndl_vif_index);
+               local_ndi = fapi_get_buff(skb, u.mlme_ndp_terminated_ind.local_ndp_interface_address);
+       } else {
+               ndl_vif_id = fapi_get_u16(skb, u.mlme_ndp_terminate_ind.ndl_vif_index);
+               local_ndi = fapi_get_buff(skb, u.mlme_ndp_terminate_ind.local_ndp_interface_address);
+       }
+
+       ndp_id = slsi_nan_get_ndp_from_ndl_local_ndi(dev, ndl_vif_id, local_ndi);
+       if (ndp_id <= SLSI_NAN_MAX_NDP_INSTANCES)
+               slsi_nan_ndp_termination_handler(sdev, dev, ndp_id, ndl_vif_id, local_ndi);
+
+       SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+       slsi_kfree_skb(skb);
 }
index 126ec9f15a7cd42f914e36afbdc16526ff11ad36..33a97cff483067963454d8159b150155840d6fa1 100755 (executable)
 #define SLSI_NAN_TLV_TAG_DATA_PATH_SECURITY        0x010e
 #define SLSI_NAN_TLV_TAG_APP_INFO                  0x010f
 #define SLSI_NAN_TLV_TAG_RANGING                   0x0110
+#define SLSI_NAN_TLV_WFA_IPV6_LOCAL_LINK           0x0000
+
+#define SLSI_NAN_MAX_SERVICE_ID 16
+
+#define SLSI_NAN_MAX_NDP_INSTANCES 8
+#define SLSI_NAN_DATA_IFINDEX_START 5
 
 enum SLSI_NAN_REPLY_ATTRIBUTES {
        NAN_REPLY_ATTR_STATUS_TYPE,
@@ -39,7 +45,17 @@ enum SLSI_NAN_REPLY_ATTRIBUTES {
        NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN,
        NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES,
        NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS,
-       NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN
+       NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN,
+       NAN_REPLY_ATTR_NDP_INSTANCE_ID,
+       NAN_REPLY_ATTR_CAP_MAX_QUEUED_TRANSMIT_FOLLOWUP_MGS,
+       NAN_REPLY_ATTR_CAP_MAX_NDP_SUPPORTED_BANDS,
+       NAN_REPLY_ATTR_CAP_MAX_CIPHER_SUITES_SUPPORTED,
+       NAN_REPLY_ATTR_CAP_MAX_SCID_LEN,
+       NAN_REPLY_ATTR_CAP_NDP_SECURITY_SUPPORTED,
+       NAN_REPLY_ATTR_CAP_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN,
+       NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBE_ADDRESS,
+       NAN_REPLY_ATTR_CAP_NDPE_ATTR_SUPPORTED,
+       NAN_REPLY_ATTR_HAL_TRANSACTION_ID
 };
 
 enum SLSI_NAN_REQ_ATTRIBUTES {
@@ -173,7 +189,20 @@ enum SLSI_NAN_REQ_ATTRIBUTES {
        NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PUBLISH_ID,
        NAN_REQ_ATTR_RANGE_RESPONSE_CFG_REQUESTOR_ID,
        NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PEER_ADDR,
-       NAN_REQ_ATTR_RANGE_RESPONSE_CFG_RANGING_RESPONSE
+       NAN_REQ_ATTR_RANGE_RESPONSE_CFG_RANGING_RESPONSE = 130,
+       NAN_REQ_ATTR_REQ_INSTANCE_ID,
+       NAN_REQ_ATTR_NDP_INSTANCE_ID,
+       NAN_REQ_ATTR_CHAN_REQ_TYPE,
+       NAN_REQ_ATTR_CHAN,
+       NAN_REQ_ATTR_DATA_INTERFACE_NAME_LEN,
+       NAN_REQ_ATTR_DATA_INTERFACE_NAME,
+       NAN_REQ_ATTR_APP_INFO_LEN,
+       NAN_REQ_ATTR_APP_INFO,
+       NAN_REQ_ATTR_SERVICE_NAME_LEN,
+       NAN_REQ_ATTR_SERVICE_NAME = 140,
+       NAN_REQ_ATTR_NDP_RESPONSE_CODE,
+       NAN_REQ_ATTR_USE_NDPE_ATTR,
+       NAN_REQ_ATTR_HAL_TRANSACTION_ID
 };
 
 enum SLSI_NAN_RESP_ATTRIBUTES {
@@ -258,7 +287,18 @@ enum SLSI_NAN_EVT_ATTRIBUTES {
        NAN_EVT_ATTR_RANGE_MEASUREMENT_MM,
        NAN_EVT_ATTR_RANGEING_EVENT_TYPE,
        NAN_EVT_ATTR_SECURITY_CIPHER_TYPE,
-       NAN_EVT_ATTR_STATUS
+       NAN_EVT_ATTR_STATUS,
+       NAN_EVT_ATTR_SERVICE_INSTANCE_ID,
+       NAN_EVT_ATTR_NDP_INSTANCE_ID,
+       NAN_EVT_ATTR_NDP_RSP_CODE,
+       NAN_EVT_ATTR_STATUS_CODE,
+       NAN_EVT_ATTR_CHANNEL_INFO,
+       NAN_EVT_ATTR_APP_INFO_LEN = 70,
+       NAN_EVT_ATTR_APP_INFO,
+       NAN_EVT_ATTR_CHANNEL,
+       NAN_EVT_ATTR_CHANNEL_BW,
+       NAN_EVT_ATTR_CHANNEL_NSS,
+       NAN_EVT_ATTR_HAL_TRANSACTION_ID
 };
 
 #define SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON 0X0003
@@ -294,6 +334,7 @@ enum SLSI_NAN_EVT_ATTRIBUTES {
 #define SLSI_HAL_NAN_MAX_SUBSCRIBE_MAX_ADDRESS 42
 #define SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN 5
 #define SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN 1024
+#define SLSI_HAL_NAN_DP_MAX_APP_INFO_LEN 512
 
 enum slsi_wifi_hal_nan_status_type {
        /* NAN Protocol Response Codes */
@@ -405,7 +446,12 @@ enum slsi_nan_response_type {
        NAN_RESPONSE_TCA                    = 9,
        NAN_RESPONSE_ERROR                  = 10,
        NAN_RESPONSE_BEACON_SDF_PAYLOAD     = 11,
-       NAN_RESPONSE_GET_CAPABILITIES       = 12
+       NAN_RESPONSE_GET_CAPABILITIES       = 12,
+       NAN_DP_INTERFACE_CREATE             = 13,
+       NAN_DP_INTERFACE_DELETE             = 14,
+       NAN_DP_INITIATOR_RESPONSE           = 15,
+       NAN_DP_RESPONDER_RESPONSE           = 16,
+       NAN_DP_END                          = 17
 };
 
 enum slsi_nan_disc_event_type {
@@ -414,6 +460,11 @@ enum slsi_nan_disc_event_type {
        NAN_EVENT_ID_JOINED_CLUSTER
 };
 
+enum slsi_nan_data_path_response_code {
+       NAN_DP_REQUEST_ACCEPT = 0,
+       NAN_DP_REQUEST_REJECT
+};
+
 struct slsi_hal_nan_social_channel_scan_params {
        u8 dwell_time[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS];
        u16 scan_period[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS];
@@ -521,6 +572,7 @@ struct slsi_nan_security_info {
 };
 
 struct slsi_hal_nan_enable_req {
+       u16 transaction_id;
        /* Mandatory parameters below */
        u8 master_pref;
        u16 cluster_low;
@@ -593,6 +645,7 @@ struct slsi_hal_nan_enable_req {
 };
 
 struct slsi_hal_nan_publish_req {
+       u16 transaction_id;
        /* id  0 means new publish, any other id is existing publish */
        u16 publish_id;
        /* how many seconds to run for. 0 means forever until canceled */
@@ -652,6 +705,7 @@ struct slsi_hal_nan_publish_req {
 };
 
 struct slsi_hal_nan_subscribe_req {
+       u16 transaction_id;
        /* id 0 means new subscribe, non zero is existing subscribe */
        u16 subscribe_id;
        /* how many seconds to run for. 0 means forever until canceled */
@@ -751,6 +805,7 @@ struct slsi_hal_nan_subscribe_req {
 };
 
 struct slsi_hal_nan_transmit_followup_req {
+       u16 transaction_id;
        /* Publish or Subscribe Id of an earlier Publish/Subscribe */
        u16 publish_subscribe_id;
 
@@ -778,6 +833,7 @@ struct slsi_hal_nan_transmit_followup_req {
 };
 
 struct slsi_hal_nan_config_req {
+       u16 transaction_id;
        u8 config_sid_beacon;
        u8 sid_beacon;
        u8 config_rssi_proximity;
@@ -833,6 +889,88 @@ struct slsi_hal_nan_config_req {
        u32 dw_5g_interval_val;
        u32 disc_mac_addr_rand_interval_sec;
 
+       /* Values Added from enable Req*/
+       u16 cluster_low;
+       u16 cluster_high;
+
+       u8 config_support_5g;
+       u8 support_5g_val;
+
+       u8 config_2dot4g_rssi_close;
+       u8 rssi_close_2dot4g_val;
+
+       u8 config_2dot4g_rssi_middle;
+       u8 rssi_middle_2dot4g_val;
+       u8 config_hop_count_limit;
+       u8 hop_count_limit_val;
+
+       u8 config_2dot4g_support;
+       u8 support_2dot4g_val;
+
+       u8 config_2dot4g_beacons;
+       u8 beacon_2dot4g_val;
+       u8 config_2dot4g_sdf;
+       u8 sdf_2dot4g_val;
+       u8 config_5g_beacons;
+       u8 beacon_5g_val;
+       u8 config_5g_sdf;
+       u8 sdf_5g_val;
+       u8 config_5g_rssi_close;
+       u8 rssi_close_5g_val;
+       u8 config_5g_rssi_middle;
+       u8 rssi_middle_5g_val;
+
+       /* The 24 bit Organizationally Unique ID + the 8 bit Network Id. */
+       u8 config_oui;
+       u32 oui_val;
+       u8 config_intf_addr;
+       u8 intf_addr_val[ETH_ALEN];
+
+       /* channel frequency in MHz to enable Nan on */
+       u8 config_24g_channel;
+       u32 channel_24g_val;
+};
+
+struct slsi_hal_nan_data_path_cfg {
+       u8 security_cfg;
+       u8 qos_cfg;
+};
+
+struct slsi_hal_nan_data_path_app_info {
+       u16 ndp_app_info_len;
+       u8 ndp_app_info[SLSI_HAL_NAN_DP_MAX_APP_INFO_LEN];
+};
+
+struct slsi_hal_nan_data_path_initiator_req {
+       u16 transaction_id;
+       u32 requestor_instance_id;
+       u8 channel_request_type;
+       u32 channel;
+       u8 peer_disc_mac_addr[ETH_ALEN];
+       char ndp_iface[IFNAMSIZ + 1];
+       struct slsi_hal_nan_data_path_cfg ndp_cfg;
+       struct slsi_hal_nan_data_path_app_info app_info;
+       struct slsi_nan_security_info key_info;
+       u32 service_name_len;
+       u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN];
+};
+
+struct slsi_hal_nan_data_path_indication_response {
+       u16 transaction_id;
+       u32 ndp_instance_id;
+       char ndp_iface[IFNAMSIZ + 1];
+       struct slsi_hal_nan_data_path_cfg ndp_cfg;
+       struct slsi_hal_nan_data_path_app_info app_info;
+       u32 rsp_code;
+       struct slsi_nan_security_info key_info;
+       u8 service_name_len;
+       u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN];
+};
+
+struct slsi_hal_nan_data_end {
+       u16 transaction_id;
+       u8 num_ndp_instances;
+       u32 ndp_instance_id[SLSI_NAN_MAX_NDP_INSTANCES];
 };
 
 struct slsi_hal_nan_capabilities {
@@ -888,6 +1026,36 @@ struct slsi_hal_nan_match_ind {
        u8 sdea_service_specific_info[SLSI_HAL_NAN_MAX_SDEA_SERVICE_SPEC_INFO_LEN];
 };
 
+struct slsi_hal_nan_channel_info {
+       u32 channel;
+       u32 bandwidth;
+       u32 nss;
+};
+
+struct slsi_nan_data_path_request_ind {
+       u16 service_instance_id;
+       u8 peer_disc_mac_addr[ETH_ALEN];
+       u32 ndp_instance_id;
+       struct slsi_hal_nan_data_path_cfg ndp_cfg;
+       struct slsi_hal_nan_data_path_app_info app_info;
+};
+
+#define SLSI_HAL_NAN_MAX_CHANNEL_INFO_SUPPORTED 4
+struct slsi_hal_nan_data_path_confirm_ind {
+       u32 ndp_instance_id;
+       u8 peer_ndi_mac_addr[ETH_ALEN];
+       struct slsi_hal_nan_data_path_app_info app_info;
+       u32 rsp_code;
+       u32 reason_code;
+       u32 num_channels;
+       struct slsi_hal_nan_channel_info channel_info[SLSI_HAL_NAN_MAX_CHANNEL_INFO_SUPPORTED];
+};
+
+struct slsi_hal_nan_data_path_end_ind {
+       u8 num_ndp_instances;
+       u32 ndp_instance_id[SLSI_NAN_MAX_NDP_INSTANCES];
+};
+
 void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb);
 void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb);
 void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb);
@@ -903,4 +1071,19 @@ int slsi_nan_subscribe_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, co
 int slsi_nan_transmit_followup(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
 int slsi_nan_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
 int slsi_nan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_data_iface_create(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_data_iface_delete(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_ndp_initiate(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_ndp_respond(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_ndp_end(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_ndp_new_entry(struct slsi_dev *sdev, struct net_device *dev, u32 ndp_id,
+                          u16 ndl_vif_id, u8 *local_ndi, u8 *peer_nmi);
+void slsi_nan_ndp_del_entry(struct slsi_dev *sdev, struct net_device *dev, u32 ndp_id);
+void slsi_nan_ndp_setup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, bool is_req_ind);
+void slsi_nan_ndp_requested_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb);
+void slsi_nan_ndp_termination_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb,
+                                 bool is_terminated_ind);
+u32 slsi_nan_get_ndp_from_ndl_local_ndi(struct net_device *dev, u16 ndl_vif_id, u8 *local_ndi);
+void slsi_nan_del_peer(struct slsi_dev *sdev, struct net_device *dev, u8 *local_ndi, u16 ndp_id);
+void slsi_nan_ndp_termination_handler(struct slsi_dev *sdev, struct net_device *dev, u16 ndp_id, u16 ndl_vif, u8 *ndi);
 #endif
index 738141f31e3a168eb41c9c3b15dfc92f02cfafba..689446d5b21b4987d6972490cb4191ad15420b75 100755 (executable)
@@ -1097,6 +1097,75 @@ static ssize_t slsi_procfs_nan_mac_addr_read(struct file *file,  char __user *use
        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+static ssize_t slsi_procfs_nan_info_read(struct file *file,  char __user *user_buf, size_t count, loff_t *ppos)
+{
+       char              buf[300];
+       int               pos = 0;
+       const size_t      bufsz = sizeof(buf);
+       struct slsi_dev   *sdev = (struct slsi_dev *)file->private_data;
+       struct net_device *dev = slsi_nan_get_netdev(sdev);
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+       struct slsi_vif_nan *nan_data;
+
+       SLSI_UNUSED_PARAMETER(file);
+
+       SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+       nan_data = &ndev_vif->nan;
+       memset(buf, 0, sizeof(buf));
+
+       pos += scnprintf(buf, bufsz, "NANMACADDRESS,");
+       pos += scnprintf(buf + pos, bufsz - pos, "%pM", nan_data->local_nmi);
+       pos += scnprintf(buf + pos, bufsz, ",CLUSTERID,");
+       pos += scnprintf(buf + pos, bufsz - pos, "%pM", nan_data->cluster_id);
+       pos += scnprintf(buf + pos, bufsz, ",OPERATINGCHANNEL,");
+       if (nan_data->operating_channel[0])
+               pos += scnprintf(buf + pos, bufsz - pos, "%d ", nan_data->operating_channel[0]);
+       if (nan_data->operating_channel[1])
+               pos += scnprintf(buf + pos, bufsz - pos, "%d", nan_data->operating_channel[1]);
+       pos += scnprintf(buf + pos, bufsz, ",ROLE,");
+       pos += scnprintf(buf + pos, bufsz - pos, "%d", nan_data->role);
+       pos += scnprintf(buf + pos, bufsz, ",STATE,");
+       pos += scnprintf(buf + pos, bufsz - pos, "%d", nan_data->state);
+       pos += scnprintf(buf + pos, bufsz, ",MASTERPREFVAL,");
+       pos += scnprintf(buf + pos, bufsz - pos, "%d", nan_data->master_pref_value);
+       pos += scnprintf(buf + pos, bufsz, ",AMT,");
+       pos += scnprintf(buf + pos, bufsz - pos, "%d", nan_data->amt);
+       pos += scnprintf(buf + pos, bufsz, ",HOPCOUNT,");
+       pos += scnprintf(buf + pos, bufsz - pos, "%d", nan_data->hopcount);
+       pos += scnprintf(buf + pos, bufsz, ",NMIRANDOMINTERVAL,");
+       pos += scnprintf(buf + pos, bufsz - pos, "%d", nan_data->random_mac_interval_sec);
+
+       SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t slsi_procfs_nan_exclude_ipv6_addr_tlv_write(struct file *file, const char __user *user_buf, size_t len,
+                                                          loff_t *ppos)
+{
+       struct slsi_dev *sdev = (struct slsi_dev *)file->private_data;
+       struct net_device *dev = slsi_nan_get_netdev(sdev);
+       struct netdev_vif *ndev_vif = netdev_priv(dev);
+       char read_string[3];
+       int  val, ret;
+
+       simple_write_to_buffer(read_string, sizeof(read_string), ppos, user_buf, sizeof(read_string) - 1);
+       read_string[sizeof(read_string) - 1] = '\0';
+
+       if (strtoint(read_string, &val)) {
+               SLSI_ERR(sdev, "invalid input %s\n", read_string);
+               ret = -EINVAL;
+       } else {
+               ndev_vif->nan.disable_cluster_merge = val ? 1 : 0;
+               ret = sizeof(read_string) - 1;
+       }
+
+       kfree(read_string);
+       return ret;
+}
+
+#endif
+
 SLSI_PROCFS_SEQ_FILE_OPS(vifs);
 SLSI_PROCFS_SEQ_FILE_OPS(mac_addr);
 SLSI_PROCFS_WRITE_FILE_OPS(uapsd);
@@ -1120,7 +1189,10 @@ SLSI_PROCFS_READ_FILE_OPS(big_data);
 SLSI_PROCFS_READ_FILE_OPS(throughput_stats);
 SLSI_PROCFS_SEQ_FILE_OPS(tcp_ack_suppression);
 SLSI_PROCFS_READ_FILE_OPS(nan_mac_addr);
-
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+SLSI_PROCFS_READ_FILE_OPS(nan_info);
+SLSI_PROCFS_WRITE_FILE_OPS(nan_exclude_ipv6_addr_tlv);
+#endif
 
 int slsi_create_proc_dir(struct slsi_dev *sdev)
 {
@@ -1158,6 +1230,10 @@ int slsi_create_proc_dir(struct slsi_dev *sdev)
                SLSI_PROCFS_ADD_FILE(sdev, throughput_stats, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
                SLSI_PROCFS_SEQ_ADD_FILE(sdev, tcp_ack_suppression, sdev->procfs_dir, S_IRUSR | S_IRGRP);
                SLSI_PROCFS_ADD_FILE(sdev, nan_mac_addr, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+               SLSI_PROCFS_ADD_FILE(sdev, nan_info, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+               SLSI_PROCFS_ADD_FILE(sdev, nan_exclude_ipv6_addr_tlv, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+#endif
                return 0;
        }
 
@@ -1196,6 +1272,10 @@ void slsi_remove_proc_dir(struct slsi_dev *sdev)
                SLSI_PROCFS_REMOVE_FILE(throughput_stats, sdev->procfs_dir);
                SLSI_PROCFS_REMOVE_FILE(tcp_ack_suppression, sdev->procfs_dir);
                SLSI_PROCFS_REMOVE_FILE(nan_mac_addr, sdev->procfs_dir);
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+               SLSI_PROCFS_REMOVE_FILE(nan_info, sdev->procfs_dir);
+               SLSI_PROCFS_REMOVE_FILE(nan_exclude_ipv6_addr_tlv, sdev->procfs_dir);
+#endif
 
                (void)snprintf(dir, sizeof(dir), "driver/unifi%d", sdev->procfs_instance);
                remove_proc_entry(dir, NULL);
diff --git a/drivers/net/wireless/scsc/reg_info.c b/drivers/net/wireless/scsc/reg_info.c
new file mode 100755 (executable)
index 0000000..911f5cc
--- /dev/null
@@ -0,0 +1,155 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
+ *
+ *****************************************************************************/
+#include "dev.h"
+#include "reg_info.h"
+#include "debug.h"
+
+void slsi_regd_init(struct slsi_dev *sdev)
+{
+       struct ieee80211_regdomain *slsi_world_regdom_custom = sdev->device_config.domain_info.regdomain;
+       struct ieee80211_reg_rule  reg_rules[] = {
+               /* Channel 1 - 11*/
+               REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0),
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+               /* Channel 12 - 13 NO_IR*/
+               REG_RULE(2467 - 10, 2472 + 10, 40, 0, 20, NL80211_RRF_NO_IR),
+#endif
+               /* Channel 36 - 48 */
+               REG_RULE(5180 - 10, 5240 + 10, 80, 0, 20, 0),
+               /* Channel 52 - 64 */
+               REG_RULE(5260 - 10, 5320 + 10, 80, 0, 20, NL80211_RRF_DFS),
+               /* Channel 100 - 140 */
+               REG_RULE(5500 - 10, 5700 + 10, 80, 0, 20, NL80211_RRF_DFS),
+               /* Channel 149 - 165 */
+               REG_RULE(5745 - 10, 5825 + 10, 80, 0, 20, 0),
+       };
+
+       int                        i;
+
+       SLSI_DBG1_NODEV(SLSI_INIT_DEINIT, "regulatory init\n");
+       sdev->regdb.regdb_state = SLSI_REG_DB_NOT_SET;
+       slsi_world_regdom_custom->n_reg_rules = 6;
+       for (i = 0; i < slsi_world_regdom_custom->n_reg_rules; i++)
+               slsi_world_regdom_custom->reg_rules[i] = reg_rules[i];
+
+       /* Country code '00' indicates world regulatory domain */
+       slsi_world_regdom_custom->alpha2[0] = '0';
+       slsi_world_regdom_custom->alpha2[1] = '0';
+
+       wiphy_apply_custom_regulatory(sdev->wiphy, slsi_world_regdom_custom);
+}
+
+void  slsi_regd_deinit(struct slsi_dev *sdev)
+{
+       SLSI_DBG1(sdev, SLSI_INIT_DEINIT, "slsi_regd_deinit\n");
+
+       kfree(sdev->device_config.domain_info.countrylist);
+       sdev->device_config.domain_info.countrylist = NULL;
+       kfree(sdev->regdb.freq_ranges);
+       sdev->regdb.freq_ranges = NULL;
+       kfree(sdev->regdb.reg_rules);
+       sdev->regdb.reg_rules = NULL;
+       kfree(sdev->regdb.rules_collection);
+       sdev->regdb.rules_collection = NULL;
+       kfree(sdev->regdb.country);
+       sdev->regdb.country = NULL;
+}
+
+int slsi_read_regulatory(struct slsi_dev *sdev)
+{
+       struct file *fptr = NULL;
+       char *reg_file_t = "/vendor/etc/wifi/slsi_reg_database.bin";
+       int i = 0, j = 0, index = 0;
+       uint32_t num_freqbands = 0, num_rules = 0, num_collections = 0;
+
+       if (sdev->regdb.regdb_state == SLSI_REG_DB_SET) {
+               SLSI_INFO(sdev, "Regulatory is already set!\n");
+               sdev->regdb.regdb_state = SLSI_REG_DB_ERROR;
+               return 0;
+       }
+
+       fptr = filp_open(reg_file_t, O_RDONLY, 0);
+       if (IS_ERR(fptr) || !fptr) {
+               SLSI_INFO(sdev, "Error! opening file %s\n", reg_file_t);
+               return -EINVAL;
+       }
+
+       kernel_read(fptr, &sdev->regdb.version, sizeof(uint32_t), &fptr->f_pos);
+       kernel_read(fptr, &num_freqbands, sizeof(uint32_t), &fptr->f_pos);
+
+       sdev->regdb.freq_ranges = kmalloc(sizeof(*sdev->regdb.freq_ranges) * num_freqbands, GFP_KERNEL);
+       if (!sdev->regdb.freq_ranges) {
+               SLSI_ERR(sdev, "kmalloc of sdev->regdb->freq_ranges failed\n");
+               sdev->regdb.regdb_state = SLSI_REG_DB_ERROR;
+               return -EINVAL;
+       }
+       for (i = 0; i < num_freqbands; i++)
+               kernel_read(fptr, &sdev->regdb.freq_ranges[i], sizeof(struct regdb_file_freq_range), &fptr->f_pos);
+
+       kernel_read(fptr, &num_rules, sizeof(uint32_t), &fptr->f_pos);
+
+       sdev->regdb.reg_rules = kmalloc(sizeof(*sdev->regdb.reg_rules) * num_rules, GFP_KERNEL);
+       if (!sdev->regdb.reg_rules) {
+               SLSI_ERR(sdev, "kmalloc of sdev->regdb->reg_rules failed\n");
+               kfree(sdev->regdb.freq_ranges);
+               sdev->regdb.freq_ranges = NULL;
+               sdev->regdb.regdb_state = SLSI_REG_DB_ERROR;
+               return -EINVAL;
+       }
+       for (i = 0; i < num_rules; i++) {
+               kernel_read(fptr, &index, sizeof(uint32_t), &fptr->f_pos);
+               sdev->regdb.reg_rules[i].freq_range = &sdev->regdb.freq_ranges[index];
+               kernel_read(fptr, &sdev->regdb.reg_rules[i].max_eirp, sizeof(uint32_t), &fptr->f_pos);
+               kernel_read(fptr, &sdev->regdb.reg_rules[i].flags, sizeof(uint32_t), &fptr->f_pos);
+       }
+
+       kernel_read(fptr, &num_collections, sizeof(uint32_t), &fptr->f_pos);
+
+       sdev->regdb.rules_collection = kmalloc(sizeof(*sdev->regdb.rules_collection) * num_collections, GFP_KERNEL);
+       if (!sdev->regdb.rules_collection) {
+               SLSI_ERR(sdev, "kmalloc of sdev->regdb->rules_collection failed\n");
+               kfree(sdev->regdb.freq_ranges);
+               sdev->regdb.freq_ranges = NULL;
+               kfree(sdev->regdb.reg_rules);
+               sdev->regdb.reg_rules = NULL;
+               sdev->regdb.regdb_state = SLSI_REG_DB_ERROR;
+               return -EINVAL;
+       }
+       for (i = 0; i < num_collections; i++) {
+               kernel_read(fptr, &sdev->regdb.rules_collection[i].reg_rule_num, sizeof(uint32_t), &fptr->f_pos);
+               for (j = 0; j < sdev->regdb.rules_collection[i].reg_rule_num; j++) {
+                       kernel_read(fptr, &index, sizeof(uint32_t), &fptr->f_pos);
+                       sdev->regdb.rules_collection[i].reg_rule[j] = &sdev->regdb.reg_rules[index];
+               }
+       }
+
+       kernel_read(fptr, &sdev->regdb.num_countries, sizeof(uint32_t), &fptr->f_pos);
+       SLSI_INFO(sdev, "Regulatory Version: %d ,Number of Countries: %d\n", sdev->regdb.version, sdev->regdb.num_countries);
+
+       sdev->regdb.country = kmalloc(sizeof(*sdev->regdb.country) * sdev->regdb.num_countries, GFP_KERNEL);
+       if (!sdev->regdb.country) {
+               SLSI_ERR(sdev, "kmalloc of sdev->regdb->country failed\n");
+               kfree(sdev->regdb.freq_ranges);
+               sdev->regdb.freq_ranges = NULL;
+               kfree(sdev->regdb.reg_rules);
+               sdev->regdb.reg_rules = NULL;
+               kfree(sdev->regdb.rules_collection);
+               sdev->regdb.rules_collection = NULL;
+               sdev->regdb.regdb_state = SLSI_REG_DB_ERROR;
+               return -EINVAL;
+       }
+       for (i = 0; i < sdev->regdb.num_countries; i++) {
+               kernel_read(fptr, &sdev->regdb.country[i].alpha2, 2 * sizeof(uint8_t), &fptr->f_pos);
+               kernel_read(fptr, &sdev->regdb.country[i].pad_byte, sizeof(uint8_t), &fptr->f_pos);
+               kernel_read(fptr, &sdev->regdb.country[i].dfs_region, sizeof(uint8_t), &fptr->f_pos);
+               kernel_read(fptr, &index, sizeof(uint32_t), &fptr->f_pos);
+               sdev->regdb.country[i].collection = &sdev->regdb.rules_collection[index];
+       }
+
+       filp_close(fptr, NULL);
+       sdev->regdb.regdb_state = SLSI_REG_DB_SET;
+       return 0;
+}
diff --git a/drivers/net/wireless/scsc/reg_info.h b/drivers/net/wireless/scsc/reg_info.h
new file mode 100755 (executable)
index 0000000..2362a5c
--- /dev/null
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
+ *
+ *****************************************************************************/
+#ifndef __SLSI_REGINFO_H__
+#define __SLSI_REGINFO_H__
+
+int slsi_read_regulatory(struct slsi_dev *sdev);
+void slsi_regd_deinit(struct slsi_dev *sdev);
+void slsi_regd_init(struct slsi_dev *sdev);
+
+enum slsi_regdb_state {
+       SLSI_REG_DB_NOT_SET,
+       SLSI_REG_DB_ERROR,
+       SLSI_REG_DB_SET,
+};
+
+struct reg_database {
+       enum slsi_regdb_state regdb_state;
+       uint32_t version;
+       uint32_t num_countries;
+       struct regdb_file_reg_rule *reg_rules;
+       struct regdb_file_freq_range *freq_ranges;
+       struct regdb_file_reg_rules_collection *rules_collection;
+       struct regdb_file_reg_country *country;
+};
+
+struct regdb_file_freq_range {
+       uint32_t start_freq; /* in MHz */
+       uint32_t end_freq; /* in MHz */
+       uint32_t max_bandwidth; /* in MHz */
+};
+
+struct regdb_file_reg_rule {
+       struct regdb_file_freq_range *freq_range;       /* ptr to regdb_file_freq_range array */
+       uint32_t max_eirp;/* this is power in dBm */
+       uint32_t flags;
+};
+
+struct regdb_file_reg_rules_collection {
+       uint32_t reg_rule_num;
+       /* pointers to struct regdb_file_reg_rule */
+       struct regdb_file_reg_rule *reg_rule[8];
+};
+
+struct regdb_file_reg_country {
+       uint8_t alpha2[2];
+       uint8_t pad_byte;
+       uint8_t dfs_region; /* first two bits define the DFS region */
+       /* pointers to struct regdb_file_reg_rules_collection */
+       struct regdb_file_reg_rules_collection *collection;
+};
+
+#endif
+
index 39784a2718cc3af3e3c3bf68d80b1e54db1b0de2..f411eb06c6787a254c5b5849b2bc1f3dee533f21 100755 (executable)
@@ -387,13 +387,13 @@ void slsi_rx_beacon_reporting_event_ind(struct slsi_dev *sdev, struct net_device
 
        if (!ndev_vif->is_wips_running) {
                SLSI_ERR(sdev, "WIPS is not running. Ignore beacon_reporting_event_ind(%u)\n", reason_code);
+               slsi_kfree_skb(skb);
                return;
        }
 
        ndev_vif->is_wips_running = false;
 
-       if (reason_code >= SLSI_FORWARD_BEACON_ABORT_REASON_UNSPECIFIED &&
-           reason_code <= SLSI_FORWARD_BEACON_ABORT_REASON_SUSPENDED) {
+       if (reason_code <= SLSI_FORWARD_BEACON_ABORT_REASON_SUSPENDED) {
                SLSI_INFO(sdev, "received abort_event from FW with reason(%u)\n", reason_code);
        } else {
                SLSI_ERR(sdev, "received abort_event unsupporting reason(%u)\n", reason_code);
@@ -402,6 +402,7 @@ void slsi_rx_beacon_reporting_event_ind(struct slsi_dev *sdev, struct net_device
        ret = slsi_send_forward_beacon_abort_vendor_event(sdev, reason_code);
        if (ret)
                SLSI_ERR(sdev, "Failed to send forward_beacon_abort_event(err=%d)\n", ret);
+       slsi_kfree_skb(skb);
 }
 
 void slsi_handle_wips_beacon(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb,
@@ -881,10 +882,10 @@ int slsi_set_band_any_auto_channel(struct slsi_dev *sdev, struct netdev_vif  *nd
        struct slsi_acs_chan_info ch_info_5g[MAX_5G_CHANNELS];
        struct slsi_acs_selected_channels acs_selected_channels_5g;
        struct slsi_acs_selected_channels acs_selected_channels_2g;
-       int Best_channel_5g = -1;
-       int Best_channel_5g_num_ap = 0;
-       int Best_channel_2g = -1;
-       int Best_channel_2g_num_ap = 0;
+       int best_channel_5g = -1;
+       int best_channel_5g_num_ap = 0;
+       int best_channel_2g = -1;
+       int best_channel_2g_num_ap = 0;
        int i, ret = 0;
        int j = 0;
 
@@ -900,17 +901,17 @@ int slsi_set_band_any_auto_channel(struct slsi_dev *sdev, struct netdev_vif  *nd
        ret = slsi_set_5g_auto_channel(sdev, ndev_vif, &acs_selected_channels_5g, ch_info_5g);
 
        if(ret == 0) {
-               Best_channel_5g = acs_selected_channels_5g.pri_channel;
+               best_channel_5g = acs_selected_channels_5g.pri_channel;
                for(i = 0; i < MAX_5G_CHANNELS; i++) {
-                       if (ch_info_5g[i].chan == Best_channel_5g) {
-                               Best_channel_5g_num_ap = ch_info_5g[i].num_ap;
+                       if (ch_info_5g[i].chan == best_channel_5g) {
+                               best_channel_5g_num_ap = ch_info_5g[i].num_ap;
                                break;
                        }
                }
-               SLSI_DBG3(sdev, SLSI_MLME, "Best 5G channel = %d, num_ap = %d\n", Best_channel_5g,
-                                                                       Best_channel_5g_num_ap);
+               SLSI_DBG3(sdev, SLSI_MLME, "Best 5G channel = %d, num_ap = %d\n", best_channel_5g,
+                                                                       best_channel_5g_num_ap);
 
-               if (Best_channel_5g_num_ap < MAX_AP_THRESHOLD) {
+               if (best_channel_5g_num_ap < MAX_AP_THRESHOLD) {
                        *acs_selected_channels = acs_selected_channels_5g;
                        return ret;
                }
@@ -918,28 +919,28 @@ int slsi_set_band_any_auto_channel(struct slsi_dev *sdev, struct netdev_vif  *nd
 
        SLSI_DBG3(sdev, SLSI_MLME, "5G AP threshold exceed, trying to select from 2G band\n");
 
-       for(i =0; i < MAX_24G_CHANNELS; i++) {
+       for(i = 0; i < MAX_24G_CHANNELS; i++) {
                ch_info_2g[i] = ch_info[i];
        }
        ret = slsi_set_2g_auto_channel(sdev, ndev_vif, &acs_selected_channels_2g, ch_info_2g);
 
        if(ret == 0) {
-               Best_channel_2g = acs_selected_channels_2g.pri_channel;
-               for(i =0; i < MAX_24G_CHANNELS; i++) {
-                       if (ch_info_2g[i].chan == Best_channel_2g) {
-                               Best_channel_2g_num_ap = ch_info_2g[i].num_ap;
+               best_channel_2g = acs_selected_channels_2g.pri_channel;
+               for(i = 0; i < MAX_24G_CHANNELS; i++) {
+                       if (ch_info_2g[i].chan == best_channel_2g) {
+                               best_channel_2g_num_ap = ch_info_2g[i].num_ap;
                                break;
                        }
                }
-               SLSI_DBG3(sdev, SLSI_MLME, "Best 2G channel = %d, num_ap = %d\n", Best_channel_2g,
-                                                               Best_channel_2g_num_ap);
-               if (Best_channel_5g == -1) {
+               SLSI_DBG3(sdev, SLSI_MLME, "Best 2G channel = %d, num_ap = %d\n", best_channel_2g,
+                                                               best_channel_2g_num_ap);
+               if (best_channel_5g == -1) {
                        *acs_selected_channels = acs_selected_channels_2g;
                        return ret;
                } else {
                        /* Based on min no of APs selecting channel from that band */
                        /* If no. of APs are equal, selecting the 5G channel */
-                       if(Best_channel_5g_num_ap > Best_channel_2g_num_ap)
+                       if(best_channel_5g_num_ap > best_channel_2g_num_ap)
                                *acs_selected_channels = acs_selected_channels_2g;
                        else
                                *acs_selected_channels = acs_selected_channels_5g;
@@ -1010,7 +1011,7 @@ struct slsi_acs_chan_info *slsi_acs_scan_results(struct slsi_dev *sdev, struct n
                idx = slsi_find_chan_idx(scan_channel->hw_value, ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode);
                SLSI_DBG3(sdev, SLSI_MLME, "chan_idx:%d chan_value: %d\n", idx, ch_info[idx].chan);
 
-               if ((idx < 0) || (idx == MAX_CHAN_VALUE_ACS)) {
+               if (idx < 0) {
                        SLSI_DBG3(sdev, SLSI_MLME, "idx is not in range idx=%d\n", idx);
                        goto next_scan;
                }
@@ -1782,6 +1783,7 @@ void slsi_rx_synchronised_ind(struct slsi_dev *sdev, struct net_device *dev, str
        if (r)
                SLSI_NET_DBG1(dev, SLSI_MLME, "cfg80211_external_auth_request failed");
        SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+       slsi_kfree_skb(skb);
 }
 #endif
 
@@ -2000,11 +2002,13 @@ void slsi_rx_connect_ind(struct slsi_dev *sdev, struct net_device *dev, struct s
                        SLSI_INFO(sdev, "Connect failed,Result code:AUTH_NO_ACK\n");
                } else if (fw_result_code == FAPI_RESULTCODE_ASSOC_NO_ACK) {
                        SLSI_INFO(sdev, "Connect failed,Result code:ASSOC_NO_ACK\n");
-               } else if (fw_result_code >= 0x8100 && fw_result_code <= 0x81FF) {
-                       fw_result_code = fw_result_code & 0x00FF;
+               } else if (fw_result_code >= FAPI_RESULTCODE_AUTH_FAILED_CODE && fw_result_code <= 0x81FF) {
+                       if (fw_result_code != FAPI_RESULTCODE_AUTH_FAILED_CODE)
+                               fw_result_code = fw_result_code & 0x00FF;
                        SLSI_INFO(sdev, "Connect failed(Auth failure), Result code:0x%04x\n", fw_result_code);
-               } else if (fw_result_code >= 0x8200 && fw_result_code <= 0x82FF) {
-                       fw_result_code = fw_result_code & 0x00FF;
+               } else if (fw_result_code >= FAPI_RESULTCODE_ASSOC_FAILED_CODE && fw_result_code <= 0x82FF) {
+                       if (fw_result_code != FAPI_RESULTCODE_ASSOC_FAILED_CODE)
+                               fw_result_code = fw_result_code & 0x00FF;
                        SLSI_INFO(sdev, "Connect failed(Assoc Failure), Result code:0x%04x\n", fw_result_code);
                        if (fapi_get_datalen(skb)) {
                                int mgmt_hdr_len;
@@ -2404,9 +2408,10 @@ void slsi_rx_procedure_started_ind(struct slsi_dev *sdev, struct net_device *dev
                break;
        case FAPI_PROCEDURETYPE_DEVICE_DISCOVERED:
                /* Expected only in P2P Device and P2P GO role */
-               if (WARN_ON(!SLSI_IS_VIF_INDEX_P2P(ndev_vif) && (ndev_vif->iftype != NL80211_IFTYPE_P2P_GO)))
+               if (!SLSI_IS_VIF_INDEX_P2P(ndev_vif) && (ndev_vif->iftype != NL80211_IFTYPE_P2P_GO)){
+                       SLSI_NET_DBG1(dev, SLSI_MLME, "PROCEDURETYPE_DEVICE_DISCOVERED recd in non P2P role\n");
                        goto exit_with_lock;
-
+               }
                /* Send probe request to supplicant only if in listening state. Issues were seen earlier if
                 * Probe request was sent to supplicant while waiting for GO Neg Req from peer.
                 * Send Probe request to supplicant if received in GO mode
index f9d3a9d4c81e182e9fa4182389aae50cbb222c02..e6ab78259d5883893dfdce51b2cd8b428e3a51a4 100755 (executable)
@@ -529,7 +529,23 @@ static int slsi_rx_napi_process(struct slsi_dev *sdev, struct sk_buff *skb)
        vif = fapi_get_vif(skb);
 
        rcu_read_lock();
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+       if (vif >= SLSI_NAN_DATA_IFINDEX_START && fapi_get_sigid(skb) == MA_UNITDATA_IND) {
+               struct ethhdr *eth_hdr = (struct ethhdr *)fapi_get_data(skb);
+               u32 data_len = fapi_get_datalen(skb);
+
+               if (!eth_hdr || data_len < sizeof(*eth_hdr)) {
+                       SLSI_WARN(sdev, "Unexpected datalen:%d\n", data_len);
+                       rcu_read_unlock();
+                       return -EINVAL;
+               }
+               dev = slsi_get_netdev_by_mac_addr_lockless(sdev, eth_hdr->h_dest, SLSI_NAN_DATA_IFINDEX_START);
+       } else {
+               dev = slsi_get_netdev_rcu(sdev, vif);
+       }
+#else
        dev = slsi_get_netdev_rcu(sdev, vif);
+#endif
        if (!dev) {
                SLSI_ERR(sdev, "netdev(%d) No longer exists\n", vif);
                rcu_read_unlock();
@@ -630,7 +646,24 @@ static int slsi_rx_queue_data(struct slsi_dev *sdev, struct sk_buff *skb)
        vif = fapi_get_vif(skb);
 
        rcu_read_lock();
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+       if (vif >= SLSI_NAN_DATA_IFINDEX_START && fapi_get_sigid(skb) == MA_UNITDATA_IND) {
+               struct ethhdr *eth_hdr = (struct ethhdr *)fapi_get_data(skb);
+               u32 data_len = fapi_get_datalen(skb);
+
+               if (!eth_hdr || data_len < sizeof(*eth_hdr)) {
+                       SLSI_ERR(sdev, "ma_untidata_ind dropped. datalen:%d\n", data_len);
+                       rcu_read_unlock();
+                       return 0; /* return success */
+               }
+               dev = slsi_get_netdev_by_mac_addr_locked(sdev, eth_hdr->h_dest, SLSI_NAN_DATA_IFINDEX_START);
+       } else {
+               dev = slsi_get_netdev_rcu(sdev, vif);
+       }
+#else
        dev = slsi_get_netdev_rcu(sdev, vif);
+#endif
+
        if (!dev) {
                SLSI_ERR(sdev, "netdev(%d) No longer exists\n", vif);
                rcu_read_unlock();
@@ -702,12 +735,12 @@ static int sap_ma_txdone(struct slsi_dev *sdev, u16 colour)
        /* colour is defined as: */
        /* u16 register bits:
         * 0      - do not use
-        * [2:1]  - vif
-        * [7:3]  - peer_index
+        * [3:1]  - vif
+        * [7:4]  - peer_index
         * [10:8] - ac queue
         */
-       vif = (colour & 0x6) >> 1;
-       peer_index = (colour & 0xf8) >> 3;
+       vif = (colour & 0xE) >> 1;
+       peer_index = (colour & 0xF0) >> 4;
        ac = (colour & 0x300) >> 8;
 
        rcu_read_lock();
index be571434c5ebc3873de0e5f929fe047adf3a3b20..9f3a76a4d996df5dd296dc8b6ad939a45b89c913 100755 (executable)
@@ -54,18 +54,20 @@ static int sap_mlme_notifier(struct slsi_dev *sdev, unsigned long event)
                sdev->mlme_blocked = true;
                /* cleanup all the VIFs and scan data */
                SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex);
+#ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
                level = atomic_read(&sdev->cm_if.reset_level);
                SLSI_INFO_NODEV("MLME BLOCKED system error level:%d\n", level);
+#endif
                complete_all(&sdev->sig_wait.completion);
                /*WLAN system down actions*/
                for (i = 1; i <= CONFIG_SCSC_WLAN_MAX_INTERFACES; i++)
                        if (sdev->netdev[i]) {
                                ndev_vif = netdev_priv(sdev->netdev[i]);
+                               complete_all(&ndev_vif->sig_wait.completion);
                                slsi_scan_cleanup(sdev, sdev->netdev[i]);
 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
-/* For level7 use the older panic flow */
+/* For level8 use the older panic flow */
                                if (level < SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC && ndev_vif->vif_type == FAPI_VIFTYPE_AP) {
-                                       slsi_ap_cleanup(sdev, sdev->netdev[i]);
                                        vif_type_ap = true;
                                }
 #endif
@@ -80,6 +82,8 @@ static int sap_mlme_notifier(struct slsi_dev *sdev, unsigned long event)
 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
                        if (level < SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC)
                                sdev->device_state = SLSI_DEVICE_STATE_STOPPING;
+                       if (sdev->netdev_up_count == 0)
+                               sdev->mlme_blocked = false;
 #endif
                SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex);
                SLSI_INFO_NODEV("Force cleaned all VIFs\n");
@@ -89,7 +93,7 @@ static int sap_mlme_notifier(struct slsi_dev *sdev, unsigned long event)
 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
                level = atomic_read(&sdev->cm_if.reset_level);
                if (level < SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC)
-                       slsi_failure_reset(sdev);
+                       queue_work(sdev->device_wq, &sdev->recovery_work_on_stop);
 #endif
                break;
 
@@ -121,8 +125,8 @@ static int sap_mlme_notifier(struct slsi_dev *sdev, unsigned long event)
                break;
        case SCSC_WIFI_CHIP_READY:
                level = atomic_read(&sdev->cm_if.reset_level);
-               if (level < SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC)
-                       slsi_chip_recovery(sdev);
+               if (level < SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC && sdev->netdev_up_count != 0)
+                       queue_work(sdev->device_wq, &sdev->recovery_work_on_start);
                break;
 #endif
        default:
@@ -229,21 +233,32 @@ static int slsi_rx_netdev_mlme(struct slsi_dev *sdev, struct net_device *dev, st
 #ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
        case MLME_NAN_EVENT_IND:
                slsi_nan_event(sdev, dev, skb);
-               slsi_kfree_skb(skb);
                break;
        case MLME_NAN_FOLLOWUP_IND:
                slsi_nan_followup_ind(sdev, dev, skb);
-               slsi_kfree_skb(skb);
                break;
        case MLME_NAN_SERVICE_IND:
                slsi_nan_service_ind(sdev, dev, skb);
-               slsi_kfree_skb(skb);
+               break;
+       case MLME_NDP_REQUEST_IND:
+               slsi_nan_ndp_setup_ind(sdev, dev, skb, true);
+               break;
+       case MLME_NDP_REQUESTED_IND:
+               slsi_nan_ndp_requested_ind(sdev, dev, skb);
+               break;
+       case MLME_NDP_RESPONSE_IND:
+               slsi_nan_ndp_setup_ind(sdev, dev, skb, false);
+               break;
+       case MLME_NDP_TERMINATE_IND:
+               slsi_nan_ndp_termination_ind(sdev, dev, skb, false);
+               break;
+       case MLME_NDP_TERMINATED_IND:
+               slsi_nan_ndp_termination_ind(sdev, dev, skb, true);
                break;
 #endif
 #ifdef CONFIG_SCSC_WLAN_SAE_CONFIG
        case MLME_SYNCHRONISED_IND:
                slsi_rx_synchronised_ind(sdev, dev, skb);
-               slsi_kfree_skb(skb);
                break;
 #endif
 #ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON
@@ -392,10 +407,17 @@ static int sap_mlme_rx_handler(struct slsi_dev *sdev, struct sk_buff *skb)
                        }
                        return slsi_rx_action_enqueue_netdev_mlme(sdev, skb, vif);
 #ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
                case MLME_NAN_EVENT_IND:
                case MLME_NAN_FOLLOWUP_IND:
                case MLME_NAN_SERVICE_IND:
+               case MLME_NDP_REQUEST_IND:
+               case MLME_NDP_REQUESTED_IND:
+               case MLME_NDP_RESPONSE_IND:
+               case MLME_NDP_TERMINATE_IND:
+               case MLME_NDP_TERMINATED_IND:
                        return slsi_rx_enqueue_netdev_mlme(sdev, skb, vif);
+#endif
                case MLME_RANGE_IND:
                case MLME_RANGE_DONE_IND:
                        if (vif == 0)
index 5068d09244fe9410d04227425306fe462dec1b63..e9d1670c736cf42ae1b773400c647b9afc26fb33 100755 (executable)
@@ -13,7 +13,7 @@
 
 #include <scsc/scsc_mx.h>
 
-#define SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC 7
+#define SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC 8
 
 struct slsi_dev;
 
index c8236ee3e51be783e1a5a7bfc0de92d05fe45464..f8a9d59f51d1c0c8e9172d12c42b266039c6b408 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved
+ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
  *
  *****************************************************************************/
 
@@ -169,11 +169,16 @@ int slsi_tx_data(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *
                SLSI_NET_WARN(dev, "WlanLite: NOT supported\n");
                return -EOPNOTSUPP;
        }
-
-       if (!ndev_vif->activated) {
-               SLSI_NET_WARN(dev, "vif NOT activated\n");
-               return -EINVAL;
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+       if (ndev_vif->ifnum < SLSI_NAN_DATA_IFINDEX_START) {
+#endif
+               if (!ndev_vif->activated) {
+                       SLSI_NET_WARN(dev, "vif NOT activated\n");
+                       return -EINVAL;
+               }
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
        }
+#endif
 
        if ((ndev_vif->vif_type == FAPI_VIFTYPE_AP) && !ndev_vif->peer_sta_records) {
                SLSI_NET_DBG3(dev, SLSI_TX, "AP with no STAs associated, drop Tx frame\n");
@@ -298,12 +303,12 @@ int slsi_tx_data(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *
        /* colour is defined as: */
        /* u16 register bits:
         * 0      - do not use
-        * [2:1]  - vif
-        * [7:3]  - peer_index
+        * [3:1]  - vif
+        * [7:4]  - peer_index
         * [10:8] - ac queue
         */
        cb->colour = (slsi_frame_priority_to_ac_queue(skb->priority) << 8) |
-               (fapi_get_u16(skb, u.ma_unitdata_req.peer_index) << 3) | ndev_vif->ifnum << 1;
+               (fapi_get_u16(skb, u.ma_unitdata_req.peer_index) << 4) | ndev_vif->ifnum << 1;
 
 #ifdef CONFIG_SCSC_WIFILOGGER
        /* Log only the linear skb chunk ... unidata anywya will be truncated to 100.*/
@@ -320,8 +325,8 @@ int slsi_tx_data(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *
                                                          &ndev_vif->ap.group_data_qs,
                                                          slsi_frame_priority_to_ac_queue(skb->priority),
                                                          sdev,
-                                                         (cb->colour & 0x6) >> 1,
-                                                         (cb->colour & 0xf8) >> 3);
+                                                         (cb->colour & 0xE) >> 1,
+                                                         (cb->colour & 0xF0) >> 4);
                        if (ret < 0) {
                                SLSI_NET_WARN(dev, "no fcq for groupcast, drop Tx frame\n");
                                /* Free the local copy here ..if any */
@@ -344,8 +349,8 @@ int slsi_tx_data(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *
                                                           &ndev_vif->ap.group_data_qs,
                                                           slsi_frame_priority_to_ac_queue(skb->priority),
                                                           sdev,
-                                                          (cb->colour & 0x6) >> 1,
-                                                          (cb->colour & 0xf8) >> 3);
+                                                          (cb->colour & 0xE) >> 1,
+                                                          (cb->colour & 0xF0) >> 4);
                                if (original_skb)
                                        slsi_kfree_skb(skb);
                                return ret;
@@ -375,13 +380,26 @@ int slsi_tx_data(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *
        if (peer->qos_enabled)
                fapi_set_u16(skb, u.ma_unitdata_req.priority, skb->priority);
 
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+       /* For NAN vif_index is set to ndl_vif */
+       if (ndev_vif->ifnum >= SLSI_NAN_DATA_IFINDEX_START) {
+               if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
+                       memcpy(eth_hdr(skb)->h_dest, peer->address, ETH_ALEN);
+                       SLSI_NET_DBG1(dev, SLSI_TX, "multicast on NAN interface: changed to peer=%pM\n", eth_hdr(skb)->h_dest);
+               }
+               fapi_set_u16(skb, u.ma_unitdata_req.vif, peer->ndl_vif);
+               cb->colour = (slsi_frame_priority_to_ac_queue(skb->priority) << 8) |
+               (fapi_get_u16(skb, u.ma_unitdata_req.peer_index) << 4) | peer->ndl_vif << 1;
+       }
+#endif
+
        slsi_debug_frame(sdev, dev, skb, "TX");
 
        ret = scsc_wifi_fcq_transmit_data(dev, &peer->data_qs,
                                          slsi_frame_priority_to_ac_queue(skb->priority),
                                          sdev,
-                                         (cb->colour & 0x6) >> 1,
-                                         (cb->colour & 0xf8) >> 3);
+                                         (cb->colour & 0xE) >> 1,
+                                         (cb->colour & 0xF0) >> 4);
        if (ret < 0) {
                SLSI_NET_WARN(dev, "no fcq for %pM, drop Tx frame\n", eth_hdr(skb)->h_dest);
                slsi_spinlock_unlock(&ndev_vif->peer_lock);
@@ -399,8 +417,8 @@ int slsi_tx_data(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *
                /* scsc_wifi_transmit_frame failed, decrement BoT counters */
                scsc_wifi_fcq_receive_data(dev, &peer->data_qs, slsi_frame_priority_to_ac_queue(skb->priority),
                                           sdev,
-                                          (cb->colour & 0x6) >> 1,
-                                          (cb->colour & 0xf8) >> 3);
+                                          (cb->colour & 0xE) >> 1,
+                                          (cb->colour & 0xF0) >> 4);
 
                if (ret == -ENOSPC) {
                        slsi_spinlock_unlock(&ndev_vif->peer_lock);
@@ -474,8 +492,8 @@ int slsi_tx_data_lower(struct slsi_dev *sdev, struct sk_buff *skb)
                if (scsc_wifi_fcq_transmit_data(dev, &ndev_vif->ap.group_data_qs,
                                                slsi_frame_priority_to_ac_queue(skb->priority),
                                                sdev,
-                                               (cb->colour & 0x6) >> 1,
-                                               (cb->colour & 0xf8) >> 3) < 0) {
+                                               (cb->colour & 0xE) >> 1,
+                                               (cb->colour & 0xF0) >> 4) < 0) {
                        SLSI_NET_DBG3(dev, SLSI_TX, "no fcq for groupcast, dropping TX frame\n");
                        return -EINVAL;
                }
@@ -494,8 +512,8 @@ int slsi_tx_data_lower(struct slsi_dev *sdev, struct sk_buff *skb)
                scsc_wifi_fcq_receive_data(dev, &ndev_vif->ap.group_data_qs,
                                           slsi_frame_priority_to_ac_queue(skb->priority),
                                           sdev,
-                                          (cb->colour & 0x6) >> 1,
-                                          (cb->colour & 0xf8) >> 3);
+                                          (cb->colour & 0xE) >> 1,
+                                          (cb->colour & 0xF0) >> 4);
                return ret;
        }
 
@@ -517,8 +535,8 @@ int slsi_tx_data_lower(struct slsi_dev *sdev, struct sk_buff *skb)
        if (scsc_wifi_fcq_transmit_data(dev, &peer->data_qs,
                                        slsi_frame_priority_to_ac_queue(skb->priority),
                                        sdev,
-                                       (cb->colour & 0x6) >> 1,
-                                       (cb->colour & 0xf8) >> 3) < 0) {
+                                       (cb->colour & 0xE) >> 1,
+                                       (cb->colour & 0xF0) >> 4) < 0) {
                SLSI_NET_DBG3(dev, SLSI_TX, "no fcq for %02x:%02x:%02x:%02x:%02x:%02x, dropping TX frame\n",
                              eth_hdr(skb)->h_dest[0], eth_hdr(skb)->h_dest[1], eth_hdr(skb)->h_dest[2], eth_hdr(skb)->h_dest[3], eth_hdr(skb)->h_dest[4], eth_hdr(skb)->h_dest[5]);
                slsi_spinlock_unlock(&ndev_vif->peer_lock);
@@ -534,8 +552,8 @@ int slsi_tx_data_lower(struct slsi_dev *sdev, struct sk_buff *skb)
                scsc_wifi_fcq_receive_data(dev, &ndev_vif->ap.group_data_qs,
                                           slsi_frame_priority_to_ac_queue(skb->priority),
                                           sdev,
-                                          (cb->colour & 0x6) >> 1,
-                                          (cb->colour & 0xf8) >> 3);
+                                          (cb->colour & 0xE) >> 1,
+                                          (cb->colour & 0xF0) >> 4);
                if (ret == -ENOSPC)
                        SLSI_NET_DBG1(dev, SLSI_TX,
                                      "TX_LOWER...Queue Full...BUT Dropping packet\n");
index 278a759ab9f95e1da0075ee232e3978358440a6e..ef242edec746788a5e1d5e7f01e5b9e824087e1b 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved
+ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
  *
  *****************************************************************************/
 
@@ -648,6 +648,38 @@ static inline u32 slsi_get_center_freq1(struct slsi_dev *sdev, u16 chann_info, u
        return center_freq1;
 }
 
+/* Name: strtoint
+ * Desc: Converts a string to a decimal or hexadecimal integer
+ * s: the string to be converted
+ * res: pointer to the calculated integer
+ * return: 0 (success), 1(failure)
+ */
+static inline int strtoint(const char *s, int *res)
+{
+       int base = 10;
+
+       if (strlen(s) > 2)
+               if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+                       base = 16;
+       return kstrtoint(s, base, res);
+}
+
+static inline u8 *slsi_mem_dup(u8 *src, size_t len)
+{
+       u8 *dest;
+
+       dest = kmalloc(len, GFP_KERNEL);
+       if (!dest)
+               return NULL;
+       memcpy(dest, src, len);
+       return dest;
+}
+
+static inline void slsi_get_random_bytes(u8 *byte_buffer, u32 buffer_len)
+{
+       return get_random_bytes(byte_buffer, buffer_len);
+}
+
 #ifdef __cplusplus
 }
 #endif
index b1bbbfc5ceaf54843a7dce3714749bc4e403a3a0..55873d9ac88aa6246e4bfe881748c05402ebf32b 100755 (executable)
@@ -49,6 +49,8 @@
 #define BSMHCP_EVENT_TYPE_NONE                  (0x00)
 #define BSMHCP_EVENT_TYPE_CONNECTED             (0x01)
 #define BSMHCP_EVENT_TYPE_DISCONNECTED          (0x02)
+#define BSMHCP_EVENT_TYPE_IQ_REPORT_ENABLED     (0x03)
+#define BSMHCP_EVENT_TYPE_IQ_REPORT_DISABLED    (0x04)
 
 #define BSMHCP_ACL_BC_FLAG_BCAST_NON            (0x00)
 #define BSMHCP_ACL_BC_FLAG_BCAST_ACTIVE         (0x40)
index f0b705f74298c866858ec6c55e32d52e25a39cf3..3d022b5b1a6960dfc95041ceab34a249475abcd1 100644 (file)
 
 
 #define SCSC_RELEASE_PRODUCT 10
-#define SCSC_RELEASE_ITERATION 6
+#define SCSC_RELEASE_ITERATION 9
 #define SCSC_RELEASE_CANDIDATE 1
 
-#define SCSC_RELEASE_POINT 5
+#define SCSC_RELEASE_POINT 0
 
 #endif