2014-09-12 09:10:02

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 00/16] mwifiex updates for 3.18

This patchset brings in channel scan gap & RX work queue support to
mwifiex. With channel scan gap in, we remove low priority scan
handling feature.

Patset also includes trivial fixes for SDIO multiport aggregation,
one fix for A band association.

Amitkumar Karwar (4):
mwifiex: fix a bug in Tx multiport aggregation
mwifiex: minor cleanup in multiport aggregation
mwifiex: remove redundant variable report_scan_result
mwifiex: remove low priority scan handling

Avinash Patil (11):
mwifiex: set fw api info for backword compatibility
mwifiex: fix probable memory corruption while processing TDLS frame
mwifiex: avoid processing RX packets with invalid length
mwifiex: rework internal scan for association
mwifiex: support for event done interrupt
mwifiex: set passive scan type for scan requests with no ssid
mwifiex: bring in scan channel gap feature
mwifiex: remove restriction of single channel scan when connected
mwifiex: process TX even when scan is ongoing
mwifiex: add rx workqueue support
mwifiex: modify TX/RX window sizes for AP interface

Xinming Hu (1):
mwifiex: fix 5G association failure after leaving 2.4G IBSS

drivers/net/wireless/mwifiex/11n_rxreorder.c | 14 ++
drivers/net/wireless/mwifiex/cfg80211.c | 14 +-
drivers/net/wireless/mwifiex/cmdevt.c | 4 +
drivers/net/wireless/mwifiex/decl.h | 4 +-
drivers/net/wireless/mwifiex/fw.h | 10 +-
drivers/net/wireless/mwifiex/init.c | 21 ++-
drivers/net/wireless/mwifiex/main.c | 191 +++++++++++++--------------
drivers/net/wireless/mwifiex/main.h | 48 +++++--
drivers/net/wireless/mwifiex/pcie.c | 37 +++++-
drivers/net/wireless/mwifiex/pcie.h | 5 +-
drivers/net/wireless/mwifiex/scan.c | 108 ++++++++++-----
drivers/net/wireless/mwifiex/sdio.c | 28 ++--
drivers/net/wireless/mwifiex/sta_cmdresp.c | 2 -
drivers/net/wireless/mwifiex/sta_ioctl.c | 9 +-
drivers/net/wireless/mwifiex/tdls.c | 4 +-
15 files changed, 317 insertions(+), 182 deletions(-)

--
1.8.1.4



2014-09-12 09:10:10

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 02/16] mwifiex: fix probable memory corruption while processing TDLS frame

Size of RSN IE buffer in driver is 254 while maximum size of received buffer
to be copied to RSN IE buffer can be 255. Add boundary check to copy maximum
of 254 bytes into RSN IE buffer.

Reported-by: Dan Carpenter <[email protected]>
Signed-off-by: Avinash Patil <[email protected]>
---
drivers/net/wireless/mwifiex/tdls.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
index 4c5fd95..e294907 100644
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -871,7 +871,9 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
break;
case WLAN_EID_RSN:
memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
- sizeof(struct ieee_types_header) + pos[1]);
+ sizeof(struct ieee_types_header) +
+ min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
+ sizeof(struct ieee_types_header)));
break;
case WLAN_EID_QOS_CAPA:
sta_ptr->tdls_cap.qos_info = pos[2];
--
1.8.1.4


2014-09-12 09:11:30

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 15/16] mwifiex: add rx workqueue support

This patch adds RX work queue support to mwifiex.
Packets received are queued to internal queue which are then
processed by scheduling a work item for RX process.

RX work is enabled only on SMP systems.

Reviewed-by: James Cameron <[email protected]>
Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Marc Yang <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
drivers/net/wireless/mwifiex/11n_rxreorder.c | 14 +++++
drivers/net/wireless/mwifiex/init.c | 19 ++++++
drivers/net/wireless/mwifiex/main.c | 91 ++++++++++++++++++++++++++++
drivers/net/wireless/mwifiex/main.h | 14 +++++
drivers/net/wireless/mwifiex/pcie.c | 12 +++-
drivers/net/wireless/mwifiex/sdio.c | 11 +++-
6 files changed, 159 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 06a2c21..4005707 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -183,6 +183,15 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
if (!tbl)
return;

+ spin_lock_irqsave(&priv->adapter->rx_proc_lock, flags);
+ priv->adapter->rx_locked = true;
+ if (priv->adapter->rx_processing) {
+ spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
+ flush_workqueue(priv->adapter->rx_workqueue);
+ } else {
+ spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
+ }
+
start_win = (tbl->start_win + tbl->win_size) & (MAX_TID_VALUE - 1);
mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);

@@ -194,6 +203,11 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,

kfree(tbl->rx_reorder_ptr);
kfree(tbl);
+
+ spin_lock_irqsave(&priv->adapter->rx_proc_lock, flags);
+ priv->adapter->rx_locked = false;
+ spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags);
+
}

/*
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index cd9baad..f7c97cf 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -447,8 +447,11 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
spin_lock_init(&adapter->cmd_free_q_lock);
spin_lock_init(&adapter->cmd_pending_q_lock);
spin_lock_init(&adapter->scan_pending_q_lock);
+ spin_lock_init(&adapter->rx_q_lock);
+ spin_lock_init(&adapter->rx_proc_lock);

skb_queue_head_init(&adapter->usb_rx_data_q);
+ skb_queue_head_init(&adapter->rx_data_q);

for (i = 0; i < adapter->priv_num; ++i) {
INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head);
@@ -614,6 +617,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
int ret = -EINPROGRESS;
struct mwifiex_private *priv;
s32 i;
+ unsigned long flags;
struct sk_buff *skb;

/* mwifiex already shutdown */
@@ -648,6 +652,21 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
}
}

+ spin_lock_irqsave(&adapter->rx_proc_lock, flags);
+
+ while ((skb = skb_dequeue(&adapter->rx_data_q))) {
+ struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
+
+ atomic_dec(&adapter->rx_pending);
+ priv = adapter->priv[rx_info->bss_num];
+ if (priv)
+ priv->stats.rx_dropped++;
+
+ dev_kfree_skb_any(skb);
+ }
+
+ spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+
spin_lock(&adapter->mwifiex_lock);

if (adapter->if_ops.data_complete) {
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index f139386..b522f7c 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -126,6 +126,42 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter)
return 0;
}

+static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
+{
+ unsigned long flags;
+ struct sk_buff *skb;
+ bool delay_main_work = adapter->delay_main_work;
+
+ spin_lock_irqsave(&adapter->rx_proc_lock, flags);
+ if (adapter->rx_processing || adapter->rx_locked) {
+ spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+ goto exit_rx_proc;
+ } else {
+ adapter->rx_processing = true;
+ spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+ }
+
+ /* Check for Rx data */
+ while ((skb = skb_dequeue(&adapter->rx_data_q))) {
+ atomic_dec(&adapter->rx_pending);
+ if (adapter->delay_main_work &&
+ (atomic_dec_return(&adapter->rx_pending) <
+ LOW_RX_PENDING)) {
+ adapter->delay_main_work = false;
+ queue_work(adapter->rx_workqueue, &adapter->rx_work);
+ }
+ mwifiex_handle_rx_packet(adapter, skb);
+ }
+ spin_lock_irqsave(&adapter->rx_proc_lock, flags);
+ adapter->rx_processing = false;
+ spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+
+ if (delay_main_work)
+ queue_work(adapter->workqueue, &adapter->main_work);
+exit_rx_proc:
+ return 0;
+}
+
/*
* The main process.
*
@@ -163,6 +199,19 @@ process_start:
(adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY))
break;

+ /* If we process interrupts first, it would increase RX pending
+ * even further. Avoid this by checking if rx_pending has
+ * crossed high threshold and schedule rx work queue
+ * and then process interrupts
+ */
+ if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING) {
+ adapter->delay_main_work = true;
+ if (!adapter->rx_processing)
+ queue_work(adapter->rx_workqueue,
+ &adapter->rx_work);
+ break;
+ }
+
/* Handle pending interrupt if any */
if (adapter->int_status) {
if (adapter->hs_activated)
@@ -171,6 +220,9 @@ process_start:
adapter->if_ops.process_int_status(adapter);
}

+ if (adapter->rx_work_enabled && adapter->data_received)
+ queue_work(adapter->rx_workqueue, &adapter->rx_work);
+
/* Need to wake up the card ? */
if ((adapter->ps_state == PS_STATE_SLEEP) &&
(adapter->pm_wakeup_card_req &&
@@ -183,6 +235,7 @@ process_start:
}

if (IS_CARD_RX_RCVD(adapter)) {
+ adapter->data_received = false;
adapter->pm_wakeup_fw_try = false;
if (adapter->ps_state == PS_STATE_SLEEP)
adapter->ps_state = PS_STATE_AWAKE;
@@ -318,6 +371,12 @@ static void mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
flush_workqueue(adapter->workqueue);
destroy_workqueue(adapter->workqueue);
adapter->workqueue = NULL;
+
+ if (adapter->rx_workqueue) {
+ flush_workqueue(adapter->rx_workqueue);
+ destroy_workqueue(adapter->rx_workqueue);
+ adapter->rx_workqueue = NULL;
+ }
}

/*
@@ -732,6 +791,21 @@ int is_command_pending(struct mwifiex_adapter *adapter)
}

/*
+ * This is the RX work queue function.
+ *
+ * It handles the RX operations.
+ */
+static void mwifiex_rx_work_queue(struct work_struct *work)
+{
+ struct mwifiex_adapter *adapter =
+ container_of(work, struct mwifiex_adapter, rx_work);
+
+ if (adapter->surprise_removed)
+ return;
+ mwifiex_process_rx(adapter);
+}
+
+/*
* This is the main work queue function.
*
* It handles the main process, which in turn handles the complete
@@ -787,6 +861,11 @@ mwifiex_add_card(void *card, struct semaphore *sem,
adapter->cmd_wait_q.status = 0;
adapter->scan_wait_q_woken = false;

+ if (num_possible_cpus() > 1) {
+ adapter->rx_work_enabled = true;
+ pr_notice("rx work enabled, cpus %d\n", num_possible_cpus());
+ }
+
adapter->workqueue =
alloc_workqueue("MWIFIEX_WORK_QUEUE",
WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
@@ -794,6 +873,18 @@ mwifiex_add_card(void *card, struct semaphore *sem,
goto err_kmalloc;

INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
+
+ if (adapter->rx_work_enabled) {
+ adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE",
+ WQ_HIGHPRI |
+ WQ_MEM_RECLAIM |
+ WQ_UNBOUND, 1);
+ if (!adapter->rx_workqueue)
+ goto err_kmalloc;
+
+ INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue);
+ }
+
if (adapter->if_ops.iface_work)
INIT_WORK(&adapter->iface_work, adapter->if_ops.iface_work);

diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index e9cd4ab..1a99999 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -58,6 +58,9 @@ enum {
#define MAX_TX_PENDING 100
#define LOW_TX_PENDING 80

+#define HIGH_RX_PENDING 50
+#define LOW_RX_PENDING 20
+
#define MWIFIEX_UPLD_SIZE (2312)

#define MAX_EVENT_SIZE 2048
@@ -714,6 +717,12 @@ struct mwifiex_adapter {
atomic_t cmd_pending;
struct workqueue_struct *workqueue;
struct work_struct main_work;
+ struct workqueue_struct *rx_workqueue;
+ struct work_struct rx_work;
+ bool rx_work_enabled;
+ bool rx_processing;
+ bool delay_main_work;
+ bool rx_locked;
struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM];
/* spin lock for init/shutdown */
spinlock_t mwifiex_lock;
@@ -754,6 +763,10 @@ struct mwifiex_adapter {
struct list_head scan_pending_q;
/* spin lock for scan_pending_q */
spinlock_t scan_pending_q_lock;
+ /* spin lock for RX queue */
+ spinlock_t rx_q_lock;
+ /* spin lock for RX processing routine */
+ spinlock_t rx_proc_lock;
struct sk_buff_head usb_rx_data_q;
u32 scan_processing;
u16 region_code;
@@ -831,6 +844,7 @@ struct mwifiex_adapter {
u8 num_mem_types;
u8 curr_mem_idx;
bool scan_chan_gap_enabled;
+ struct sk_buff_head rx_data_q;
};

int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 2ada1b7..1504b16 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -1233,6 +1233,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
struct sk_buff *skb_tmp = NULL;
struct mwifiex_pcie_buf_desc *desc;
struct mwifiex_pfu_buf_desc *desc2;
+ unsigned long flags;

if (!mwifiex_pcie_ok_to_access_hw(adapter))
mwifiex_pm_wakeup_card(adapter);
@@ -1283,7 +1284,16 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
"info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
card->rxbd_rdptr, wrptr, rx_len);
skb_pull(skb_data, INTF_HEADER_LEN);
- mwifiex_handle_rx_packet(adapter, skb_data);
+ if (adapter->rx_work_enabled) {
+ spin_lock_irqsave(&adapter->rx_q_lock, flags);
+ skb_queue_tail(&adapter->rx_data_q, skb_data);
+ spin_unlock_irqrestore(&adapter->rx_q_lock,
+ flags);
+ adapter->data_received = true;
+ atomic_inc(&adapter->rx_pending);
+ } else {
+ mwifiex_handle_rx_packet(adapter, skb_data);
+ }
}

skb_tmp = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE);
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index bdab122..ea8fc58 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -1039,6 +1039,7 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
struct sk_buff *skb, u32 upld_typ)
{
u8 *cmd_buf;
+ unsigned long flags;
__le16 *curr_ptr = (__le16 *)skb->data;
u16 pkt_len = le16_to_cpu(*curr_ptr);

@@ -1048,7 +1049,15 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
switch (upld_typ) {
case MWIFIEX_TYPE_DATA:
dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n");
- mwifiex_handle_rx_packet(adapter, skb);
+ if (adapter->rx_work_enabled) {
+ spin_lock_irqsave(&adapter->rx_q_lock, flags);
+ skb_queue_tail(&adapter->rx_data_q, skb);
+ spin_unlock_irqrestore(&adapter->rx_q_lock, flags);
+ adapter->data_received = true;
+ atomic_inc(&adapter->rx_pending);
+ } else {
+ mwifiex_handle_rx_packet(adapter, skb);
+ }
break;

case MWIFIEX_TYPE_CMD:
--
1.8.1.4


2014-09-12 09:11:28

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 11/16] mwifiex: remove restriction of single channel scan when connected

With scan channel gap in place, FW comes back to connected channel
after each scan; so we dont need to restrict FW to scan
single channel while connected.

Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Marc Yang <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
drivers/net/wireless/mwifiex/scan.c | 6 ------
1 file changed, 6 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 6fd69af..7c85f61 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1067,12 +1067,6 @@ mwifiex_config_scan(struct mwifiex_private *priv,
*filtered_scan);
}

- /*
- * In associated state we will reduce the number of channels scanned per
- * scan command to 1 to avoid any traffic delay/loss.
- */
- if (priv->media_connected)
- *max_chan_per_scan = 1;
}

/*
--
1.8.1.4


2014-09-12 09:10:26

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 06/16] mwifiex: fix 5G association failure after leaving 2.4G IBSS

From: Xinming Hu <[email protected]>

When assocaiting to an AP , mwifiex set supported data rates
based on target AP's capability. For 5G AP(11a mode), a/n/ac mode
would possibly be set.
However, for some chips which dont support 11AC mode current config_bands
will be used instead.

For example, if we join an IBSS in 11b mode ,adapter->config_bands
will be set to 1(11b mode). Then we leave IBSS ,and try to connect
5G a/n mode AP. At this time , only 11b mode data rates will be
supported in assoc request , which result in assoc failure with
reason code 18: Association denied due to requesting station not
supporting all rates.

This patch fix such a cornel case, by adding additional check for
current chip's 11ac capability.

Reported-by: Andreas Fenkart <[email protected]>
Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Marc Yang <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
drivers/net/wireless/mwifiex/sta_ioctl.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index b95a29b..92f3eb8 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -287,10 +287,13 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
return -1;

if (mwifiex_band_to_radio_type(bss_desc->bss_band) ==
- HostCmd_SCAN_RADIO_TYPE_BG)
+ HostCmd_SCAN_RADIO_TYPE_BG) {
config_bands = BAND_B | BAND_G | BAND_GN;
- else
- config_bands = BAND_A | BAND_AN | BAND_AAC;
+ } else {
+ config_bands = BAND_A | BAND_AN;
+ if (adapter->fw_bands & BAND_AAC)
+ config_bands |= BAND_AAC;
+ }

if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands))
adapter->config_bands = config_bands;
--
1.8.1.4


2014-09-12 09:10:45

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 14/16] mwifiex: remove low priority scan handling

From: Amitkumar Karwar <[email protected]>

We have a logic in driver to delay or abort low priority scan
to serve Tx traffic effectively. With scan channel
gap support added, firmware now allows driver to send Tx data while
scan operation is in progress. Hence low priority scan handling
in driver is not required now. This patch removes related code.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
drivers/net/wireless/mwifiex/cfg80211.c | 8 ---
drivers/net/wireless/mwifiex/init.c | 1 -
drivers/net/wireless/mwifiex/main.c | 96 +--------------------------------
drivers/net/wireless/mwifiex/main.h | 10 ----
drivers/net/wireless/mwifiex/scan.c | 59 ++++++++++----------
5 files changed, 30 insertions(+), 144 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 50cc0db..1fd35be 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1935,13 +1935,6 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,

wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);

- if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
- atomic_read(&priv->wmm.tx_pkts_queued) >=
- MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN) {
- dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n");
- return -EBUSY;
- }
-
/* Block scan request if scan operation or scan cleanup when interface
* is disabled is in process
*/
@@ -2919,7 +2912,6 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)

wiphy->features |= NL80211_FEATURE_HT_IBSS |
NL80211_FEATURE_INACTIVITY_TIMER |
- NL80211_FEATURE_LOW_PRIORITY_SCAN |
NL80211_FEATURE_NEED_OBSS_SCAN;

/* Reserve space for mwifiex specific private data for BSS */
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index d99c6f6..cd9baad 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -281,7 +281,6 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
adapter->arp_filter_size = 0;
adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
- adapter->empty_tx_q_cnt = 0;
adapter->ext_scan = true;
adapter->key_api_major_ver = 0;
adapter->key_api_minor_ver = 0;
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index d6d2342..f139386 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -28,91 +28,6 @@ const char driver_version[] = "mwifiex " VERSION " (%s) ";
static char *cal_data_cfg;
module_param(cal_data_cfg, charp, 0);

-static void scan_delay_timer_fn(unsigned long data)
-{
- struct mwifiex_private *priv = (struct mwifiex_private *)data;
- struct mwifiex_adapter *adapter = priv->adapter;
- struct cmd_ctrl_node *cmd_node, *tmp_node;
- spinlock_t *scan_q_lock = &adapter->scan_pending_q_lock;
- unsigned long flags;
-
- if (adapter->surprise_removed)
- return;
-
- if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT ||
- !adapter->scan_processing) {
- /*
- * Abort scan operation by cancelling all pending scan
- * commands
- */
- spin_lock_irqsave(scan_q_lock, flags);
- list_for_each_entry_safe(cmd_node, tmp_node,
- &adapter->scan_pending_q, list) {
- list_del(&cmd_node->list);
- mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
- }
- spin_unlock_irqrestore(scan_q_lock, flags);
-
- spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
- adapter->scan_processing = false;
- adapter->scan_delay_cnt = 0;
- adapter->empty_tx_q_cnt = 0;
- spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-
- if (priv->scan_request) {
- dev_dbg(adapter->dev, "info: aborting scan\n");
- cfg80211_scan_done(priv->scan_request, 1);
- priv->scan_request = NULL;
- } else {
- priv->scan_aborting = false;
- dev_dbg(adapter->dev, "info: scan already aborted\n");
- }
- goto done;
- }
-
- if (!atomic_read(&priv->adapter->is_tx_received)) {
- adapter->empty_tx_q_cnt++;
- if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) {
- /*
- * No Tx traffic for 200msec. Get scan command from
- * scan pending queue and put to cmd pending queue to
- * resume scan operation
- */
- adapter->scan_delay_cnt = 0;
- adapter->empty_tx_q_cnt = 0;
- spin_lock_irqsave(scan_q_lock, flags);
-
- if (list_empty(&adapter->scan_pending_q)) {
- spin_unlock_irqrestore(scan_q_lock, flags);
- goto done;
- }
-
- cmd_node = list_first_entry(&adapter->scan_pending_q,
- struct cmd_ctrl_node, list);
- list_del(&cmd_node->list);
- spin_unlock_irqrestore(scan_q_lock, flags);
-
- mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
- true);
- queue_work(adapter->workqueue, &adapter->main_work);
- goto done;
- }
- } else {
- adapter->empty_tx_q_cnt = 0;
- }
-
- /* Delay scan operation further by 20msec */
- mod_timer(&priv->scan_delay_timer, jiffies +
- msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
- adapter->scan_delay_cnt++;
-
-done:
- if (atomic_read(&priv->adapter->is_tx_received))
- atomic_set(&priv->adapter->is_tx_received, false);
-
- return;
-}
-
/*
* This function registers the device and performs all the necessary
* initializations.
@@ -160,10 +75,6 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,

adapter->priv[i]->adapter = adapter;
adapter->priv_num++;
-
- setup_timer(&adapter->priv[i]->scan_delay_timer,
- scan_delay_timer_fn,
- (unsigned long)adapter->priv[i]);
}
mwifiex_init_lock_list(adapter);

@@ -207,7 +118,6 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter)
for (i = 0; i < adapter->priv_num; i++) {
if (adapter->priv[i]) {
mwifiex_free_curr_bcn(adapter->priv[i]);
- del_timer_sync(&adapter->priv[i]->scan_delay_timer);
kfree(adapter->priv[i]);
}
}
@@ -285,7 +195,6 @@ process_start:
break;

if ((!adapter->scan_chan_gap_enabled &&
- !adapter->scan_delay_cnt &&
adapter->scan_processing) || adapter->data_sent ||
mwifiex_wmm_lists_empty(adapter)) {
if (adapter->cmd_sent || adapter->curr_cmd ||
@@ -341,7 +250,7 @@ process_start:
}

if ((adapter->scan_chan_gap_enabled ||
- (!adapter->scan_processing || adapter->scan_delay_cnt)) &&
+ !adapter->scan_processing) &&
!adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) {
mwifiex_wmm_process_tx(adapter);
if (adapter->hs_activated) {
@@ -600,9 +509,6 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)
atomic_inc(&priv->adapter->tx_pending);
mwifiex_wmm_add_buf_txqueue(priv, skb);

- if (priv->adapter->scan_delay_cnt)
- atomic_set(&priv->adapter->is_tx_received, true);
-
queue_work(priv->adapter->workqueue, &priv->adapter->main_work);

return 0;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 651fd8c..e9cd4ab 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -90,12 +90,6 @@ enum {

#define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S)

-#define MWIFIEX_MAX_SCAN_DELAY_CNT 50
-#define MWIFIEX_MAX_EMPTY_TX_Q_CNT 10
-#define MWIFIEX_SCAN_DELAY_MSEC 20
-
-#define MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN 2
-
#define RSN_GTK_OUI_OFFSET 2

#define MWIFIEX_OUI_NOT_PRESENT 0
@@ -561,7 +555,6 @@ struct mwifiex_private {
u16 proberesp_idx;
u16 assocresp_idx;
u16 rsn_idx;
- struct timer_list scan_delay_timer;
u8 ap_11n_enabled;
u8 ap_11ac_enabled;
u32 mgmt_frame_mask;
@@ -816,8 +809,6 @@ struct mwifiex_adapter {
spinlock_t queue_lock; /* lock for tx queues */
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
u16 max_mgmt_ie_index;
- u8 scan_delay_cnt;
- u8 empty_tx_q_cnt;
const struct firmware *cal_data;
struct device_node *dt_node;

@@ -829,7 +820,6 @@ struct mwifiex_adapter {
u32 usr_dot_11ac_dev_cap_a;
u32 usr_dot_11ac_mcs_support;

- atomic_t is_tx_received;
atomic_t pending_bridged_pkts;
struct semaphore *card_sem;
bool ext_scan;
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 7b07da2..67f9cdb 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1765,7 +1765,7 @@ static void mwifiex_complete_scan(struct mwifiex_private *priv)
static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
{
struct mwifiex_adapter *adapter = priv->adapter;
- struct cmd_ctrl_node *cmd_node;
+ struct cmd_ctrl_node *cmd_node, *tmp_node;
unsigned long flags;

spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
@@ -1786,37 +1786,36 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
priv->scan_aborting = false;
dev_dbg(adapter->dev, "info: scan already aborted\n");
}
- } else {
- if ((priv->scan_aborting && !priv->scan_request) ||
- priv->scan_block) {
- spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
- flags);
- adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT;
- mod_timer(&priv->scan_delay_timer, jiffies);
- dev_dbg(priv->adapter->dev,
- "info: %s: triggerring scan abort\n", __func__);
- } else if (!mwifiex_wmm_lists_empty(adapter) &&
- (priv->scan_request && (priv->scan_request->flags &
- NL80211_SCAN_FLAG_LOW_PRIORITY))) {
- spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
- flags);
- adapter->scan_delay_cnt = 1;
- mod_timer(&priv->scan_delay_timer, jiffies +
- msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
- dev_dbg(priv->adapter->dev,
- "info: %s: deferring scan\n", __func__);
- } else {
- /* Get scan command from scan_pending_q and put to
- * cmd_pending_q
- */
- cmd_node = list_first_entry(&adapter->scan_pending_q,
- struct cmd_ctrl_node, list);
+ } else if ((priv->scan_aborting && !priv->scan_request) ||
+ priv->scan_block) {
+ list_for_each_entry_safe(cmd_node, tmp_node,
+ &adapter->scan_pending_q, list) {
list_del(&cmd_node->list);
- spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
- flags);
- mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
- true);
+ mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+ }
+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+
+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+ adapter->scan_processing = false;
+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+
+ if (priv->scan_request) {
+ dev_dbg(adapter->dev, "info: aborting scan\n");
+ cfg80211_scan_done(priv->scan_request, 1);
+ priv->scan_request = NULL;
+ } else {
+ priv->scan_aborting = false;
+ dev_dbg(adapter->dev, "info: scan already aborted\n");
}
+ } else {
+ /* Get scan command from scan_pending_q and put to
+ * cmd_pending_q
+ */
+ cmd_node = list_first_entry(&adapter->scan_pending_q,
+ struct cmd_ctrl_node, list);
+ list_del(&cmd_node->list);
+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+ mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
}

return;
--
1.8.1.4


2014-09-12 09:10:06

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 01/16] mwifiex: set fw api info for backword compatibility

If we dont set FW API info here, for older FW releases where FW API
is not available in GET_HW_SPEC, API version would remain 0.
This may cause issues with 11ac if older FW is used with newer driver.

Signed-off-by: Avinash Patil <[email protected]>
---
drivers/net/wireless/mwifiex/cmdevt.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 985f6c2..fcc70ae 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -1508,6 +1508,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
}

adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number);
+ adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff;
adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna);

if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) {
--
1.8.1.4


2014-09-12 09:10:11

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 03/16] mwifiex: avoid processing RX packets with invalid length

If rx_len received in interface header from FW is more than
RX buffer size, skb_put for such length results into skb_panic.
Avoid this by not processing such packets. We just print a warning
for such packets and free skb.

Reviewed-by: Paul Stewart <[email protected]>
Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
Signed-off-by: Marc Yang <[email protected]>
---
drivers/net/wireless/mwifiex/pcie.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index ff05458..27c2bf8 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -1271,12 +1271,20 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
*/
pkt_len = *((__le16 *)skb_data->data);
rx_len = le16_to_cpu(pkt_len);
- skb_put(skb_data, rx_len);
- dev_dbg(adapter->dev,
- "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
- card->rxbd_rdptr, wrptr, rx_len);
- skb_pull(skb_data, INTF_HEADER_LEN);
- mwifiex_handle_rx_packet(adapter, skb_data);
+ if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
+ rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
+ dev_err(adapter->dev,
+ "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
+ rx_len, card->rxbd_rdptr, wrptr);
+ dev_kfree_skb_any(skb_data);
+ } else {
+ skb_put(skb_data, rx_len);
+ dev_dbg(adapter->dev,
+ "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
+ card->rxbd_rdptr, wrptr, rx_len);
+ skb_pull(skb_data, INTF_HEADER_LEN);
+ mwifiex_handle_rx_packet(adapter, skb_data);
+ }

skb_tmp = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE);
if (!skb_tmp) {
--
1.8.1.4


2014-09-12 09:11:32

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 05/16] mwifiex: support for event done interrupt

This patch adds support for writing CPU event interrupt done back
to device.
Patch also increases interrupt buffer ring size from 4 to 8.

Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
drivers/net/wireless/mwifiex/pcie.c | 7 +++++++
drivers/net/wireless/mwifiex/pcie.h | 5 +++--
2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 27c2bf8..2ada1b7 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -1726,6 +1726,13 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
buffer is released. This is just to make things simpler,
we need to find a better method of managing these buffers.
*/
+ } else {
+ if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+ CPU_INTR_EVENT_DONE)) {
+ dev_warn(adapter->dev,
+ "Write register failed\n");
+ return -1;
+ }
}

return 0;
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h
index a1a8fd3..200e8b0 100644
--- a/drivers/net/wireless/mwifiex/pcie.h
+++ b/drivers/net/wireless/mwifiex/pcie.h
@@ -40,8 +40,8 @@
#define MWIFIEX_TXBD_MASK 0x3F
#define MWIFIEX_RXBD_MASK 0x3F

-#define MWIFIEX_MAX_EVT_BD 0x04
-#define MWIFIEX_EVTBD_MASK 0x07
+#define MWIFIEX_MAX_EVT_BD 0x08
+#define MWIFIEX_EVTBD_MASK 0x0f

/* PCIE INTERNAL REGISTERS */
#define PCIE_SCRATCH_0_REG 0xC10
@@ -69,6 +69,7 @@
#define CPU_INTR_DOOR_BELL BIT(1)
#define CPU_INTR_SLEEP_CFM_DONE BIT(2)
#define CPU_INTR_RESET BIT(3)
+#define CPU_INTR_EVENT_DONE BIT(5)

#define HOST_INTR_DNLD_DONE BIT(0)
#define HOST_INTR_UPLD_RDY BIT(1)
--
1.8.1.4


2014-09-12 09:10:44

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 10/16] mwifiex: bring in scan channel gap feature

With scan channel gap when any station/AP is active, FW comes back
to connected channel for any pending data transfter after scanning each
channel.
We set scan channel gap TLV to FW in scan command when any of the
interface is active. This enables scan channel gap in FW.
Also when scan channel gap is enabled, we would scan maximum channels
allowed by FW.

Scan channel gap is supported only on FW with V15 FW API.

Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Marc Yang <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
drivers/net/wireless/mwifiex/cfg80211.c | 5 +++++
drivers/net/wireless/mwifiex/cmdevt.c | 3 +++
drivers/net/wireless/mwifiex/fw.h | 10 +++++++++-
drivers/net/wireless/mwifiex/init.c | 1 +
drivers/net/wireless/mwifiex/main.h | 23 +++++++++++++++++++++++
drivers/net/wireless/mwifiex/scan.c | 17 +++++++++++++++++
6 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 320512f..50cc0db 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1990,6 +1990,11 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
user_scan_cfg->chan_list[i].scan_time = 0;
}

+ if (priv->adapter->scan_chan_gap_enabled &&
+ mwifiex_is_any_intf_active(priv))
+ user_scan_cfg->scan_chan_gap =
+ priv->adapter->scan_chan_gap_time;
+
ret = mwifiex_scan_networks(priv, user_scan_cfg);
kfree(user_scan_cfg);
if (ret) {
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index fcc70ae..8559720 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -1613,5 +1613,8 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
adapter->if_ops.update_mp_end_port(adapter,
le16_to_cpu(hw_spec->mp_end_port));

+ if (adapter->fw_api_ver == MWIFIEX_FW_V15)
+ adapter->scan_chan_gap_enabled = true;
+
return 0;
}
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 6a703ea..1eb6173 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -170,7 +170,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154)
#define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156)
#define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194)
-#define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199)
+#define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197)
+#define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199)

#define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048

@@ -653,6 +654,12 @@ struct mwifiex_ie_types_num_probes {
__le16 num_probes;
} __packed;

+struct mwifiex_ie_types_scan_chan_gap {
+ struct mwifiex_ie_types_header header;
+ /* time gap in TUs to be used between two consecutive channels scan */
+ __le16 chan_gap;
+} __packed;
+
struct mwifiex_ie_types_wildcard_ssid_params {
struct mwifiex_ie_types_header header;
u8 max_ssid_length;
@@ -1249,6 +1256,7 @@ struct mwifiex_user_scan_cfg {
u8 num_ssids;
/* Variable number (fixed maximum) of channels to scan up */
struct mwifiex_user_scan_chan chan_list[MWIFIEX_USER_SCAN_CHAN_MAX];
+ u16 scan_chan_gap;
} __packed;

struct ie_body {
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 80bda80..d99c6f6 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -212,6 +212,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->specific_scan_time = MWIFIEX_SPECIFIC_SCAN_CHAN_TIME;
adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME;
adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME;
+ adapter->scan_chan_gap_time = MWIFIEX_DEF_SCAN_CHAN_GAP_TIME;

adapter->scan_probes = 1;

diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 5439963..c3d097c 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -84,6 +84,7 @@ enum {
#define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 110
#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 30
#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 30
+#define MWIFIEX_DEF_SCAN_CHAN_GAP_TIME 50

#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI)))

@@ -770,6 +771,7 @@ struct mwifiex_adapter {
u16 specific_scan_time;
u16 active_scan_time;
u16 passive_scan_time;
+ u16 scan_chan_gap_time;
u8 fw_bands;
u8 adhoc_start_band;
u8 config_bands;
@@ -839,6 +841,7 @@ struct mwifiex_adapter {
struct memory_type_mapping *mem_type_mapping_tbl;
u8 num_mem_types;
u8 curr_mem_idx;
+ bool scan_chan_gap_enabled;
};

int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -1139,6 +1142,25 @@ mwifiex_11h_get_csa_closed_channel(struct mwifiex_private *priv)
return priv->csa_chan;
}

+static inline u8 mwifiex_is_any_intf_active(struct mwifiex_private *priv)
+{
+ struct mwifiex_private *priv_num;
+ int i;
+
+ for (i = 0; i < priv->adapter->priv_num; i++) {
+ priv_num = priv->adapter->priv[i];
+ if (priv_num) {
+ if ((GET_BSS_ROLE(priv_num) == MWIFIEX_BSS_ROLE_UAP &&
+ priv_num->bss_started) ||
+ (GET_BSS_ROLE(priv_num) == MWIFIEX_BSS_ROLE_STA &&
+ priv_num->media_connected))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
@@ -1274,6 +1296,7 @@ void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv);
bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv);
u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
u32 pri_chan, u8 chan_bw);
+int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter);

#ifdef CONFIG_DEBUG_FS
void mwifiex_debugfs_init(void);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index bec48cc..6fd69af 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -799,6 +799,7 @@ mwifiex_config_scan(struct mwifiex_private *priv,
{
struct mwifiex_adapter *adapter = priv->adapter;
struct mwifiex_ie_types_num_probes *num_probes_tlv;
+ struct mwifiex_ie_types_scan_chan_gap *chan_gap_tlv;
struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
struct mwifiex_ie_types_bssid_list *bssid_tlv;
u8 *tlv_pos;
@@ -939,6 +940,22 @@ mwifiex_config_scan(struct mwifiex_private *priv,
else
*max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;

+ if (user_scan_in->scan_chan_gap) {
+ *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+ dev_dbg(adapter->dev, "info: scan: channel gap = %d\n",
+ user_scan_in->scan_chan_gap);
+
+ chan_gap_tlv = (void *)tlv_pos;
+ chan_gap_tlv->header.type =
+ cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
+ chan_gap_tlv->header.len =
+ cpu_to_le16(sizeof(chan_gap_tlv->chan_gap));
+ chan_gap_tlv->chan_gap =
+ cpu_to_le16((user_scan_in->scan_chan_gap));
+
+ tlv_pos += sizeof(struct mwifiex_ie_types_scan_chan_gap);
+ }
+
/* If the input config or adapter has the number of Probes set,
add tlv */
if (num_probes) {
--
1.8.1.4


2014-09-12 09:10:15

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 04/16] mwifiex: rework internal scan for association

There was an issue with internal scan during association wherein
we would complete internal scan on first scan command response.
This would cause association failure if AP is not found in first scan
response e.g. APs from A band.
This patch fixes this issue by completing internal scan only when all
scan commands from scan pending queue and command pending queue are
sent to FW and response to last scan command is received.

Tested-by: Xinmin Hu <[email protected]>
Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Marc Yang <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
drivers/net/wireless/mwifiex/scan.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index dee717a..bec48cc 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1970,9 +1970,34 @@ int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
/* This function handles the command response of extended scan */
int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv)
{
+ struct mwifiex_adapter *adapter = priv->adapter;
+ struct host_cmd_ds_command *cmd_ptr;
+ struct cmd_ctrl_node *cmd_node;
+ unsigned long cmd_flags, scan_flags;
+ bool complete_scan = false;
+
dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n");

- mwifiex_complete_scan(priv);
+ spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
+ spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
+ if (list_empty(&adapter->scan_pending_q)) {
+ complete_scan = true;
+ list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
+ cmd_ptr = (void *)cmd_node->cmd_skb->data;
+ if (le16_to_cpu(cmd_ptr->command) ==
+ HostCmd_CMD_802_11_SCAN_EXT) {
+ dev_dbg(priv->adapter->dev,
+ "Scan pending in command pending list");
+ complete_scan = false;
+ break;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags);
+ spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags);
+
+ if (complete_scan)
+ mwifiex_complete_scan(priv);

return 0;
}
--
1.8.1.4


2014-09-12 09:10:42

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 09/16] mwifiex: set passive scan type for scan requests with no ssid

It was observed that station would sent probe request even when
scan type has been set as passive during iw scan.
This was happening because driver sets passive scan type only
when channel has IEEE80211_CHAN_NO_IR flag set.
Along with this, add condition to check if no ssids are specified in
scan request so as to mark such scan request passive.

Signed-off-by: Avinash Patil <[email protected]>
---
drivers/net/wireless/mwifiex/cfg80211.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index e2e6bf1..320512f 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1980,7 +1980,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
user_scan_cfg->chan_list[i].radio_type = chan->band;

- if (chan->flags & IEEE80211_CHAN_NO_IR)
+ if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids)
user_scan_cfg->chan_list[i].scan_type =
MWIFIEX_SCAN_TYPE_PASSIVE;
else
--
1.8.1.4


2014-09-12 09:10:29

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 07/16] mwifiex: fix a bug in Tx multiport aggregation

From: Amitkumar Karwar <[email protected]>

When aggregation port limit is reached, we stop aggregation and
the data is sent to firmware. It is observed that one less packet
than the port limit is aggregated in this case. ex. 15 instead of
16.
The reason is we have redundant port limit checks before current
packet is added to aggregation buffer.

The issue is fixed by removing these checks. We already have
necessary check in precopy current buffer handling.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
---
drivers/net/wireless/mwifiex/sdio.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 1770fa3..993841e 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -1527,8 +1527,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
__func__);

if (MP_TX_AGGR_IN_PROGRESS(card)) {
- if (!mp_tx_aggr_port_limit_reached(card) &&
- MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) {
+ if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) {
f_precopy_cur_buf = 1;

if (!(card->mp_wr_bitmap &
@@ -1540,8 +1539,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
/* No room in Aggr buf, send it */
f_send_aggr_buf = 1;

- if (mp_tx_aggr_port_limit_reached(card) ||
- !(card->mp_wr_bitmap &
+ if (!(card->mp_wr_bitmap &
(1 << card->curr_wr_port)))
f_send_cur_buf = 1;
else
--
1.8.1.4


2014-09-12 09:11:37

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 16/16] mwifiex: modify TX/RX window sizes for AP interface

This patch sets uAP BA window sizes to 64.

Signed-off-by: Avinash Patil <[email protected]>
---
drivers/net/wireless/mwifiex/decl.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 0e03fe3..e0d00a7 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -48,8 +48,8 @@
#define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE 16
#define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE 64
#define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE 64
-#define MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE 48
-#define MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE 32
+#define MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE 64
+#define MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE 64

#define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff

--
1.8.1.4


2014-09-12 09:10:32

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 08/16] mwifiex: minor cleanup in multiport aggregation

From: Amitkumar Karwar <[email protected]>

'mp_data_port_mask' and 'mp_end_port' gives correct information
even for the chipsets supporting SDIO new mode (32 ports).
We will get rid of this chip specific handling.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
---
drivers/net/wireless/mwifiex/sdio.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 993841e..bdab122 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -622,22 +622,15 @@ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u32 *port)

dev_dbg(adapter->dev, "data: mp_wr_bitmap=0x%08x\n", wr_bitmap);

- if (card->supports_sdio_new_mode &&
- !(wr_bitmap & reg->data_port_mask)) {
+ if (!(wr_bitmap & card->mp_data_port_mask)) {
adapter->data_sent = true;
return -EBUSY;
- } else if (!card->supports_sdio_new_mode &&
- !(wr_bitmap & card->mp_data_port_mask)) {
- return -1;
}

if (card->mp_wr_bitmap & (1 << card->curr_wr_port)) {
card->mp_wr_bitmap &= (u32) (~(1 << card->curr_wr_port));
*port = card->curr_wr_port;
- if (((card->supports_sdio_new_mode) &&
- (++card->curr_wr_port == card->max_ports)) ||
- ((!card->supports_sdio_new_mode) &&
- (++card->curr_wr_port == card->mp_end_port)))
+ if (++card->curr_wr_port == card->mp_end_port)
card->curr_wr_port = reg->start_wr_port;
} else {
adapter->data_sent = true;
--
1.8.1.4


2014-09-12 09:11:43

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 13/16] mwifiex: remove redundant variable report_scan_result

From: Amitkumar Karwar <[email protected]>

This variable is never used, get rid of it.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Avinash Patil <[email protected]>
---
drivers/net/wireless/mwifiex/main.h | 1 -
drivers/net/wireless/mwifiex/scan.c | 3 ---
drivers/net/wireless/mwifiex/sta_cmdresp.c | 2 --
3 files changed, 6 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index c3d097c..651fd8c 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -548,7 +548,6 @@ struct mwifiex_private {
u8 nick_name[16];
u16 current_key_index;
struct semaphore async_sem;
- u8 report_scan_result;
struct cfg80211_scan_request *scan_request;
u8 cfg_bssid[6];
struct wps wps;
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 7c85f61..7b07da2 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1778,9 +1778,6 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
if (!adapter->ext_scan)
mwifiex_complete_scan(priv);

- if (priv->report_scan_result)
- priv->report_scan_result = false;
-
if (priv->scan_request) {
dev_dbg(adapter->dev, "info: notifying scan done\n");
cfg80211_scan_done(priv->scan_request, 0);
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 62866b0..4aad446 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -85,8 +85,6 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->scan_processing = false;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
- if (priv->report_scan_result)
- priv->report_scan_result = false;
break;

case HostCmd_CMD_MAC_CONTROL:
--
1.8.1.4


2014-09-12 09:10:40

by Avinash Patil

[permalink] [raw]
Subject: [PATCHv2 12/16] mwifiex: process TX even when scan is ongoing

With channel scan gap, FW comes back to connected channel after each
single channel scan. So we can safely transfer data to FW during scan.
FW would send this data once on connected channel.

Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
drivers/net/wireless/mwifiex/main.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index dfa37ea..d6d2342 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -284,8 +284,9 @@ process_start:
adapter->tx_lock_flag)
break;

- if ((adapter->scan_processing &&
- !adapter->scan_delay_cnt) || adapter->data_sent ||
+ if ((!adapter->scan_chan_gap_enabled &&
+ !adapter->scan_delay_cnt &&
+ adapter->scan_processing) || adapter->data_sent ||
mwifiex_wmm_lists_empty(adapter)) {
if (adapter->cmd_sent || adapter->curr_cmd ||
(!is_command_pending(adapter)))
@@ -339,7 +340,8 @@ process_start:
}
}

- if ((!adapter->scan_processing || adapter->scan_delay_cnt) &&
+ if ((adapter->scan_chan_gap_enabled ||
+ (!adapter->scan_processing || adapter->scan_delay_cnt)) &&
!adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) {
mwifiex_wmm_process_tx(adapter);
if (adapter->hs_activated) {
--
1.8.1.4