2015-08-04 12:31:20

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH v2 1/3] mwifiex: add support for 8997 chipset

From: Zhaoyang Liu <[email protected]>

This patch adds support for 8997 chipset to mwifiex
with SDIO/PCIe/USB interface.

The corresponding firmware image files are located in:
"mrvl/sd8997_uapsta.bin"
"mrvl/pcie8997_uapsta.bin"
"mrvl/usb8997_uapsta.bin"

Signed-off-by: Zhaoyang Liu <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/mwifiex/Kconfig | 12 +++----
drivers/net/wireless/mwifiex/pcie.c | 12 +++++--
drivers/net/wireless/mwifiex/pcie.h | 45 ++++++++++++++++++++++++-
drivers/net/wireless/mwifiex/sdio.c | 5 +++
drivers/net/wireless/mwifiex/sdio.h | 65 ++++++++++++++++++++++++++++++++++++
drivers/net/wireless/mwifiex/usb.c | 14 ++++++++
drivers/net/wireless/mwifiex/usb.h | 3 ++
7 files changed, 147 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig
index 48edf38..317d991 100644
--- a/drivers/net/wireless/mwifiex/Kconfig
+++ b/drivers/net/wireless/mwifiex/Kconfig
@@ -9,36 +9,36 @@ config MWIFIEX
mwifiex.

config MWIFIEX_SDIO
- tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897"
+ tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897/SD8997"
depends on MWIFIEX && MMC
select FW_LOADER
select WANT_DEV_COREDUMP
---help---
This adds support for wireless adapters based on Marvell
- 8786/8787/8797/8887/8897 chipsets with SDIO interface.
+ 8786/8787/8797/8887/8897/8997 chipsets with SDIO interface.

If you choose to build it as a module, it will be called
mwifiex_sdio.

config MWIFIEX_PCIE
- tristate "Marvell WiFi-Ex Driver for PCIE 8766/8897"
+ tristate "Marvell WiFi-Ex Driver for PCIE 8766/8897/8997"
depends on MWIFIEX && PCI
select FW_LOADER
select WANT_DEV_COREDUMP
---help---
This adds support for wireless adapters based on Marvell
- 8766/8897 chipsets with PCIe interface.
+ 8766/8897/8997 chipsets with PCIe interface.

If you choose to build it as a module, it will be called
mwifiex_pcie.

config MWIFIEX_USB
- tristate "Marvell WiFi-Ex Driver for USB8766/8797/8897"
+ tristate "Marvell WiFi-Ex Driver for USB8766/8797/8897/8997"
depends on MWIFIEX && USB
select FW_LOADER
---help---
This adds support for wireless adapters based on Marvell
- 8797/8897 chipset with USB interface.
+ 8797/8897/8997 chipset with USB interface.

If you choose to build it as a module, it will be called
mwifiex_usb.
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 33c75d7..408b684 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -266,12 +266,17 @@ static const struct pci_device_id mwifiex_ids[] = {
{
PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- .driver_data = (unsigned long) &mwifiex_pcie8766,
+ .driver_data = (unsigned long)&mwifiex_pcie8766,
},
{
PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8897,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- .driver_data = (unsigned long) &mwifiex_pcie8897,
+ .driver_data = (unsigned long)&mwifiex_pcie8897,
+ },
+ {
+ PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8997,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ .driver_data = (unsigned long)&mwifiex_pcie8997,
},
{},
};
@@ -1082,6 +1087,7 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
card->txbd_rdptr++;
break;
case PCIE_DEVICE_ID_MARVELL_88W8897:
+ case PCIE_DEVICE_ID_MARVELL_88W8997:
card->txbd_rdptr += reg->ring_tx_start_ptr;
break;
}
@@ -1179,6 +1185,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
card->txbd_wrptr++;
break;
case PCIE_DEVICE_ID_MARVELL_88W8897:
+ case PCIE_DEVICE_ID_MARVELL_88W8997:
card->txbd_wrptr += reg->ring_tx_start_ptr;
break;
}
@@ -2733,3 +2740,4 @@ MODULE_VERSION(PCIE_VERSION);
MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE(PCIE8766_DEFAULT_FW_NAME);
MODULE_FIRMWARE(PCIE8897_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(PCIE8997_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h
index 0e7ee8b..48e549c 100644
--- a/drivers/net/wireless/mwifiex/pcie.h
+++ b/drivers/net/wireless/mwifiex/pcie.h
@@ -30,10 +30,12 @@

#define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin"
#define PCIE8897_DEFAULT_FW_NAME "mrvl/pcie8897_uapsta.bin"
+#define PCIE8997_DEFAULT_FW_NAME "mrvl/pcie8997_uapsta.bin"

#define PCIE_VENDOR_ID_MARVELL (0x11ab)
#define PCIE_DEVICE_ID_MARVELL_88W8766P (0x2b30)
#define PCIE_DEVICE_ID_MARVELL_88W8897 (0x2b38)
+#define PCIE_DEVICE_ID_MARVELL_88W8997 (0x2b42)

/* Constants for Buffer Descriptor (BD) rings */
#define MWIFIEX_MAX_TXRX_BD 0x20
@@ -197,7 +199,38 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = {
.sleep_cookie = 0,
.fw_dump_ctrl = 0xcf4,
.fw_dump_start = 0xcf8,
- .fw_dump_end = 0xcff
+ .fw_dump_end = 0xcff,
+};
+
+static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = {
+ .cmd_addr_lo = PCIE_SCRATCH_0_REG,
+ .cmd_addr_hi = PCIE_SCRATCH_1_REG,
+ .cmd_size = PCIE_SCRATCH_2_REG,
+ .fw_status = PCIE_SCRATCH_3_REG,
+ .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
+ .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
+ .tx_rdptr = 0xC1A4,
+ .tx_wrptr = 0xC1A8,
+ .rx_rdptr = 0xC1A8,
+ .rx_wrptr = 0xC1A4,
+ .evt_rdptr = PCIE_SCRATCH_10_REG,
+ .evt_wrptr = PCIE_SCRATCH_11_REG,
+ .drv_rdy = PCIE_SCRATCH_12_REG,
+ .tx_start_ptr = 16,
+ .tx_mask = 0x0FFF0000,
+ .tx_wrap_mask = 0x01FF0000,
+ .rx_mask = 0x00000FFF,
+ .rx_wrap_mask = 0x000001FF,
+ .tx_rollover_ind = BIT(28),
+ .rx_rollover_ind = BIT(12),
+ .evt_rollover_ind = MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND,
+ .ring_flag_sop = MWIFIEX_BD_FLAG_SOP,
+ .ring_flag_eop = MWIFIEX_BD_FLAG_EOP,
+ .ring_flag_xs_sop = MWIFIEX_BD_FLAG_XS_SOP,
+ .ring_flag_xs_eop = MWIFIEX_BD_FLAG_XS_EOP,
+ .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR,
+ .pfu_enabled = 1,
+ .sleep_cookie = 0,
};

struct mwifiex_pcie_device {
@@ -227,6 +260,15 @@ static const struct mwifiex_pcie_device mwifiex_pcie8897 = {
.can_ext_scan = true,
};

+static const struct mwifiex_pcie_device mwifiex_pcie8997 = {
+ .firmware = PCIE8997_DEFAULT_FW_NAME,
+ .reg = &mwifiex_reg_8997,
+ .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
+ .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
+ .can_dump_fw = false,
+ .can_ext_scan = true,
+};
+
struct mwifiex_evt_buf_desc {
u64 paddr;
u16 len;
@@ -325,6 +367,7 @@ mwifiex_pcie_txbd_not_full(struct pcie_service_card *card)
return 1;
break;
case PCIE_DEVICE_ID_MARVELL_88W8897:
+ case PCIE_DEVICE_ID_MARVELL_88W8997:
if (((card->txbd_wrptr & reg->tx_mask) !=
(card->txbd_rdptr & reg->tx_mask)) ||
((card->txbd_wrptr & reg->tx_rollover_ind) ==
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index e4c35ee..9904a77 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -288,6 +288,8 @@ static int mwifiex_sdio_suspend(struct device *dev)
#define SDIO_DEVICE_ID_MARVELL_8887 (0x9135)
/* Device ID for SD8801 */
#define SDIO_DEVICE_ID_MARVELL_8801 (0x9139)
+/* Device ID for SD8997 */
+#define SDIO_DEVICE_ID_MARVELL_8997 (0x9141)


/* WLAN IDs */
@@ -304,6 +306,8 @@ static const struct sdio_device_id mwifiex_ids[] = {
.driver_data = (unsigned long)&mwifiex_sdio_sd8887},
{SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8801),
.driver_data = (unsigned long)&mwifiex_sdio_sd8801},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8997),
+ .driver_data = (unsigned long)&mwifiex_sdio_sd8997},
{},
};

@@ -2531,3 +2535,4 @@ MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8897_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8887_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(SD8997_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index c44da61..cd149196 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -35,6 +35,7 @@
#define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin"
#define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin"
#define SD8801_DEFAULT_FW_NAME "mrvl/sd8801_uapsta.bin"
+#define SD8997_DEFAULT_FW_NAME "mrvl/sd8997_uapsta.bin"

#define BLOCK_MODE 1
#define BYTE_MODE 0
@@ -364,6 +365,55 @@ static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8897 = {
0x59, 0x5c, 0x5d},
};

+static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8997 = {
+ .start_rd_port = 0,
+ .start_wr_port = 0,
+ .base_0_reg = 0xF8,
+ .base_1_reg = 0xF9,
+ .poll_reg = 0x5C,
+ .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+ CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+ .host_int_rsr_reg = 0x4,
+ .host_int_status_reg = 0x0C,
+ .host_int_mask_reg = 0x08,
+ .status_reg_0 = 0xE8,
+ .status_reg_1 = 0xE9,
+ .sdio_int_mask = 0xff,
+ .data_port_mask = 0xffffffff,
+ .io_port_0_reg = 0xE4,
+ .io_port_1_reg = 0xE5,
+ .io_port_2_reg = 0xE6,
+ .max_mp_regs = 196,
+ .rd_bitmap_l = 0x10,
+ .rd_bitmap_u = 0x11,
+ .rd_bitmap_1l = 0x12,
+ .rd_bitmap_1u = 0x13,
+ .wr_bitmap_l = 0x14,
+ .wr_bitmap_u = 0x15,
+ .wr_bitmap_1l = 0x16,
+ .wr_bitmap_1u = 0x17,
+ .rd_len_p0_l = 0x18,
+ .rd_len_p0_u = 0x19,
+ .card_misc_cfg_reg = 0xd8,
+ .card_cfg_2_1_reg = 0xd9,
+ .cmd_rd_len_0 = 0xc0,
+ .cmd_rd_len_1 = 0xc1,
+ .cmd_rd_len_2 = 0xc2,
+ .cmd_rd_len_3 = 0xc3,
+ .cmd_cfg_0 = 0xc4,
+ .cmd_cfg_1 = 0xc5,
+ .cmd_cfg_2 = 0xc6,
+ .cmd_cfg_3 = 0xc7,
+ .func1_dump_reg_start = 0x10,
+ .func1_dump_reg_end = 0x17,
+ .func1_scratch_reg = 0xe8,
+ .func1_spec_reg_num = 13,
+ .func1_spec_reg_table = {0x08, 0x58, 0x5C, 0x5D,
+ 0x60, 0x61, 0x62, 0x64,
+ 0x65, 0x66, 0x68, 0x69,
+ 0x6a},
+};
+
static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8887 = {
.start_rd_port = 0,
.start_wr_port = 0,
@@ -472,6 +522,21 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = {
.can_ext_scan = true,
};

+static const struct mwifiex_sdio_device mwifiex_sdio_sd8997 = {
+ .firmware = SD8997_DEFAULT_FW_NAME,
+ .reg = &mwifiex_reg_sd8997,
+ .max_ports = 32,
+ .mp_agg_pkt_limit = 16,
+ .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
+ .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
+ .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
+ .supports_sdio_new_mode = true,
+ .has_control_mask = false,
+ .can_dump_fw = false,
+ .can_auto_tdls = false,
+ .can_ext_scan = true,
+};
+
static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = {
.firmware = SD8887_DEFAULT_FW_NAME,
.reg = &mwifiex_reg_sd8887,
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index fbad99c..6eabd95 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -47,6 +47,11 @@ static struct usb_device_id mwifiex_usb_table[] = {
{USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8897_PID_2,
USB_CLASS_VENDOR_SPEC,
USB_SUBCLASS_VENDOR_SPEC, 0xff)},
+ /* 8997 */
+ {USB_DEVICE(USB8XXX_VID, USB8997_PID_1)},
+ {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8997_PID_2,
+ USB_CLASS_VENDOR_SPEC,
+ USB_SUBCLASS_VENDOR_SPEC, 0xff)},
{ } /* Terminating entry */
};

@@ -382,12 +387,14 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
case USB8797_PID_1:
case USB8801_PID_1:
case USB8897_PID_1:
+ case USB8997_PID_1:
card->usb_boot_state = USB8XXX_FW_DNLD;
break;
case USB8766_PID_2:
case USB8797_PID_2:
case USB8801_PID_2:
case USB8897_PID_2:
+ case USB8997_PID_2:
card->usb_boot_state = USB8XXX_FW_READY;
break;
default:
@@ -814,6 +821,12 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
adapter->dev = &card->udev->dev;

switch (le16_to_cpu(card->udev->descriptor.idProduct)) {
+ case USB8997_PID_1:
+ case USB8997_PID_2:
+ adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
+ strcpy(adapter->fw_name, USB8997_DEFAULT_FW_NAME);
+ adapter->ext_scan = true;
+ break;
case USB8897_PID_1:
case USB8897_PID_2:
adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
@@ -1121,3 +1134,4 @@ MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME);
MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME);
MODULE_FIRMWARE(USB8801_DEFAULT_FW_NAME);
MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(USB8997_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h
index 57e1a57..f0051f8 100644
--- a/drivers/net/wireless/mwifiex/usb.h
+++ b/drivers/net/wireless/mwifiex/usb.h
@@ -32,6 +32,8 @@
#define USB8897_PID_2 0x2046
#define USB8801_PID_1 0x2049
#define USB8801_PID_2 0x204a
+#define USB8997_PID_1 0x204d
+#define USB8997_PID_2 0x204e


#define USB8XXX_FW_DNLD 1
@@ -46,6 +48,7 @@
#define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin"
#define USB8801_DEFAULT_FW_NAME "mrvl/usb8801_uapsta.bin"
#define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin"
+#define USB8997_DEFAULT_FW_NAME "mrvl/usb8997_uapsta.bin"

#define FW_DNLD_TX_BUF_SIZE 620
#define FW_DNLD_RX_BUF_SIZE 2048
--
1.8.1.4



2015-08-05 13:08:10

by Amitkumar Karwar

[permalink] [raw]
Subject: RE: [PATCH v2 3/3] mwifiex: fix unable to connect hidden SSID AP on DFS channel

SGkgUGF1bCwNCg0KPiA+ICsgICAgICAgaWYgKG13aWZpZXhfaXNfaGlkZGVuX3NzaWQoJmJzc19k
ZXNjLT5zc2lkKSkgew0KPiA+ICsgICAgICAgICAgICAgICBtd2lmaWV4X2RiZyhwcml2LT5hZGFw
dGVyLCBJTkZPLCAiZm91bmQgaGlkZGVuDQo+IFNTSURcbiIpOw0KPiA+ICsgICAgICAgICAgICAg
ICBmb3IgKGNoaWQgPSAwIDsgY2hpZCA8IE1XSUZJRVhfVVNFUl9TQ0FOX0NIQU5fTUFYOw0KPiBj
aGlkKyspIHsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJpdi0+aGlkZGVuX2No
YW5bY2hpZF0uY2hhbl9udW1iZXIgPT0gMCkNCj4gew0KPiA+ICsgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgcHJpdi0+aGlkZGVuX2NoYW5bY2hpZF0uY2hhbl9udW1iZXIgPQ0KPiA+ICsg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBic3MtPmNoYW5uZWwtPmh3X3Zh
bHVlOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpdi0+aGlkZGVuX2No
YW5bY2hpZF0ucmFkaW9fdHlwZSA9DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIGJzcy0+Y2hhbm5lbC0+YmFuZDsNCj4gPiArICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIHByaXYtPmhpZGRlbl9jaGFuW2NoaWRdLnNjYW5fdHlwZSA9DQo+ID4gKyAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1XSUZJRVhfU0NBTl9UWVBFX0FDVElW
RTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KPiBEb2VzIHRo
aXMgbWVhbiBhbiBlbnRyeSB3aWxsIGJlIGNyZWF0ZWQgaW4gcHJpdi0+aGlkZGVuX2NoYW4gZm9y
IGVhY2gNCj4gaGlkZGVuIEJTUywgZXZlbiBpZiBtdWx0aXBsZSBvZiB0aGVtIGV4aXN0IG9uIG9u
ZSBjaGFubmVsPw0KDQpZZXMuIFRoYW5rcyBmb3IgcG9pbnRpbmcgdGhpcyBvdXQuIEkgd2lsbCBz
ZW5kIHVwZGF0ZWQgdmVyc2lvbiB3aXRoIGNvdXBsZSBvZiBvdGhlciBjb3JyZWN0aW9ucy4NCg0K
UmVnYXJkcywNCkFtaXQNCg==

2015-08-04 19:39:08

by Paul Stewart

[permalink] [raw]
Subject: Re: [PATCH v2 3/3] mwifiex: fix unable to connect hidden SSID AP on DFS channel

On Tue, Aug 4, 2015 at 5:30 AM, Amitkumar Karwar <[email protected]> wrote:
> From: chunfan chen <[email protected]>
>
> We will check if any hidden SSID found in passive scan channels
> and do specific SSID active scan for those channels.
>
> Signed-off-by: chunfan chen <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>
> ---
> v2: Corrected hidden SSID detection logic as per Paul Stewart's comment.
> ---
> drivers/net/wireless/mwifiex/fw.h | 1 +
> drivers/net/wireless/mwifiex/init.c | 2 +-
> drivers/net/wireless/mwifiex/main.h | 2 +
> drivers/net/wireless/mwifiex/scan.c | 136 +++++++++++++++++++++++++++++++++---
> 4 files changed, 129 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
> index 9a8c1832..3ec2ac8 100644
> --- a/drivers/net/wireless/mwifiex/fw.h
> +++ b/drivers/net/wireless/mwifiex/fw.h
> @@ -685,6 +685,7 @@ struct mwifiex_fw_chan_stats {
> enum mwifiex_chan_scan_mode_bitmasks {
> MWIFIEX_PASSIVE_SCAN = BIT(0),
> MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
> + MWIFIEX_HIDDEN_SSID_REPORT = BIT(4),
> };
>
> struct mwifiex_chan_scan_param_set {
> diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
> index 7a970c2..5d3ae63 100644
> --- a/drivers/net/wireless/mwifiex/init.c
> +++ b/drivers/net/wireless/mwifiex/init.c
> @@ -301,7 +301,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
> adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM;
> adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM;
> adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
> -
> + adapter->active_scan_triggered = false;
> setup_timer(&adapter->wakeup_timer, wakeup_timer_fn,
> (unsigned long)adapter);
> }
> diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
> index face747..6b95121 100644
> --- a/drivers/net/wireless/mwifiex/main.h
> +++ b/drivers/net/wireless/mwifiex/main.h
> @@ -666,6 +666,7 @@ struct mwifiex_private {
> struct mwifiex_11h_intf_state state_11h;
> struct mwifiex_ds_mem_rw mem_rw;
> struct sk_buff_head bypass_txq;
> + struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX];
> };
>
>
> @@ -986,6 +987,7 @@ struct mwifiex_adapter {
> u8 coex_tx_win_size;
> u8 coex_rx_win_size;
> bool drcs_enabled;
> + u8 active_scan_triggered;
> };
>
> void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
> diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
> index ef8da8e..47e9253 100644
> --- a/drivers/net/wireless/mwifiex/scan.c
> +++ b/drivers/net/wireless/mwifiex/scan.c
> @@ -527,7 +527,8 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
>
> if (ch->flags & IEEE80211_CHAN_NO_IR)
> scan_chan_list[chan_idx].chan_scan_mode_bitmap
> - |= MWIFIEX_PASSIVE_SCAN;
> + |= (MWIFIEX_PASSIVE_SCAN |
> + MWIFIEX_HIDDEN_SSID_REPORT);
> else
> scan_chan_list[chan_idx].chan_scan_mode_bitmap
> &= ~MWIFIEX_PASSIVE_SCAN;
> @@ -1049,7 +1050,8 @@ mwifiex_config_scan(struct mwifiex_private *priv,
> if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
> (scan_chan_list +
> chan_idx)->chan_scan_mode_bitmap
> - |= MWIFIEX_PASSIVE_SCAN;
> + |= (MWIFIEX_PASSIVE_SCAN |
> + MWIFIEX_HIDDEN_SSID_REPORT);
> else
> (scan_chan_list +
> chan_idx)->chan_scan_mode_bitmap
> @@ -1600,6 +1602,58 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
> return ret;
> }
>
> +/* This function checks if SSID string contains all zeroes or length is zero */
> +static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
> +{
> + int idx;
> +
> + for (idx = 0; idx < ssid->ssid_len; idx++) {
> + if (ssid->ssid[idx])
> + return false;
> + }
> +
> + return true;
> +}
> +
> +/* This function checks if any hidden SSID found in passive scan channels
> + * and save those channels for specific SSID active scan
> + */
> +static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
> + struct cfg80211_bss *bss)
> +{
> + struct mwifiex_bssdescriptor *bss_desc;
> + int ret;
> + int chid;
> +
> + /* Allocate and fill new bss descriptor */
> + bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
> + if (!bss_desc)
> + return -ENOMEM;
> +
> + ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
> + if (ret)
> + goto done;
> +
> + if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
> + mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
> + for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
> + if (priv->hidden_chan[chid].chan_number == 0) {
> + priv->hidden_chan[chid].chan_number =
> + bss->channel->hw_value;
> + priv->hidden_chan[chid].radio_type =
> + bss->channel->band;
> + priv->hidden_chan[chid].scan_type =
> + MWIFIEX_SCAN_TYPE_ACTIVE;
> + break;
Does this mean an entry will be created in priv->hidden_chan for each
hidden BSS, even if multiple of them exist on one channel?
> + }
> + }
> + }
> +
> +done:
> + kfree(bss_desc);
> + return 0;
> +}
> +
> static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
> struct cfg80211_bss *bss)
> {
> @@ -1789,6 +1843,14 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
> .mac_address, ETH_ALEN))
> mwifiex_update_curr_bss_params(priv, bss);
> cfg80211_put_bss(priv->wdev.wiphy, bss);
> +
> + if ((chan->flags & IEEE80211_CHAN_RADAR) ||
> + (chan->flags & IEEE80211_CHAN_NO_IR)) {
> + mwifiex_dbg(adapter, INFO,
> + "radar or passive channel %d\n",
> + channel);
> + mwifiex_save_hidden_ssid_channels(priv, bss);
> + }
> }
> } else {
> mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
> @@ -1812,6 +1874,54 @@ static void mwifiex_complete_scan(struct mwifiex_private *priv)
> }
> }
>
> +/* This function checks if any hidden SSID found in passive scan channels
> + * and do specific SSID active scan for those channels
> + */
> +static int
> +mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
> +{
> + int ret;
> + struct mwifiex_adapter *adapter = priv->adapter;
> + u8 id = 0;
> + struct mwifiex_user_scan_cfg *user_scan_cfg;
> +
> + if (adapter->active_scan_triggered) {
> + adapter->active_scan_triggered = false;
> + return 0;
> + }
> +
> + if (priv->hidden_chan[0].chan_number == 0) {
> + mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
> + return 0;
> + }
> + user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
> +
> + if (!user_scan_cfg)
> + return -ENOMEM;
> +
> + memset(user_scan_cfg, 0, sizeof(*user_scan_cfg));
> +
> + for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++)
> + memcpy(&user_scan_cfg->chan_list[id],
> + &priv->hidden_chan[id],
> + sizeof(struct mwifiex_user_scan_chan));
> +
> + adapter->active_scan_triggered = true;
> + user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
> + user_scan_cfg->ssid_list = priv->scan_request->ssids;
> +
> + ret = mwifiex_scan_networks(priv, user_scan_cfg);
> + kfree(user_scan_cfg);
> +
> + memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
> +
> + if (ret) {
> + dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
> {
> struct mwifiex_adapter *adapter = priv->adapter;
> @@ -1825,6 +1935,8 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
> adapter->scan_processing = false;
> spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
>
> + mwifiex_active_scan_req_for_passive_chan(priv);
> +
> if (!adapter->ext_scan)
> mwifiex_complete_scan(priv);
>
> @@ -1851,15 +1963,17 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
> adapter->scan_processing = false;
> spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
>
> - if (priv->scan_request) {
> - mwifiex_dbg(adapter, INFO,
> - "info: aborting scan\n");
> - cfg80211_scan_done(priv->scan_request, 1);
> - priv->scan_request = NULL;
> - } else {
> - priv->scan_aborting = false;
> - mwifiex_dbg(adapter, INFO,
> - "info: scan already aborted\n");
> + if (!adapter->active_scan_triggered) {
> + if (priv->scan_request) {
> + mwifiex_dbg(adapter, INFO,
> + "info: aborting scan\n");
> + cfg80211_scan_done(priv->scan_request, 1);
> + priv->scan_request = NULL;
> + } else {
> + priv->scan_aborting = false;
> + mwifiex_dbg(adapter, INFO,
> + "info: scan already aborted\n");
> + }
> }
> } else {
> /* Get scan command from scan_pending_q and put to
> --
> 1.8.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2015-08-04 12:31:23

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH v2 2/3] mwifiex: add firmware dump support for SD8997

From: Zhaoyang Liu <[email protected]>

This patch adds firmware dump feature for SD8997 chipset.
The difference here is only one memory type is needed
to save all firmware information. Device dump information
will be uploaded to usersapace file.

Signed-off-by: Zhaoyang Liu <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/mwifiex/sdio.c | 147 +++++++++++++++++++++++++++++++++---
drivers/net/wireless/mwifiex/sdio.h | 11 ++-
2 files changed, 148 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 9904a77..7cef27e9 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -51,6 +51,10 @@ static unsigned long iface_work_flags;

static struct semaphore add_remove_card_sem;

+static struct memory_type_mapping generic_mem_type_map[] = {
+ {"DUMP", NULL, 0, 0xDD},
+};
+
static struct memory_type_mapping mem_type_mapping_tbl[] = {
{"ITCM", NULL, 0, 0xF0},
{"DTCM", NULL, 0, 0xF1},
@@ -108,6 +112,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size;
card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size;
card->can_dump_fw = data->can_dump_fw;
+ card->fw_dump_enh = data->fw_dump_enh;
card->can_auto_tdls = data->can_auto_tdls;
card->can_ext_scan = data->can_ext_scan;
}
@@ -1969,8 +1974,13 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
adapter->dev = &func->dev;

strcpy(adapter->fw_name, card->firmware);
- adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
- adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
+ if (card->fw_dump_enh) {
+ adapter->mem_type_mapping_tbl = generic_mem_type_map;
+ adapter->num_mem_types = 1;
+ } else {
+ adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
+ adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
+ }

return 0;
}
@@ -2163,8 +2173,8 @@ rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
int ret, tries;
u8 ctrl_data = 0;

- sdio_writeb(card->func, FW_DUMP_HOST_READY, card->reg->fw_dump_ctrl,
- &ret);
+ sdio_writeb(card->func, card->reg->fw_dump_host_ready,
+ card->reg->fw_dump_ctrl, &ret);
if (ret) {
mwifiex_dbg(adapter, ERROR, "SDIO Write ERR\n");
return RDWR_STATUS_FAILURE;
@@ -2180,10 +2190,10 @@ rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
break;
if (doneflag && ctrl_data == doneflag)
return RDWR_STATUS_DONE;
- if (ctrl_data != FW_DUMP_HOST_READY) {
+ if (ctrl_data != card->reg->fw_dump_host_ready) {
mwifiex_dbg(adapter, WARN,
- "The ctrl reg was changed, re-try again!\n");
- sdio_writeb(card->func, FW_DUMP_HOST_READY,
+ "The ctrl reg was changed, re-try again\n");
+ sdio_writeb(card->func, card->reg->fw_dump_host_ready,
card->reg->fw_dump_ctrl, &ret);
if (ret) {
mwifiex_dbg(adapter, ERROR, "SDIO write err\n");
@@ -2192,7 +2202,7 @@ rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
}
usleep_range(100, 200);
}
- if (ctrl_data == FW_DUMP_HOST_READY) {
+ if (ctrl_data == card->reg->fw_dump_host_ready) {
mwifiex_dbg(adapter, ERROR,
"Fail to pull ctrl_data\n");
return RDWR_STATUS_FAILURE;
@@ -2325,10 +2335,129 @@ done:
sdio_release_host(card->func);
}

+static void mwifiex_sdio_generic_fw_dump(struct mwifiex_adapter *adapter)
+{
+ struct sdio_mmc_card *card = adapter->card;
+ struct memory_type_mapping *entry = &generic_mem_type_map[0];
+ unsigned int reg, reg_start, reg_end;
+ u8 start_flag = 0, done_flag = 0;
+ u8 *dbg_ptr, *end_ptr;
+ enum rdwr_status stat;
+ int ret = -1, tries;
+
+ if (!card->fw_dump_enh)
+ return;
+
+ if (entry->mem_ptr) {
+ vfree(entry->mem_ptr);
+ entry->mem_ptr = NULL;
+ }
+ entry->mem_size = 0;
+
+ mwifiex_pm_wakeup_card(adapter);
+ sdio_claim_host(card->func);
+
+ mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
+
+ stat = mwifiex_sdio_rdwr_firmware(adapter, done_flag);
+ if (stat == RDWR_STATUS_FAILURE)
+ goto done;
+
+ reg_start = card->reg->fw_dump_start;
+ reg_end = card->reg->fw_dump_end;
+ for (reg = reg_start; reg <= reg_end; reg++) {
+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+ start_flag = sdio_readb(card->func, reg, &ret);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR,
+ "SDIO read err\n");
+ goto done;
+ }
+ if (start_flag == 0)
+ break;
+ if (tries == MAX_POLL_TRIES) {
+ mwifiex_dbg(adapter, ERROR,
+ "FW not ready to dump\n");
+ ret = -1;
+ goto done;
+ }
+ }
+ usleep_range(100, 200);
+ }
+
+ entry->mem_ptr = vmalloc(0xf0000 + 1);
+ if (!entry->mem_ptr) {
+ ret = -1;
+ goto done;
+ }
+ dbg_ptr = entry->mem_ptr;
+ entry->mem_size = 0xf0000;
+ end_ptr = dbg_ptr + entry->mem_size;
+
+ done_flag = entry->done_flag;
+ mwifiex_dbg(adapter, DUMP,
+ "Start %s output, please wait...\n", entry->mem_name);
+
+ while (true) {
+ stat = mwifiex_sdio_rdwr_firmware(adapter, done_flag);
+ if (stat == RDWR_STATUS_FAILURE)
+ goto done;
+ for (reg = reg_start; reg <= reg_end; reg++) {
+ *dbg_ptr = sdio_readb(card->func, reg, &ret);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR,
+ "SDIO read err\n");
+ goto done;
+ }
+ dbg_ptr++;
+ if (dbg_ptr >= end_ptr) {
+ u8 *tmp_ptr;
+
+ tmp_ptr = vmalloc(entry->mem_size + 0x4000 + 1);
+ if (!tmp_ptr)
+ goto done;
+
+ memcpy(tmp_ptr, entry->mem_ptr,
+ entry->mem_size);
+ vfree(entry->mem_ptr);
+ entry->mem_ptr = tmp_ptr;
+ tmp_ptr = NULL;
+ dbg_ptr = entry->mem_ptr + entry->mem_size;
+ entry->mem_size += 0x4000;
+ end_ptr = entry->mem_ptr + entry->mem_size;
+ }
+ }
+ if (stat == RDWR_STATUS_DONE) {
+ entry->mem_size = dbg_ptr - entry->mem_ptr;
+ mwifiex_dbg(adapter, DUMP, "dump %s done size=0x%x\n",
+ entry->mem_name, entry->mem_size);
+ ret = 0;
+ break;
+ }
+ }
+ mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
+
+done:
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "firmware dump failed\n");
+ if (entry->mem_ptr) {
+ vfree(entry->mem_ptr);
+ entry->mem_ptr = NULL;
+ }
+ entry->mem_size = 0;
+ }
+ sdio_release_host(card->func);
+}
+
static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter)
{
+ struct sdio_mmc_card *card = adapter->card;
+
mwifiex_drv_info_dump(adapter);
- mwifiex_sdio_fw_dump(adapter);
+ if (card->fw_dump_enh)
+ mwifiex_sdio_generic_fw_dump(adapter);
+ else
+ mwifiex_sdio_fw_dump(adapter);
mwifiex_upload_device_dump(adapter);
}

diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index cd149196..b9fbc5c 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -223,6 +223,7 @@ struct mwifiex_sdio_card_reg {
u8 cmd_cfg_1;
u8 cmd_cfg_2;
u8 cmd_cfg_3;
+ u8 fw_dump_host_ready;
u8 fw_dump_ctrl;
u8 fw_dump_start;
u8 fw_dump_end;
@@ -258,6 +259,7 @@ struct sdio_mmc_card {
bool supports_sdio_new_mode;
bool has_control_mask;
bool can_dump_fw;
+ bool fw_dump_enh;
bool can_auto_tdls;
bool can_ext_scan;

@@ -279,6 +281,7 @@ struct mwifiex_sdio_device {
bool supports_sdio_new_mode;
bool has_control_mask;
bool can_dump_fw;
+ bool fw_dump_enh;
bool can_auto_tdls;
bool can_ext_scan;
};
@@ -354,6 +357,7 @@ static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8897 = {
.cmd_cfg_1 = 0xb9,
.cmd_cfg_2 = 0xba,
.cmd_cfg_3 = 0xbb,
+ .fw_dump_host_ready = 0xee,
.fw_dump_ctrl = 0xe2,
.fw_dump_start = 0xe3,
.fw_dump_end = 0xea,
@@ -404,6 +408,10 @@ static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8997 = {
.cmd_cfg_1 = 0xc5,
.cmd_cfg_2 = 0xc6,
.cmd_cfg_3 = 0xc7,
+ .fw_dump_host_ready = 0xcc,
+ .fw_dump_ctrl = 0xf0,
+ .fw_dump_start = 0xf1,
+ .fw_dump_end = 0xf8,
.func1_dump_reg_start = 0x10,
.func1_dump_reg_end = 0x17,
.func1_scratch_reg = 0xe8,
@@ -532,7 +540,8 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8997 = {
.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX,
.supports_sdio_new_mode = true,
.has_control_mask = false,
- .can_dump_fw = false,
+ .can_dump_fw = true,
+ .fw_dump_enh = true,
.can_auto_tdls = false,
.can_ext_scan = true,
};
--
1.8.1.4


2015-08-04 12:31:26

by Amitkumar Karwar

[permalink] [raw]
Subject: [PATCH v2 3/3] mwifiex: fix unable to connect hidden SSID AP on DFS channel

From: chunfan chen <[email protected]>

We will check if any hidden SSID found in passive scan channels
and do specific SSID active scan for those channels.

Signed-off-by: chunfan chen <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v2: Corrected hidden SSID detection logic as per Paul Stewart's comment.
---
drivers/net/wireless/mwifiex/fw.h | 1 +
drivers/net/wireless/mwifiex/init.c | 2 +-
drivers/net/wireless/mwifiex/main.h | 2 +
drivers/net/wireless/mwifiex/scan.c | 136 +++++++++++++++++++++++++++++++++---
4 files changed, 129 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 9a8c1832..3ec2ac8 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -685,6 +685,7 @@ struct mwifiex_fw_chan_stats {
enum mwifiex_chan_scan_mode_bitmasks {
MWIFIEX_PASSIVE_SCAN = BIT(0),
MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
+ MWIFIEX_HIDDEN_SSID_REPORT = BIT(4),
};

struct mwifiex_chan_scan_param_set {
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 7a970c2..5d3ae63 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -301,7 +301,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM;
adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM;
adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
-
+ adapter->active_scan_triggered = false;
setup_timer(&adapter->wakeup_timer, wakeup_timer_fn,
(unsigned long)adapter);
}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index face747..6b95121 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -666,6 +666,7 @@ struct mwifiex_private {
struct mwifiex_11h_intf_state state_11h;
struct mwifiex_ds_mem_rw mem_rw;
struct sk_buff_head bypass_txq;
+ struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX];
};


@@ -986,6 +987,7 @@ struct mwifiex_adapter {
u8 coex_tx_win_size;
u8 coex_rx_win_size;
bool drcs_enabled;
+ u8 active_scan_triggered;
};

void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index ef8da8e..47e9253 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -527,7 +527,8 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,

if (ch->flags & IEEE80211_CHAN_NO_IR)
scan_chan_list[chan_idx].chan_scan_mode_bitmap
- |= MWIFIEX_PASSIVE_SCAN;
+ |= (MWIFIEX_PASSIVE_SCAN |
+ MWIFIEX_HIDDEN_SSID_REPORT);
else
scan_chan_list[chan_idx].chan_scan_mode_bitmap
&= ~MWIFIEX_PASSIVE_SCAN;
@@ -1049,7 +1050,8 @@ mwifiex_config_scan(struct mwifiex_private *priv,
if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
(scan_chan_list +
chan_idx)->chan_scan_mode_bitmap
- |= MWIFIEX_PASSIVE_SCAN;
+ |= (MWIFIEX_PASSIVE_SCAN |
+ MWIFIEX_HIDDEN_SSID_REPORT);
else
(scan_chan_list +
chan_idx)->chan_scan_mode_bitmap
@@ -1600,6 +1602,58 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
return ret;
}

+/* This function checks if SSID string contains all zeroes or length is zero */
+static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
+{
+ int idx;
+
+ for (idx = 0; idx < ssid->ssid_len; idx++) {
+ if (ssid->ssid[idx])
+ return false;
+ }
+
+ return true;
+}
+
+/* This function checks if any hidden SSID found in passive scan channels
+ * and save those channels for specific SSID active scan
+ */
+static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
+ struct cfg80211_bss *bss)
+{
+ struct mwifiex_bssdescriptor *bss_desc;
+ int ret;
+ int chid;
+
+ /* Allocate and fill new bss descriptor */
+ bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
+ if (!bss_desc)
+ return -ENOMEM;
+
+ ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
+ if (ret)
+ goto done;
+
+ if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
+ mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
+ for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
+ if (priv->hidden_chan[chid].chan_number == 0) {
+ priv->hidden_chan[chid].chan_number =
+ bss->channel->hw_value;
+ priv->hidden_chan[chid].radio_type =
+ bss->channel->band;
+ priv->hidden_chan[chid].scan_type =
+ MWIFIEX_SCAN_TYPE_ACTIVE;
+ break;
+ }
+ }
+ }
+
+done:
+ kfree(bss_desc);
+ return 0;
+}
+
static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
struct cfg80211_bss *bss)
{
@@ -1789,6 +1843,14 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
.mac_address, ETH_ALEN))
mwifiex_update_curr_bss_params(priv, bss);
cfg80211_put_bss(priv->wdev.wiphy, bss);
+
+ if ((chan->flags & IEEE80211_CHAN_RADAR) ||
+ (chan->flags & IEEE80211_CHAN_NO_IR)) {
+ mwifiex_dbg(adapter, INFO,
+ "radar or passive channel %d\n",
+ channel);
+ mwifiex_save_hidden_ssid_channels(priv, bss);
+ }
}
} else {
mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
@@ -1812,6 +1874,54 @@ static void mwifiex_complete_scan(struct mwifiex_private *priv)
}
}

+/* This function checks if any hidden SSID found in passive scan channels
+ * and do specific SSID active scan for those channels
+ */
+static int
+mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
+{
+ int ret;
+ struct mwifiex_adapter *adapter = priv->adapter;
+ u8 id = 0;
+ struct mwifiex_user_scan_cfg *user_scan_cfg;
+
+ if (adapter->active_scan_triggered) {
+ adapter->active_scan_triggered = false;
+ return 0;
+ }
+
+ if (priv->hidden_chan[0].chan_number == 0) {
+ mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
+ return 0;
+ }
+ user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
+
+ if (!user_scan_cfg)
+ return -ENOMEM;
+
+ memset(user_scan_cfg, 0, sizeof(*user_scan_cfg));
+
+ for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++)
+ memcpy(&user_scan_cfg->chan_list[id],
+ &priv->hidden_chan[id],
+ sizeof(struct mwifiex_user_scan_chan));
+
+ adapter->active_scan_triggered = true;
+ user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
+ user_scan_cfg->ssid_list = priv->scan_request->ssids;
+
+ ret = mwifiex_scan_networks(priv, user_scan_cfg);
+ kfree(user_scan_cfg);
+
+ memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
+
+ if (ret) {
+ dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
{
struct mwifiex_adapter *adapter = priv->adapter;
@@ -1825,6 +1935,8 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
adapter->scan_processing = false;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);

+ mwifiex_active_scan_req_for_passive_chan(priv);
+
if (!adapter->ext_scan)
mwifiex_complete_scan(priv);

@@ -1851,15 +1963,17 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
adapter->scan_processing = false;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);

- if (priv->scan_request) {
- mwifiex_dbg(adapter, INFO,
- "info: aborting scan\n");
- cfg80211_scan_done(priv->scan_request, 1);
- priv->scan_request = NULL;
- } else {
- priv->scan_aborting = false;
- mwifiex_dbg(adapter, INFO,
- "info: scan already aborted\n");
+ if (!adapter->active_scan_triggered) {
+ if (priv->scan_request) {
+ mwifiex_dbg(adapter, INFO,
+ "info: aborting scan\n");
+ cfg80211_scan_done(priv->scan_request, 1);
+ priv->scan_request = NULL;
+ } else {
+ priv->scan_aborting = false;
+ mwifiex_dbg(adapter, INFO,
+ "info: scan already aborted\n");
+ }
}
} else {
/* Get scan command from scan_pending_q and put to
--
1.8.1.4