config SCSC_COMMON_HCF
bool "Enable Common HCF loader"
depends on SCSC_CORE
- default n
+ default y
---help---
Enable Common HCF loader
/* 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
#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 */
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;
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");
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;
}
/*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); \
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");
/* 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;
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;
* 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);
/* 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);
/* 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);
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;
/* 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);
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));
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);
/* 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);
}
/* 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);
"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,
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;
"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);
"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);
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);
"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);
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));
static void __iomem *platform_mif_map_region(unsigned long phys_addr, size_t size)
{
- int i;
+ size_t i;
struct page **pages;
void *vmem;
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);
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); \
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++;
}
static void __iomem *platform_mif_map_region(unsigned long phys_addr, size_t size)
{
- int i;
+ size_t i;
struct page **pages;
void *vmem;
#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
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;
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");
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;
}
/*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); \
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");
*/
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,
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));
"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 {
static void __iomem *platform_mif_map_region(unsigned long phys_addr, size_t size)
{
- int i;
+ size_t i;
struct page **pages;
void *vmem;
#include <linux/workqueue.h>
#include <linux/spinlock.h>
#include <scsc/scsc_logring.h>
+#include <linux/timer.h>
/* Implements */
#include "scsc_wifilogger_core.h"
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);
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);
#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)
{
}
/* 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)
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;
}
*/
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 */
#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>
#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
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)
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,
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;
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;
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
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)
{
}
/* 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,
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);
+ }
}
}
}
/* 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",
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);
/* 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 */
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);
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;
}
*/
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 */
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
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.
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
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)
}
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:
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)
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;
}
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");
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;
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");
/* 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;
mutex_unlock(&slsi_start_mutex);
}
+
int slsi_check_rf_test_mode(void)
{
struct file *fp = NULL;
#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)
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);
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);
}
#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;
#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);
}
#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;
#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;
}
#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;
#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)
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 */
#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
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
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 {
/* 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
#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
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);
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
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;
#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
#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
#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
#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
#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
#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
#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
} __packed mlme_nan_config_req;
struct {
__le16 vif;
- __le16 publish_id;
+ __le16 session_id;
__le16 nan_sdf_flags;
__le32 spare_1;
__le32 spare_2;
} __packed mlme_nan_publish_req;
struct {
__le16 vif;
- __le16 subscribe_id;
+ __le16 session_id;
__le16 nan_sdf_flags;
__le32 spare_1;
__le32 spare_2;
} __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;
} __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];
__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;
__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;
} __packed mlme_nan_event_ind;
struct {
__le16 vif;
- __le16 publish_subscribe_id;
+ __le16 session_id;
__le16 match_id;
__le32 ranging_measurement;
__le16 rangingindicationtype;
} __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;
} __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;
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),
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),
#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])) {
/* 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;
/* 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;
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 {
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 {
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]);
{
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;
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]);
#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
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');
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);
} 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
} 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;
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);
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;
}
#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
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))
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
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'))
#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
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,
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,
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);
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++) {
return;
}
- complete_all(&ndev_vif->sig_wait.completion);
-
slsi_scan_cleanup(sdev, dev);
SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
sdev->netdev_up_count--;
SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+ complete_all(&ndev_vif->sig_wait.completion);
slsi_stop_chip(sdev);
}
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;
}
}
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));
}
}
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) {
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? */
/* 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;
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);
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++;
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);
#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*/
}
#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++;
}
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++;
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) {
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;
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);
}
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
}
}
}
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 };
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)
{
/* 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;
}
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);
slsi_update_supported_channels_regd_flags(sdev);
}
-exit:
SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
return error;
}
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;
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]) {
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
}
#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);
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));
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
#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,
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;
}
#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);
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);
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);
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__*/
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)
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
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);
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);
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__*/
#include "debug.h"
#include "mlme.h"
+#include "nl80211_vendor_nan.h"
#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, val) \
{ \
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);
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;
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;
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);
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);
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;
}
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) {
}
}
- 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);
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;
}
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) {
}
}
- 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);
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;
}
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);
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;
/* 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],
}
/* 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],
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);
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;
+}
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)
{
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;
}
#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);
}
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)
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))
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);
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);
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;
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;
}
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;
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;
/*****************************************************************************
*
- * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved
+ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
*
****************************************************************************/
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__*/
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";
}
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));
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;
}
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;
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;
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:
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:
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;
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;
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))
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++) {
{ 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[] = {
.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
{
{
#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,
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,
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,
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 {
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;
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;
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)
}
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;
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,
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))
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:
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)
{
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;
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);
}
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
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;
}
{
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;
}
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)
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) {
ret = -EINVAL;
goto exit;
}
+ transaction_id = hal_req->transaction_id;
SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
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;
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;
}
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) {
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;
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)
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;
}
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)
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) {
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");
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;
}
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);
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);
}
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;
}
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;
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);
!(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;
}
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) {
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;
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;
}
{ 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);
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;
}
}
+ 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)
{
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,
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,
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)
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);
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;
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;
}
#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,
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);
/* 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);
}
#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,
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 {
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 {
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
#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 */
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 {
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];
};
struct slsi_hal_nan_enable_req {
+ u16 transaction_id;
/* Mandatory parameters below */
u8 master_pref;
u16 cluster_low;
};
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 */
};
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 */
};
struct slsi_hal_nan_transmit_followup_req {
+ u16 transaction_id;
/* Publish or Subscribe Id of an earlier Publish/Subscribe */
u16 publish_subscribe_id;
};
struct slsi_hal_nan_config_req {
+ u16 transaction_id;
u8 config_sid_beacon;
u8 sid_beacon;
u8 config_rssi_proximity;
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 {
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);
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
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);
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)
{
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;
}
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);
--- /dev/null
+/******************************************************************************
+ *
+ * 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;
+}
--- /dev/null
+/******************************************************************************
+ *
+ * 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
+
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);
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,
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;
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;
}
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;
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;
}
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
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;
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
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();
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();
/* 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();
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
#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");
#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;
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:
#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
}
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)
#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;
/******************************************************************************
*
- * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved
+ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
*
*****************************************************************************/
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");
/* 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.*/
&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 */
&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;
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);
/* 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);
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;
}
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;
}
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);
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");
/******************************************************************************
*
- * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved
+ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
*
*****************************************************************************/
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
#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)
#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