linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 1/6] mwifiex: use variable interface header length
@ 2017-05-19  9:06 Xinming Hu
  2017-05-19  9:06 ` [PATCH v3 2/6] mwifiex: usb: kill urb before free its memory Xinming Hu
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Xinming Hu @ 2017-05-19  9:06 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, rajatja, Zhiyuan Yang,
	Cathy Luo, Xinming Hu, Ganapathi Bhat

From: Xinming Hu <huxm@marvell.com>

Usb tx aggregation feature will utilize 4-bytes bus interface header,
otherwise it will be set to zero in default case.

Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
---
v3: same as v1,v2
---
 drivers/net/wireless/marvell/mwifiex/11n_aggr.c |  2 +-
 drivers/net/wireless/marvell/mwifiex/cmdevt.c   |  8 ++++----
 drivers/net/wireless/marvell/mwifiex/init.c     |  5 +++++
 drivers/net/wireless/marvell/mwifiex/main.h     |  1 +
 drivers/net/wireless/marvell/mwifiex/pcie.c     | 19 ++++++++++---------
 drivers/net/wireless/marvell/mwifiex/sdio.c     | 12 ++++++------
 drivers/net/wireless/marvell/mwifiex/sta_tx.c   | 12 ++++++------
 drivers/net/wireless/marvell/mwifiex/txrx.c     | 11 +++--------
 drivers/net/wireless/marvell/mwifiex/uap_txrx.c |  5 ++---
 9 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
index a75013a..e8ffb26 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
@@ -164,7 +164,7 @@
 	int pad = 0, aggr_num = 0, ret;
 	struct mwifiex_tx_param tx_param;
 	struct txpd *ptx_pd = NULL;
-	int headroom = adapter->iface_type == MWIFIEX_USB ? 0 : INTF_HEADER_LEN;
+	int headroom = adapter->intf_hdr_len;
 
 	skb_src = skb_peek(&pra_list->skb_head);
 	if (!skb_src) {
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 0c3b217..d62f729 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -258,10 +258,10 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
 		if (ret == -EBUSY)
 			cmd_node->cmd_skb = NULL;
 	} else {
-		skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN);
+		skb_push(cmd_node->cmd_skb, adapter->intf_hdr_len);
 		ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
 						   cmd_node->cmd_skb, NULL);
-		skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN);
+		skb_pull(cmd_node->cmd_skb, adapter->intf_hdr_len);
 	}
 
 	if (ret == -1) {
@@ -351,10 +351,10 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
 		if (ret != -EBUSY)
 			dev_kfree_skb_any(sleep_cfm_tmp);
 	} else {
-		skb_push(adapter->sleep_cfm, INTF_HEADER_LEN);
+		skb_push(adapter->sleep_cfm, adapter->intf_hdr_len);
 		ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
 						   adapter->sleep_cfm, NULL);
-		skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN);
+		skb_pull(adapter->sleep_cfm, adapter->intf_hdr_len);
 	}
 
 	if (ret == -1) {
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index 7569483..0710b917 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -217,6 +217,11 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
 	else
 		adapter->data_sent = false;
 
+	if (adapter->iface_type == MWIFIEX_USB)
+		adapter->intf_hdr_len = 0;
+	else
+		adapter->intf_hdr_len = INTF_HEADER_LEN;
+
 	adapter->cmd_resp_received = false;
 	adapter->event_received = false;
 	adapter->data_received = false;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 6e76b30..ee496ab 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -849,6 +849,7 @@ struct mwifiex_adapter {
 	u8 perm_addr[ETH_ALEN];
 	bool surprise_removed;
 	u32 fw_release_number;
+	u8 intf_hdr_len;
 	u16 init_wait_q_woken;
 	wait_queue_head_t init_wait_q;
 	void *card;
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 78688ff..e47326e 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -1391,7 +1391,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
 		 * first 2 bytes for len, next 2 bytes is for type
 		 */
 		rx_len = get_unaligned_le16(skb_data->data);
-		if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
+		if (WARN_ON(rx_len <= adapter->intf_hdr_len ||
 			    rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
 			mwifiex_dbg(adapter, ERROR,
 				    "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
@@ -1402,7 +1402,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
 			mwifiex_dbg(adapter, DATA,
 				    "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
 				    card->rxbd_rdptr, wrptr, rx_len);
-			skb_pull(skb_data, INTF_HEADER_LEN);
+			skb_pull(skb_data, adapter->intf_hdr_len);
 			if (adapter->rx_work_enabled) {
 				skb_queue_tail(&adapter->rx_data_q, skb_data);
 				adapter->data_received = true;
@@ -1736,7 +1736,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
 						       MWIFIEX_MAX_DELAY_COUNT);
 			mwifiex_unmap_pci_memory(adapter, skb,
 						 PCI_DMA_FROMDEVICE);
-			skb_pull(skb, INTF_HEADER_LEN);
+			skb_pull(skb, adapter->intf_hdr_len);
 			while (reg->sleep_cookie && (count++ < 10) &&
 			       mwifiex_pcie_ok_to_access_hw(adapter))
 				usleep_range(50, 60);
@@ -1749,12 +1749,12 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
 		}
 		memcpy(adapter->upld_buf, skb->data,
 		       min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
-		skb_push(skb, INTF_HEADER_LEN);
+		skb_push(skb, adapter->intf_hdr_len);
 		if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
 					   PCI_DMA_FROMDEVICE))
 			return -1;
 	} else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
-		skb_pull(skb, INTF_HEADER_LEN);
+		skb_pull(skb, adapter->intf_hdr_len);
 		adapter->curr_cmd->resp_skb = skb;
 		adapter->cmd_resp_received = true;
 		/* Take the pointer and set it to CMD node and will
@@ -1791,7 +1791,7 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
 
 	if (skb) {
 		card->cmdrsp_buf = skb;
-		skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
+		skb_push(card->cmdrsp_buf, adapter->intf_hdr_len);
 		if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
 					   PCI_DMA_FROMDEVICE))
 			return -1;
@@ -1856,14 +1856,15 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
 		desc = card->evtbd_ring[rdptr];
 		memset(desc, 0, sizeof(*desc));
 
-		event = get_unaligned_le32(&skb_cmd->data[INTF_HEADER_LEN]);
+		event = get_unaligned_le32(
+			&skb_cmd->data[adapter->intf_hdr_len]);
 		adapter->event_cause = event;
 		/* The first 4bytes will be the event transfer header
 		   len is 2 bytes followed by type which is 2 bytes */
 		memcpy(&data_len, skb_cmd->data, sizeof(__le16));
 		evt_len = le16_to_cpu(data_len);
 		skb_trim(skb_cmd, evt_len);
-		skb_pull(skb_cmd, INTF_HEADER_LEN);
+		skb_pull(skb_cmd, adapter->intf_hdr_len);
 		mwifiex_dbg(adapter, EVENT,
 			    "info: Event length: %d\n", evt_len);
 
@@ -1922,7 +1923,7 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
 	}
 
 	if (!card->evt_buf_list[rdptr]) {
-		skb_push(skb, INTF_HEADER_LEN);
+		skb_push(skb, adapter->intf_hdr_len);
 		skb_put(skb, MAX_EVENT_SIZE - skb->len);
 		if (mwifiex_map_pci_memory(adapter, skb,
 					   MAX_EVENT_SIZE,
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index d38d31b..f81a006 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -1125,7 +1125,7 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
 	data = skb->data;
 	total_pkt_len = skb->len;
 
-	while (total_pkt_len >= (SDIO_HEADER_OFFSET + INTF_HEADER_LEN)) {
+	while (total_pkt_len >= (SDIO_HEADER_OFFSET + adapter->intf_hdr_len)) {
 		if (total_pkt_len < adapter->sdio_rx_block_size)
 			break;
 		blk_num = *(data + BLOCK_NUMBER_OFFSET);
@@ -1152,7 +1152,7 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
 			break;
 		skb_put(skb_deaggr, pkt_len);
 		memcpy(skb_deaggr->data, data + SDIO_HEADER_OFFSET, pkt_len);
-		skb_pull(skb_deaggr, INTF_HEADER_LEN);
+		skb_pull(skb_deaggr, adapter->intf_hdr_len);
 
 		mwifiex_handle_rx_packet(adapter, skb_deaggr);
 		data += blk_size;
@@ -1178,7 +1178,7 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
 
 	if (upld_typ != MWIFIEX_TYPE_AGGR_DATA) {
 		skb_trim(skb, pkt_len);
-		skb_pull(skb, INTF_HEADER_LEN);
+		skb_pull(skb, adapter->intf_hdr_len);
 	}
 
 	switch (upld_typ) {
@@ -1537,7 +1537,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
 		rx_len = card->mp_regs[reg->cmd_rd_len_1] << 8;
 		rx_len |= (u16)card->mp_regs[reg->cmd_rd_len_0];
 		rx_blocks = DIV_ROUND_UP(rx_len, MWIFIEX_SDIO_BLOCK_SIZE);
-		if (rx_len <= INTF_HEADER_LEN ||
+		if (rx_len <= adapter->intf_hdr_len ||
 		    (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
 		     MWIFIEX_RX_DATA_BUF_SIZE)
 			return -1;
@@ -1635,7 +1635,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
 			rx_blocks =
 				(rx_len + MWIFIEX_SDIO_BLOCK_SIZE -
 				 1) / MWIFIEX_SDIO_BLOCK_SIZE;
-			if (rx_len <= INTF_HEADER_LEN ||
+			if (rx_len <= adapter->intf_hdr_len ||
 			    (card->mpa_rx.enabled &&
 			     ((rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
 			      card->mpa_rx.buf_size))) {
@@ -1896,7 +1896,7 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
 		adapter->cmd_sent = true;
 		/* Type must be MWIFIEX_TYPE_CMD */
 
-		if (pkt_len <= INTF_HEADER_LEN ||
+		if (pkt_len <= adapter->intf_hdr_len ||
 		    pkt_len > MWIFIEX_UPLD_SIZE)
 			mwifiex_dbg(adapter, ERROR,
 				    "%s: payload=%p, nb=%d\n",
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_tx.c b/drivers/net/wireless/marvell/mwifiex/sta_tx.c
index f6683ea..620f865 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_tx.c
@@ -49,8 +49,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
 	struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
 	unsigned int pad;
 	u16 pkt_type, pkt_offset;
-	int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
-		       INTF_HEADER_LEN;
+	int hroom = adapter->intf_hdr_len;
 
 	if (!skb->len) {
 		mwifiex_dbg(adapter, ERROR,
@@ -116,7 +115,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
 
 	local_tx_pd->tx_pkt_offset = cpu_to_le16(pkt_offset);
 
-	/* make space for INTF_HEADER_LEN */
+	/* make space for adapter->intf_hdr_len */
 	skb_push(skb, hroom);
 
 	if (!local_tx_pd->tx_control)
@@ -165,8 +164,9 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
 	memset(tx_info, 0, sizeof(*tx_info));
 	tx_info->bss_num = priv->bss_num;
 	tx_info->bss_type = priv->bss_type;
-	tx_info->pkt_len = data_len - (sizeof(struct txpd) + INTF_HEADER_LEN);
-	skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN);
+	tx_info->pkt_len = data_len -
+			(sizeof(struct txpd) + adapter->intf_hdr_len);
+	skb_reserve(skb, sizeof(struct txpd) + adapter->intf_hdr_len);
 	skb_push(skb, sizeof(struct txpd));
 
 	local_tx_pd = (struct txpd *) skb->data;
@@ -177,11 +177,11 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
 	local_tx_pd->bss_num = priv->bss_num;
 	local_tx_pd->bss_type = priv->bss_type;
 
+	skb_push(skb, adapter->intf_hdr_len);
 	if (adapter->iface_type == MWIFIEX_USB) {
 		ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
 						   skb, NULL);
 	} else {
-		skb_push(skb, INTF_HEADER_LEN);
 		tx_param.next_pkt_len = 0;
 		ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
 						   skb, &tx_param);
diff --git a/drivers/net/wireless/marvell/mwifiex/txrx.c b/drivers/net/wireless/marvell/mwifiex/txrx.c
index fac28bd..15e92af 100644
--- a/drivers/net/wireless/marvell/mwifiex/txrx.c
+++ b/drivers/net/wireless/marvell/mwifiex/txrx.c
@@ -91,7 +91,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
 	struct mwifiex_sta_node *dest_node;
 	struct ethhdr *hdr = (void *)skb->data;
 
-	hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
+	hroom = adapter->intf_hdr_len;
 
 	if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
 		dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest);
@@ -179,13 +179,8 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
 		mwifiex_write_data_complete(adapter, skb, 0, 0);
 		return ret;
 	}
-	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
-		if (adapter->iface_type == MWIFIEX_USB)
-			local_tx_pd = (struct txpd *)head_ptr;
-		else
-			local_tx_pd = (struct txpd *) (head_ptr +
-				INTF_HEADER_LEN);
-	}
+	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
+		local_tx_pd = (struct txpd *)(head_ptr + adapter->intf_hdr_len);
 
 	if (adapter->iface_type == MWIFIEX_USB) {
 		ret = adapter->if_ops.host_to_card(adapter,
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
index bf5660e..1e6a62c 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
@@ -468,8 +468,7 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
 	struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
 	int pad;
 	u16 pkt_type, pkt_offset;
-	int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
-		       INTF_HEADER_LEN;
+	int hroom = adapter->intf_hdr_len;
 
 	if (!skb->len) {
 		mwifiex_dbg(adapter, ERROR,
@@ -521,7 +520,7 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
 
 	txpd->tx_pkt_offset = cpu_to_le16(pkt_offset);
 
-	/* make space for INTF_HEADER_LEN */
+	/* make space for adapter->intf_hdr_len */
 	skb_push(skb, hroom);
 
 	if (!txpd->tx_control)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 2/6] mwifiex: usb: kill urb before free its memory
  2017-05-19  9:06 [PATCH v3 1/6] mwifiex: use variable interface header length Xinming Hu
@ 2017-05-19  9:06 ` Xinming Hu
  2017-05-19  9:06 ` [PATCH v3 3/6] mwifiex: usb: transmit aggregation packets Xinming Hu
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Xinming Hu @ 2017-05-19  9:06 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, rajatja, Zhiyuan Yang,
	Cathy Luo, Xinming Hu

From: Xinming Hu <huxm@marvell.com>

we have observed host system hang when device firmware crash,
stack trace show it was an use-after-free case: previous submitted
urb will be holding in usbcore, and given back to device driver
when device disconnected, while the urb have been freed in usb
device disconnect handler. This patch kill the holding urb before
free its memory.

Signed-off-by: Xinming Hu <huxm@marvell.com>
---
v2: replace unnecessary sanity check with right handle of
    pending urb (Arend)
v3: same as v2
---
 drivers/net/wireless/marvell/mwifiex/usb.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 2f7705c..5a760ec 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -363,6 +363,7 @@ static void mwifiex_usb_free(struct usb_card_rec *card)
 	for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
 		port = &card->port[i];
 		for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+			usb_kill_urb(port->tx_data_list[j].urb);
 			usb_free_urb(port->tx_data_list[j].urb);
 			port->tx_data_list[j].urb = NULL;
 		}
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 3/6] mwifiex: usb: transmit aggregation packets
  2017-05-19  9:06 [PATCH v3 1/6] mwifiex: use variable interface header length Xinming Hu
  2017-05-19  9:06 ` [PATCH v3 2/6] mwifiex: usb: kill urb before free its memory Xinming Hu
@ 2017-05-19  9:06 ` Xinming Hu
  2017-05-19  9:06 ` [PATCH v3 4/6] mwifiex: usb: add timer to flush " Xinming Hu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Xinming Hu @ 2017-05-19  9:06 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, rajatja, Zhiyuan Yang,
	Cathy Luo, Xinming Hu, Ganapathi Bhat

From: Xinming Hu <huxm@marvell.com>

Instead of using 4KB packet buffer for data transfer, new chipset have
more device memory. This patch try to aggregation packets in an 16KB
buffer. In this way, totally usb transaction cost will be reduced.

Thoughput test on usb 2.0 show both TCP TX and UPD TX promote ~40M,
from ~240M to ~280M.

This feature is default disabled, and can be enabled by module
parameter, like:
insmod mwifiex.ko aggr_ctrl=1

Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
---
v3: same as v1,v2
---
 drivers/net/wireless/marvell/mwifiex/fw.h          |  10 +
 drivers/net/wireless/marvell/mwifiex/main.c        |   4 +
 drivers/net/wireless/marvell/mwifiex/main.h        |  15 +
 drivers/net/wireless/marvell/mwifiex/sta_cmd.c     |  18 ++
 drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c |  24 ++
 drivers/net/wireless/marvell/mwifiex/usb.c         | 355 ++++++++++++++++++---
 drivers/net/wireless/marvell/mwifiex/usb.h         |   9 +
 7 files changed, 382 insertions(+), 53 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 6cf9ab9..b4d915b 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -405,6 +405,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_TDLS_OPER                         0x0122
 #define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG               0x0223
 #define HostCmd_CMD_CHAN_REGION_CFG		      0x0242
+#define HostCmd_CMD_PACKET_AGGR_CTRL		      0x0251
 
 #define PROTOCOL_NO_SECURITY        0x01
 #define PROTOCOL_STATIC_WEP         0x02
@@ -2268,6 +2269,14 @@ struct host_cmd_ds_chan_region_cfg {
 	__le16 action;
 } __packed;
 
+struct host_cmd_ds_pkt_aggr_ctrl {
+	__le16 action;
+	__le16 enable;
+	__le16 tx_aggr_max_size;
+	__le16 tx_aggr_max_num;
+	__le16 tx_aggr_align;
+} __packed;
+
 struct host_cmd_ds_command {
 	__le16 command;
 	__le16 size;
@@ -2343,6 +2352,7 @@ struct host_cmd_ds_command {
 		struct host_cmd_ds_wakeup_reason hs_wakeup_reason;
 		struct host_cmd_ds_gtk_rekey_params rekey;
 		struct host_cmd_ds_chan_region_cfg reg_cfg;
+		struct host_cmd_ds_pkt_aggr_ctrl pkt_aggr_ctrl;
 	} params;
 } __packed;
 
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index dd87b9f..2c42191 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -44,6 +44,10 @@
 module_param(mfg_mode, bool, 0);
 MODULE_PARM_DESC(mfg_mode, "manufacturing mode enable:1, disable:0");
 
+bool aggr_ctrl;
+module_param(aggr_ctrl, bool, 0000);
+MODULE_PARM_DESC(aggr_ctrl, "usb tx aggreataon enable:1, disable:0");
+
 /*
  * This function registers the device and performs all the necessary
  * initializations.
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index ee496ab..1f7e6c3 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -60,6 +60,7 @@
 
 extern const char driver_version[];
 extern bool mfg_mode;
+extern bool aggr_ctrl;
 
 struct mwifiex_adapter;
 struct mwifiex_private;
@@ -798,6 +799,18 @@ struct mwifiex_auto_tdls_peer {
 	u8 do_setup;
 };
 
+#define MWIFIEX_TYPE_AGGR_DATA_V2 11
+#define MWIFIEX_BUS_AGGR_MODE_LEN_V2 (2)
+#define MWIFIEX_BUS_AGGR_MAX_LEN 16000
+#define MWIFIEX_BUS_AGGR_MAX_NUM 10
+struct bus_aggr_params {
+	u16 enable;
+	u16 mode;
+	u16 tx_aggr_max_size;
+	u16 tx_aggr_max_num;
+	u16 tx_aggr_align;
+};
+
 struct mwifiex_if_ops {
 	int (*init_if) (struct mwifiex_adapter *);
 	void (*cleanup_if) (struct mwifiex_adapter *);
@@ -1018,6 +1031,8 @@ struct mwifiex_adapter {
 	/* Wake-on-WLAN (WoWLAN) */
 	int irq_wakeup;
 	bool wake_by_wifi;
+	/* Aggregation parameters*/
+	struct bus_aggr_params bus_aggr;
 };
 
 void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index 83916c1..534d94a 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -2064,6 +2064,15 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
 	case HostCmd_CMD_11AC_CFG:
 		ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf);
 		break;
+	case HostCmd_CMD_PACKET_AGGR_CTRL:
+		cmd_ptr->command = cpu_to_le16(cmd_no);
+		cmd_ptr->params.pkt_aggr_ctrl.action = cpu_to_le16(cmd_action);
+		cmd_ptr->params.pkt_aggr_ctrl.enable =
+						cpu_to_le16(*(u16 *)data_buf);
+		cmd_ptr->size =
+			cpu_to_le16(sizeof(struct host_cmd_ds_pkt_aggr_ctrl) +
+				    S_DS_GEN);
+		break;
 	case HostCmd_CMD_P2P_MODE_CFG:
 		cmd_ptr->command = cpu_to_le16(cmd_no);
 		cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action);
@@ -2241,6 +2250,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
 	enum state_11d_t state_11d;
 	struct mwifiex_ds_11n_tx_cfg tx_cfg;
 	u8 sdio_sp_rx_aggr_enable;
+	u16 packet_aggr_enable;
 	int data;
 
 	if (first_sta) {
@@ -2387,6 +2397,14 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
 				    "11D: failed to enable 11D\n");
 	}
 
+	/* Pacekt aggregation handshake with firmware */
+	if (aggr_ctrl) {
+		packet_aggr_enable = true;
+		mwifiex_send_cmd(priv, HostCmd_CMD_PACKET_AGGR_CTRL,
+				 HostCmd_ACT_GEN_SET, 0,
+				 &packet_aggr_enable, true);
+	}
+
 	/* Send cmd to FW to configure 11n specific configuration
 	 * (Short GI, Channel BW, Green field support etc.) for transmit
 	 */
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
index f1d1f56..3348fb3 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
@@ -1154,6 +1154,27 @@ static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
 	return 0;
 }
 
+int mwifiex_ret_pkt_aggr_ctrl(struct mwifiex_private *priv,
+			      struct host_cmd_ds_command *resp)
+{
+	struct host_cmd_ds_pkt_aggr_ctrl *pkt_aggr_ctrl =
+					&resp->params.pkt_aggr_ctrl;
+	struct mwifiex_adapter *adapter = priv->adapter;
+
+	adapter->bus_aggr.enable = le16_to_cpu(pkt_aggr_ctrl->enable);
+	if (adapter->bus_aggr.enable)
+		adapter->intf_hdr_len = INTF_HEADER_LEN;
+	adapter->bus_aggr.mode = MWIFIEX_BUS_AGGR_MODE_LEN_V2;
+	adapter->bus_aggr.tx_aggr_max_size =
+				le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_size);
+	adapter->bus_aggr.tx_aggr_max_num =
+				le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_num);
+	adapter->bus_aggr.tx_aggr_align =
+				le16_to_cpu(pkt_aggr_ctrl->tx_aggr_align);
+
+	return 0;
+}
+
 /*
  * This function handles the command responses.
  *
@@ -1255,6 +1276,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
 		break;
 	case HostCmd_CMD_11AC_CFG:
 		break;
+	case HostCmd_CMD_PACKET_AGGR_CTRL:
+		ret = mwifiex_ret_pkt_aggr_ctrl(priv, resp);
+		break;
 	case HostCmd_CMD_P2P_MODE_CFG:
 		ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
 		break;
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 5a760ec..e13f758d 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -680,6 +680,7 @@ static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
 		if (!port->tx_data_ep)
 			continue;
 		port->tx_data_ix = 0;
+		skb_queue_head_init(&port->tx_aggr.aggr_list);
 		if (port->tx_data_ep == MWIFIEX_USB_EP_DATA)
 			port->block_status = false;
 		else
@@ -846,73 +847,31 @@ static inline u8 mwifiex_usb_data_sent(struct mwifiex_adapter *adapter)
 	return true;
 }
 
-/* This function write a command/data packet to card. */
-static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
-				    struct sk_buff *skb,
-				    struct mwifiex_tx_param *tx_param)
+static int mwifiex_usb_construct_send_urb(struct mwifiex_adapter *adapter,
+					  struct usb_tx_data_port *port, u8 ep,
+					  struct urb_context *context,
+					  struct sk_buff *skb_send)
 {
 	struct usb_card_rec *card = adapter->card;
-	struct urb_context *context = NULL;
-	struct usb_tx_data_port *port = NULL;
-	u8 *data = (u8 *)skb->data;
+	int ret = -EINPROGRESS;
 	struct urb *tx_urb;
-	int idx, ret = -EINPROGRESS;
-
-	if (adapter->is_suspended) {
-		mwifiex_dbg(adapter, ERROR,
-			    "%s: not allowed while suspended\n", __func__);
-		return -1;
-	}
-
-	if (adapter->surprise_removed) {
-		mwifiex_dbg(adapter, ERROR, "%s: device removed\n", __func__);
-		return -1;
-	}
-
-	mwifiex_dbg(adapter, INFO, "%s: ep=%d\n", __func__, ep);
-
-	if (ep == card->tx_cmd_ep) {
-		context = &card->tx_cmd;
-	} else {
-		for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
-			if (ep == card->port[idx].tx_data_ep) {
-				port = &card->port[idx];
-				if (atomic_read(&port->tx_data_urb_pending)
-				    >= MWIFIEX_TX_DATA_URB) {
-					port->block_status = true;
-					adapter->data_sent =
-						mwifiex_usb_data_sent(adapter);
-					return -EBUSY;
-				}
-				if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
-					port->tx_data_ix = 0;
-				context =
-					&port->tx_data_list[port->tx_data_ix++];
-				break;
-			}
-		}
-		if (!port) {
-			mwifiex_dbg(adapter, ERROR, "Wrong usb tx data port\n");
-			return -1;
-		}
-	}
 
 	context->adapter = adapter;
 	context->ep = ep;
-	context->skb = skb;
+	context->skb = skb_send;
 	tx_urb = context->urb;
 
 	if (ep == card->tx_cmd_ep &&
 	    card->tx_cmd_ep_type == USB_ENDPOINT_XFER_INT)
 		usb_fill_int_urb(tx_urb, card->udev,
-				 usb_sndintpipe(card->udev, ep), data,
-				 skb->len, mwifiex_usb_tx_complete,
+				 usb_sndintpipe(card->udev, ep), skb_send->data,
+				 skb_send->len, mwifiex_usb_tx_complete,
 				 (void *)context, card->tx_cmd_interval);
 	else
 		usb_fill_bulk_urb(tx_urb, card->udev,
-				  usb_sndbulkpipe(card->udev, ep), data,
-				  skb->len, mwifiex_usb_tx_complete,
-				  (void *)context);
+				  usb_sndbulkpipe(card->udev, ep),
+				  skb_send->data, skb_send->len,
+				  mwifiex_usb_tx_complete, (void *)context);
 
 	tx_urb->transfer_flags |= URB_ZERO_PACKET;
 
@@ -949,6 +908,275 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
 	return ret;
 }
 
+static int mwifiex_usb_prepare_tx_aggr_skb(struct mwifiex_adapter *adapter,
+					   struct usb_tx_data_port *port,
+					   struct sk_buff **skb_send)
+{
+	struct sk_buff *skb_aggr, *skb_tmp;
+	u8 *payload, pad;
+	u16 align = adapter->bus_aggr.tx_aggr_align;
+	struct mwifiex_txinfo *tx_info = NULL;
+	bool is_txinfo_set = false;
+
+	skb_aggr = mwifiex_alloc_dma_align_buf(port->tx_aggr.aggr_len,
+					       GFP_ATOMIC);
+	if (!skb_aggr) {
+		mwifiex_dbg(adapter, ERROR,
+			    "%s: alloc skb_aggr failed\n", __func__);
+
+		while ((skb_tmp = skb_dequeue(&port->tx_aggr.aggr_list)))
+			mwifiex_write_data_complete(adapter, skb_tmp, 0, -1);
+
+		port->tx_aggr.aggr_num = 0;
+		port->tx_aggr.aggr_len = 0;
+		return -EBUSY;
+	}
+
+	tx_info = MWIFIEX_SKB_TXCB(skb_aggr);
+	memset(tx_info, 0, sizeof(*tx_info));
+
+	while ((skb_tmp = skb_dequeue(&port->tx_aggr.aggr_list))) {
+		/* padding for aligning next packet header*/
+		pad = (align - (skb_tmp->len & (align - 1))) % align;
+		payload = skb_put(skb_aggr, skb_tmp->len + pad);
+		memcpy(payload, skb_tmp->data, skb_tmp->len);
+		if (skb_queue_empty(&port->tx_aggr.aggr_list)) {
+			/* do not padding for last packet*/
+			*(u16 *)payload = cpu_to_le16(skb_tmp->len);
+			*(u16 *)&payload[2] =
+				cpu_to_le16(MWIFIEX_TYPE_AGGR_DATA_V2 | 0x80);
+			skb_trim(skb_aggr, skb_aggr->len - pad);
+		} else {
+			/* add aggregation interface header */
+			*(u16 *)payload = cpu_to_le16(skb_tmp->len + pad);
+			*(u16 *)&payload[2] =
+				cpu_to_le16(MWIFIEX_TYPE_AGGR_DATA_V2);
+		}
+
+		if (!is_txinfo_set) {
+			tx_info->bss_num = MWIFIEX_SKB_TXCB(skb_tmp)->bss_num;
+			tx_info->bss_type = MWIFIEX_SKB_TXCB(skb_tmp)->bss_type;
+			is_txinfo_set = true;
+		}
+
+		port->tx_aggr.aggr_num--;
+		port->tx_aggr.aggr_len -= (skb_tmp->len + pad);
+		mwifiex_write_data_complete(adapter, skb_tmp, 0, 0);
+	}
+
+	tx_info->pkt_len = skb_aggr->len -
+			(sizeof(struct txpd) + adapter->intf_hdr_len);
+	tx_info->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT;
+
+	port->tx_aggr.aggr_num = 0;
+	port->tx_aggr.aggr_len = 0;
+	*skb_send = skb_aggr;
+
+	return 0;
+}
+
+/* This function prepare data packet to be send under usb tx aggregation
+ * protocol, check current usb aggregation status, link packet to aggrgation
+ * list if possible, work flow as below:
+ * (1) if only 1 packet available, add usb tx aggregation header and send.
+ * (2) if packet is able to aggregated, link it to current aggregation list.
+ * (3) if packet is not able to aggregated, aggregate and send exist packets
+ *     in aggrgation list. Then, link packet in the list if there is more
+ *     packet in transmit queue, otherwise try to transmit single packet.
+ */
+static int mwifiex_usb_aggr_tx_data(struct mwifiex_adapter *adapter, u8 ep,
+				    struct sk_buff *skb,
+				    struct mwifiex_tx_param *tx_param,
+				    struct usb_tx_data_port *port)
+{
+	u8 *payload, pad;
+	u16 align = adapter->bus_aggr.tx_aggr_align;
+	struct sk_buff *skb_send = NULL;
+	struct urb_context *context = NULL;
+	struct txpd *local_tx_pd =
+		(struct txpd *)((u8 *)skb->data + adapter->intf_hdr_len);
+	u8 f_send_aggr_buf = 0;
+	u8 f_send_cur_buf = 0;
+	u8 f_precopy_cur_buf = 0;
+	u8 f_postcopy_cur_buf = 0;
+	int ret;
+
+	/* padding to ensure each packet alginment */
+	pad = (align - (skb->len & (align - 1))) % align;
+
+	if (tx_param && tx_param->next_pkt_len) {
+		/* next packet available in tx queue*/
+		if (port->tx_aggr.aggr_len + skb->len + pad >
+		    adapter->bus_aggr.tx_aggr_max_size) {
+			f_send_aggr_buf = 1;
+			f_postcopy_cur_buf = 1;
+		} else {
+			/* current packet could be aggregated*/
+			f_precopy_cur_buf = 1;
+
+			if (port->tx_aggr.aggr_len + skb->len + pad +
+			    tx_param->next_pkt_len >
+			    adapter->bus_aggr.tx_aggr_max_size ||
+			    port->tx_aggr.aggr_num + 2 >
+			    adapter->bus_aggr.tx_aggr_max_num) {
+			    /* next packet could not be aggregated
+			     * send current aggregation buffer
+			     */
+				f_send_aggr_buf = 1;
+			}
+		}
+	} else {
+		/* last packet in tx queue */
+		if (port->tx_aggr.aggr_num > 0) {
+			/* pending packets in aggregation buffer*/
+			if (port->tx_aggr.aggr_len + skb->len + pad >
+			    adapter->bus_aggr.tx_aggr_max_size) {
+				/* current packet not be able to aggregated,
+				 * send aggr buffer first, then send packet.
+				 */
+				f_send_cur_buf = 1;
+			} else {
+				/* last packet, Aggregation and send */
+				f_precopy_cur_buf = 1;
+			}
+
+			f_send_aggr_buf = 1;
+		} else {
+			/* no pending packets in aggregation buffer,
+			 * send current packet immediately
+			 */
+			 f_send_cur_buf = 1;
+		}
+	}
+
+	if (local_tx_pd->flags & MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET) {
+		/* Send NULL packet immediately*/
+		if (f_precopy_cur_buf) {
+			if (skb_queue_empty(&port->tx_aggr.aggr_list)) {
+				f_precopy_cur_buf = 0;
+				f_send_aggr_buf = 0;
+				f_send_cur_buf = 1;
+			} else {
+				f_send_aggr_buf = 1;
+			}
+		} else if (f_postcopy_cur_buf) {
+			f_send_cur_buf = 1;
+			f_postcopy_cur_buf = 0;
+		}
+	}
+
+	if (f_precopy_cur_buf) {
+		skb_queue_tail(&port->tx_aggr.aggr_list, skb);
+		port->tx_aggr.aggr_len += (skb->len + pad);
+		port->tx_aggr.aggr_num++;
+	}
+
+	if (f_send_aggr_buf) {
+		ret = mwifiex_usb_prepare_tx_aggr_skb(adapter, port, &skb_send);
+		if (!ret) {
+			context = &port->tx_data_list[port->tx_data_ix++];
+			ret = mwifiex_usb_construct_send_urb(adapter, port, ep,
+							     context, skb_send);
+			if (ret == -1)
+				mwifiex_write_data_complete(adapter, skb_send,
+							    0, -1);
+		}
+	}
+
+	if (f_send_cur_buf) {
+		if (f_send_aggr_buf) {
+			if (atomic_read(&port->tx_data_urb_pending) >=
+			    MWIFIEX_TX_DATA_URB) {
+				port->block_status = true;
+				adapter->data_sent =
+					mwifiex_usb_data_sent(adapter);
+				/* no available urb, postcopy packet*/
+				f_postcopy_cur_buf = 1;
+				goto postcopy_cur_buf;
+			}
+
+			if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
+				port->tx_data_ix = 0;
+		}
+
+		payload = skb->data;
+		*(u16 *)&payload[2] =
+			cpu_to_le16(MWIFIEX_TYPE_AGGR_DATA_V2 | 0x80);
+		*(u16 *)payload = cpu_to_le16(skb->len);
+		skb_send = skb;
+		context = &port->tx_data_list[port->tx_data_ix++];
+		return mwifiex_usb_construct_send_urb(adapter, port, ep,
+						      context, skb_send);
+	}
+
+postcopy_cur_buf:
+	if (f_postcopy_cur_buf) {
+		skb_queue_tail(&port->tx_aggr.aggr_list, skb);
+		port->tx_aggr.aggr_len += (skb->len + pad);
+		port->tx_aggr.aggr_num++;
+	}
+
+	return -EINPROGRESS;
+}
+
+/* This function write a command/data packet to card. */
+static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
+				    struct sk_buff *skb,
+				    struct mwifiex_tx_param *tx_param)
+{
+	struct usb_card_rec *card = adapter->card;
+	struct urb_context *context = NULL;
+	struct usb_tx_data_port *port = NULL;
+	int idx;
+
+	if (adapter->is_suspended) {
+		mwifiex_dbg(adapter, ERROR,
+			    "%s: not allowed while suspended\n", __func__);
+		return -1;
+	}
+
+	if (adapter->surprise_removed) {
+		mwifiex_dbg(adapter, ERROR, "%s: device removed\n", __func__);
+		return -1;
+	}
+
+	mwifiex_dbg(adapter, INFO, "%s: ep=%d\n", __func__, ep);
+
+	if (ep == card->tx_cmd_ep) {
+		context = &card->tx_cmd;
+	} else {
+		/* get the data port structure for endpoint */
+		for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
+			if (ep == card->port[idx].tx_data_ep) {
+				port = &card->port[idx];
+				if (atomic_read(&port->tx_data_urb_pending)
+				    >= MWIFIEX_TX_DATA_URB) {
+					port->block_status = true;
+					adapter->data_sent =
+						mwifiex_usb_data_sent(adapter);
+					return -EBUSY;
+				}
+				if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
+					port->tx_data_ix = 0;
+				break;
+			}
+		}
+
+		if (!port) {
+			mwifiex_dbg(adapter, ERROR, "Wrong usb tx data port\n");
+			return -1;
+		}
+
+		if (adapter->bus_aggr.enable)
+			return mwifiex_usb_aggr_tx_data(adapter, ep, skb,
+							tx_param, port);
+
+		context = &port->tx_data_list[port->tx_data_ix++];
+	}
+
+	return mwifiex_usb_construct_send_urb(adapter, port, ep, context, skb);
+}
+
 /* This function register usb device and initialize parameter. */
 static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
 {
@@ -989,10 +1217,31 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
 	return 0;
 }
 
+static void mwifiex_usb_cleanup_tx_aggr(struct mwifiex_adapter *adapter)
+{
+	struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+	struct usb_tx_data_port *port;
+	struct sk_buff *skb_tmp;
+	int idx;
+
+	if (adapter->bus_aggr.enable) {
+		for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
+			port = &card->port[idx];
+			while ((skb_tmp =
+				skb_dequeue(&port->tx_aggr.aggr_list)))
+				mwifiex_write_data_complete(adapter, skb_tmp,
+							    0, -1);
+		}
+	}
+}
+
 static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
 {
 	struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
 
+	if (adapter->bus_aggr.enable)
+		mwifiex_usb_cleanup_tx_aggr(adapter);
+
 	card->adapter = NULL;
 }
 
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.h b/drivers/net/wireless/marvell/mwifiex/usb.h
index e36bd63..b89b840 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.h
+++ b/drivers/net/wireless/marvell/mwifiex/usb.h
@@ -64,12 +64,21 @@ struct urb_context {
 	u8 ep;
 };
 
+struct usb_tx_aggr {
+	struct sk_buff_head aggr_list;
+	int aggr_len;
+	int aggr_num;
+};
+
 struct usb_tx_data_port {
 	u8 tx_data_ep;
 	u8 block_status;
 	atomic_t tx_data_urb_pending;
 	int tx_data_ix;
 	struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB];
+	/* usb tx aggregation*/
+	struct usb_tx_aggr tx_aggr;
+	struct sk_buff *skb_aggr[MWIFIEX_TX_DATA_URB];
 };
 
 struct usb_card_rec {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 4/6] mwifiex: usb: add timer to flush aggregation packets
  2017-05-19  9:06 [PATCH v3 1/6] mwifiex: use variable interface header length Xinming Hu
  2017-05-19  9:06 ` [PATCH v3 2/6] mwifiex: usb: kill urb before free its memory Xinming Hu
  2017-05-19  9:06 ` [PATCH v3 3/6] mwifiex: usb: transmit aggregation packets Xinming Hu
@ 2017-05-19  9:06 ` Xinming Hu
  2017-05-19  9:06 ` [PATCH v3 5/6] mwifiex: do not aggregate tcp ack in usb tx aggregation queue Xinming Hu
  2017-05-19  9:06 ` [PATCH v3 6/6] mwifiex: check next packet length for usb tx aggregation Xinming Hu
  4 siblings, 0 replies; 10+ messages in thread
From: Xinming Hu @ 2017-05-19  9:06 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, rajatja, Zhiyuan Yang,
	Cathy Luo, Xinming Hu, Ganapathi Bhat

From: Xinming Hu <huxm@marvell.com>

Aggregation will wait for next packet until limit aggr size/number reach.
Packet might be drop and also packet dequeue will be stop in some cases.
This patch add timer to flush packets in aggregation list to avoid long
time waiting.

Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
---
v3: same as v1,v2
---
 drivers/net/wireless/marvell/mwifiex/usb.c | 258 ++++++++++++++++++++---------
 drivers/net/wireless/marvell/mwifiex/usb.h |  14 ++
 2 files changed, 193 insertions(+), 79 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index e13f758d..f230017 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -662,76 +662,6 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
 	.soft_unbind = 1,
 };
 
-static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
-{
-	struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-	struct usb_tx_data_port *port;
-	int i, j;
-
-	card->tx_cmd.adapter = adapter;
-	card->tx_cmd.ep = card->tx_cmd_ep;
-
-	card->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!card->tx_cmd.urb)
-		return -ENOMEM;
-
-	for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
-		port = &card->port[i];
-		if (!port->tx_data_ep)
-			continue;
-		port->tx_data_ix = 0;
-		skb_queue_head_init(&port->tx_aggr.aggr_list);
-		if (port->tx_data_ep == MWIFIEX_USB_EP_DATA)
-			port->block_status = false;
-		else
-			port->block_status = true;
-		for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
-			port->tx_data_list[j].adapter = adapter;
-			port->tx_data_list[j].ep = port->tx_data_ep;
-			port->tx_data_list[j].urb =
-					usb_alloc_urb(0, GFP_KERNEL);
-			if (!port->tx_data_list[j].urb)
-				return -ENOMEM;
-		}
-	}
-
-	return 0;
-}
-
-static int mwifiex_usb_rx_init(struct mwifiex_adapter *adapter)
-{
-	struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-	int i;
-
-	card->rx_cmd.adapter = adapter;
-	card->rx_cmd.ep = card->rx_cmd_ep;
-
-	card->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!card->rx_cmd.urb)
-		return -ENOMEM;
-
-	card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE);
-	if (!card->rx_cmd.skb)
-		return -ENOMEM;
-
-	if (mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE))
-		return -1;
-
-	for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
-		card->rx_data_list[i].adapter = adapter;
-		card->rx_data_list[i].ep = card->rx_data_ep;
-
-		card->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!card->rx_data_list[i].urb)
-			return -1;
-		if (mwifiex_usb_submit_rx_urb(&card->rx_data_list[i],
-					      MWIFIEX_RX_DATA_BUF_SIZE))
-			return -1;
-	}
-
-	return 0;
-}
-
 static int mwifiex_write_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf,
 				   u32 *len, u8 ep, u32 timeout)
 {
@@ -918,6 +848,15 @@ static int mwifiex_usb_prepare_tx_aggr_skb(struct mwifiex_adapter *adapter,
 	struct mwifiex_txinfo *tx_info = NULL;
 	bool is_txinfo_set = false;
 
+	/* Packets in aggr_list will be send in either skb_aggr or
+	 * write complete, delete the tx_aggr timer
+	 */
+	if (port->tx_aggr.timer_cnxt.is_hold_timer_set) {
+		del_timer(&port->tx_aggr.timer_cnxt.hold_timer);
+		port->tx_aggr.timer_cnxt.is_hold_timer_set = false;
+		port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0;
+	}
+
 	skb_aggr = mwifiex_alloc_dma_align_buf(port->tx_aggr.aggr_len,
 					       GFP_ATOMIC);
 	if (!skb_aggr) {
@@ -999,6 +938,7 @@ static int mwifiex_usb_aggr_tx_data(struct mwifiex_adapter *adapter, u8 ep,
 	u8 f_send_cur_buf = 0;
 	u8 f_precopy_cur_buf = 0;
 	u8 f_postcopy_cur_buf = 0;
+	u32 timeout;
 	int ret;
 
 	/* padding to ensure each packet alginment */
@@ -1069,8 +1009,35 @@ static int mwifiex_usb_aggr_tx_data(struct mwifiex_adapter *adapter, u8 ep,
 		skb_queue_tail(&port->tx_aggr.aggr_list, skb);
 		port->tx_aggr.aggr_len += (skb->len + pad);
 		port->tx_aggr.aggr_num++;
+		if (f_send_aggr_buf)
+			goto send_aggr_buf;
+
+		/* packet will not been send immediately,
+		 * set a timer to make sure it will be sent under
+		 * strict time limit. Dynamically fit the timeout
+		 * value, according to packets number in aggr_list
+		 */
+		if (!port->tx_aggr.timer_cnxt.is_hold_timer_set) {
+			port->tx_aggr.timer_cnxt.hold_tmo_msecs =
+					MWIFIEX_USB_TX_AGGR_TMO_MIN;
+			timeout =
+				port->tx_aggr.timer_cnxt.hold_tmo_msecs;
+			mod_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+				  jiffies + msecs_to_jiffies(timeout));
+			port->tx_aggr.timer_cnxt.is_hold_timer_set = true;
+		} else {
+			if (port->tx_aggr.timer_cnxt.hold_tmo_msecs <
+			    MWIFIEX_USB_TX_AGGR_TMO_MAX) {
+				/* Dyanmic fit timeout */
+				timeout =
+				++port->tx_aggr.timer_cnxt.hold_tmo_msecs;
+				mod_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+					  jiffies + msecs_to_jiffies(timeout));
+			}
+		}
 	}
 
+send_aggr_buf:
 	if (f_send_aggr_buf) {
 		ret = mwifiex_usb_prepare_tx_aggr_skb(adapter, port, &skb_send);
 		if (!ret) {
@@ -1114,11 +1081,60 @@ static int mwifiex_usb_aggr_tx_data(struct mwifiex_adapter *adapter, u8 ep,
 		skb_queue_tail(&port->tx_aggr.aggr_list, skb);
 		port->tx_aggr.aggr_len += (skb->len + pad);
 		port->tx_aggr.aggr_num++;
+		/* New aggregation begin, start timer */
+		if (!port->tx_aggr.timer_cnxt.is_hold_timer_set) {
+			port->tx_aggr.timer_cnxt.hold_tmo_msecs =
+					MWIFIEX_USB_TX_AGGR_TMO_MIN;
+			timeout = port->tx_aggr.timer_cnxt.hold_tmo_msecs;
+			mod_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+				  jiffies + msecs_to_jiffies(timeout));
+			port->tx_aggr.timer_cnxt.is_hold_timer_set = true;
+		}
 	}
 
 	return -EINPROGRESS;
 }
 
+static void mwifiex_usb_tx_aggr_tmo(unsigned long context)
+{
+	struct urb_context *urb_cnxt = NULL;
+	struct sk_buff *skb_send = NULL;
+	struct tx_aggr_tmr_cnxt *timer_context =
+		(struct tx_aggr_tmr_cnxt *)context;
+	struct mwifiex_adapter *adapter = timer_context->adapter;
+	struct usb_tx_data_port *port = timer_context->port;
+	unsigned long flags;
+	int err = 0;
+
+	spin_lock_irqsave(&port->tx_aggr_lock, flags);
+	err = mwifiex_usb_prepare_tx_aggr_skb(adapter, port, &skb_send);
+	if (err) {
+		mwifiex_dbg(adapter, ERROR,
+			    "prepare tx aggr skb failed, err=%d\n", err);
+		return;
+	}
+
+	if (atomic_read(&port->tx_data_urb_pending) >=
+	    MWIFIEX_TX_DATA_URB) {
+		port->block_status = true;
+		adapter->data_sent =
+			mwifiex_usb_data_sent(adapter);
+		err = -1;
+		goto done;
+	}
+
+	if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
+		port->tx_data_ix = 0;
+
+	urb_cnxt = &port->tx_data_list[port->tx_data_ix++];
+	err = mwifiex_usb_construct_send_urb(adapter, port, port->tx_data_ep,
+					     urb_cnxt, skb_send);
+done:
+	if (err == -1)
+		mwifiex_write_data_complete(adapter, skb_send, 0, -1);
+	spin_unlock_irqrestore(&port->tx_aggr_lock, flags);
+}
+
 /* This function write a command/data packet to card. */
 static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
 				    struct sk_buff *skb,
@@ -1127,7 +1143,8 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
 	struct usb_card_rec *card = adapter->card;
 	struct urb_context *context = NULL;
 	struct usb_tx_data_port *port = NULL;
-	int idx;
+	unsigned long flags;
+	int idx, ret;
 
 	if (adapter->is_suspended) {
 		mwifiex_dbg(adapter, ERROR,
@@ -1167,9 +1184,13 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
 			return -1;
 		}
 
-		if (adapter->bus_aggr.enable)
-			return mwifiex_usb_aggr_tx_data(adapter, ep, skb,
+		if (adapter->bus_aggr.enable) {
+			spin_lock_irqsave(&port->tx_aggr_lock, flags);
+			ret =  mwifiex_usb_aggr_tx_data(adapter, ep, skb,
 							tx_param, port);
+			spin_unlock_irqrestore(&port->tx_aggr_lock, flags);
+			return ret;
+		}
 
 		context = &port->tx_data_list[port->tx_data_ix++];
 	}
@@ -1177,6 +1198,84 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
 	return mwifiex_usb_construct_send_urb(adapter, port, ep, context, skb);
 }
 
+static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
+{
+	struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+	struct usb_tx_data_port *port;
+	int i, j;
+
+	card->tx_cmd.adapter = adapter;
+	card->tx_cmd.ep = card->tx_cmd_ep;
+
+	card->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!card->tx_cmd.urb)
+		return -ENOMEM;
+
+	for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+		port = &card->port[i];
+		if (!port->tx_data_ep)
+			continue;
+		port->tx_data_ix = 0;
+		skb_queue_head_init(&port->tx_aggr.aggr_list);
+		if (port->tx_data_ep == MWIFIEX_USB_EP_DATA)
+			port->block_status = false;
+		else
+			port->block_status = true;
+		for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+			port->tx_data_list[j].adapter = adapter;
+			port->tx_data_list[j].ep = port->tx_data_ep;
+			port->tx_data_list[j].urb =
+					usb_alloc_urb(0, GFP_KERNEL);
+			if (!port->tx_data_list[j].urb)
+				return -ENOMEM;
+		}
+
+		port->tx_aggr.timer_cnxt.adapter = adapter;
+		port->tx_aggr.timer_cnxt.port = port;
+		port->tx_aggr.timer_cnxt.is_hold_timer_set = false;
+		port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0;
+		setup_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+			    mwifiex_usb_tx_aggr_tmo,
+			    (unsigned long)&port->tx_aggr.timer_cnxt);
+	}
+
+	return 0;
+}
+
+static int mwifiex_usb_rx_init(struct mwifiex_adapter *adapter)
+{
+	struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+	int i;
+
+	card->rx_cmd.adapter = adapter;
+	card->rx_cmd.ep = card->rx_cmd_ep;
+
+	card->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!card->rx_cmd.urb)
+		return -ENOMEM;
+
+	card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE);
+	if (!card->rx_cmd.skb)
+		return -ENOMEM;
+
+	if (mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE))
+		return -1;
+
+	for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
+		card->rx_data_list[i].adapter = adapter;
+		card->rx_data_list[i].ep = card->rx_data_ep;
+
+		card->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!card->rx_data_list[i].urb)
+			return -1;
+		if (mwifiex_usb_submit_rx_urb(&card->rx_data_list[i],
+					      MWIFIEX_RX_DATA_BUF_SIZE))
+			return -1;
+	}
+
+	return 0;
+}
+
 /* This function register usb device and initialize parameter. */
 static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
 {
@@ -1224,14 +1323,16 @@ static void mwifiex_usb_cleanup_tx_aggr(struct mwifiex_adapter *adapter)
 	struct sk_buff *skb_tmp;
 	int idx;
 
-	if (adapter->bus_aggr.enable) {
-		for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
-			port = &card->port[idx];
+	for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
+		port = &card->port[idx];
+		if (adapter->bus_aggr.enable)
 			while ((skb_tmp =
 				skb_dequeue(&port->tx_aggr.aggr_list)))
 				mwifiex_write_data_complete(adapter, skb_tmp,
 							    0, -1);
-		}
+		del_timer_sync(&port->tx_aggr.timer_cnxt.hold_timer);
+		port->tx_aggr.timer_cnxt.is_hold_timer_set = false;
+		port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0;
 	}
 }
 
@@ -1239,8 +1340,7 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
 {
 	struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
 
-	if (adapter->bus_aggr.enable)
-		mwifiex_usb_cleanup_tx_aggr(adapter);
+	mwifiex_usb_cleanup_tx_aggr(adapter);
 
 	card->adapter = NULL;
 }
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.h b/drivers/net/wireless/marvell/mwifiex/usb.h
index b89b840..37abd22 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.h
+++ b/drivers/net/wireless/marvell/mwifiex/usb.h
@@ -64,10 +64,22 @@ struct urb_context {
 	u8 ep;
 };
 
+#define MWIFIEX_USB_TX_AGGR_TMO_MIN	1
+#define MWIFIEX_USB_TX_AGGR_TMO_MAX	4
+
+struct tx_aggr_tmr_cnxt {
+	struct mwifiex_adapter *adapter;
+	struct usb_tx_data_port *port;
+	struct timer_list hold_timer;
+	bool is_hold_timer_set;
+	u32 hold_tmo_msecs;
+};
+
 struct usb_tx_aggr {
 	struct sk_buff_head aggr_list;
 	int aggr_len;
 	int aggr_num;
+	struct tx_aggr_tmr_cnxt timer_cnxt;
 };
 
 struct usb_tx_data_port {
@@ -79,6 +91,8 @@ struct usb_tx_data_port {
 	/* usb tx aggregation*/
 	struct usb_tx_aggr tx_aggr;
 	struct sk_buff *skb_aggr[MWIFIEX_TX_DATA_URB];
+	/* lock for protect tx aggregation data path*/
+	spinlock_t tx_aggr_lock;
 };
 
 struct usb_card_rec {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 5/6] mwifiex: do not aggregate tcp ack in usb tx aggregation queue
  2017-05-19  9:06 [PATCH v3 1/6] mwifiex: use variable interface header length Xinming Hu
                   ` (2 preceding siblings ...)
  2017-05-19  9:06 ` [PATCH v3 4/6] mwifiex: usb: add timer to flush " Xinming Hu
@ 2017-05-19  9:06 ` Xinming Hu
  2017-05-19 16:42   ` Brian Norris
  2017-05-19  9:06 ` [PATCH v3 6/6] mwifiex: check next packet length for usb tx aggregation Xinming Hu
  4 siblings, 1 reply; 10+ messages in thread
From: Xinming Hu @ 2017-05-19  9:06 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, rajatja, Zhiyuan Yang,
	Cathy Luo, Xinming Hu, Ganapathi Bhat

From: Xinming Hu <huxm@marvell.com>

Tcp ack should be send as soon to avoid throuput drop during receive tcp
traffic.

Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
---
v2: same as v1
v3: avoid to use magic tcp flag (Kalle)
---
 drivers/net/wireless/marvell/mwifiex/11n_aggr.c |  4 ++++
 drivers/net/wireless/marvell/mwifiex/decl.h     |  1 +
 drivers/net/wireless/marvell/mwifiex/main.c     | 26 +++++++++++++++++++++++++
 drivers/net/wireless/marvell/mwifiex/main.h     |  1 +
 drivers/net/wireless/marvell/mwifiex/usb.c      |  6 ++++--
 5 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
index e8ffb26..cbf3bc2 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
@@ -194,6 +194,10 @@
 
 	if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
 		tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
+
+	if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TCP_ACK)
+		tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TCP_ACK;
+
 	tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT;
 	skb_aggr->priority = skb_src->priority;
 	skb_aggr->tstamp = skb_src->tstamp;
diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h
index 188e4c3..0487420 100644
--- a/drivers/net/wireless/marvell/mwifiex/decl.h
+++ b/drivers/net/wireless/marvell/mwifiex/decl.h
@@ -89,6 +89,7 @@
 #define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS   BIT(3)
 #define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS  BIT(4)
 #define MWIFIEX_BUF_FLAG_AGGR_PKT          BIT(5)
+#define MWIFIEX_BUF_FLAG_TCP_ACK           BIT(6)
 
 #define MWIFIEX_BRIDGED_PKTS_THR_HIGH      1024
 #define MWIFIEX_BRIDGED_PKTS_THR_LOW        128
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 2c42191..b7d835c 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -851,6 +851,30 @@ struct sk_buff *
 	return skb;
 }
 
+static bool is_piggyback_tcp_ack(struct sk_buff *skb)
+{
+	struct ethhdr *ethh = NULL;
+	struct iphdr  *iph = NULL;
+	struct tcphdr *tcph = NULL;
+
+	ethh = (struct ethhdr *)skb->data;
+	if (ntohs(ethh->h_proto) != ETH_P_IP)
+		return false;
+
+	iph = (struct iphdr *)((u8 *)ethh + sizeof(struct ethhdr));
+	if (iph->protocol != IPPROTO_TCP)
+		return false;
+
+	tcph = (struct tcphdr *)((u8 *)iph + iph->ihl * 4);
+	/* Piggyback ack without payload*/
+	if (tcp_flag_word(tcph) == TCP_FLAG_ACK &&
+	    ntohs(iph->tot_len) <= (iph->ihl + tcph->doff) * 4) {
+		return true;
+	}
+
+	return false;
+}
+
 /*
  * CFG802.11 network device handler for data transmission.
  */
@@ -904,6 +928,8 @@ struct sk_buff *
 	tx_info->bss_num = priv->bss_num;
 	tx_info->bss_type = priv->bss_type;
 	tx_info->pkt_len = skb->len;
+	if (is_piggyback_tcp_ack(skb))
+		tx_info->flags |= MWIFIEX_BUF_FLAG_TCP_ACK;
 
 	multicast = is_multicast_ether_addr(skb->data);
 
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 1f7e6c3..b0010a9 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -49,6 +49,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/of_irq.h>
+#include <linux/tcp.h>
 
 #include "decl.h"
 #include "ioctl.h"
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index f230017..e9c3d43 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -934,6 +934,7 @@ static int mwifiex_usb_aggr_tx_data(struct mwifiex_adapter *adapter, u8 ep,
 	struct urb_context *context = NULL;
 	struct txpd *local_tx_pd =
 		(struct txpd *)((u8 *)skb->data + adapter->intf_hdr_len);
+	struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
 	u8 f_send_aggr_buf = 0;
 	u8 f_send_cur_buf = 0;
 	u8 f_precopy_cur_buf = 0;
@@ -989,8 +990,9 @@ static int mwifiex_usb_aggr_tx_data(struct mwifiex_adapter *adapter, u8 ep,
 		}
 	}
 
-	if (local_tx_pd->flags & MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET) {
-		/* Send NULL packet immediately*/
+	if (local_tx_pd->flags & MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET ||
+	    tx_info->flags & MWIFIEX_BUF_FLAG_TCP_ACK) {
+		/* Send NULL data/TCP ACK packet immediately*/
 		if (f_precopy_cur_buf) {
 			if (skb_queue_empty(&port->tx_aggr.aggr_list)) {
 				f_precopy_cur_buf = 0;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 6/6] mwifiex: check next packet length for usb tx aggregation
  2017-05-19  9:06 [PATCH v3 1/6] mwifiex: use variable interface header length Xinming Hu
                   ` (3 preceding siblings ...)
  2017-05-19  9:06 ` [PATCH v3 5/6] mwifiex: do not aggregate tcp ack in usb tx aggregation queue Xinming Hu
@ 2017-05-19  9:06 ` Xinming Hu
  2017-05-19 16:28   ` Brian Norris
  4 siblings, 1 reply; 10+ messages in thread
From: Xinming Hu @ 2017-05-19  9:06 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, rajatja, Zhiyuan Yang,
	Cathy Luo, Xinming Hu, Ganapathi Bhat

From: Xinming Hu <huxm@marvell.com>

The next packet length will be used by interface driver, to check if the
next packet still could be aggregated.

Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
---
v3: same as v1,v2
---
 drivers/net/wireless/marvell/mwifiex/11n_aggr.c | 8 ++++----
 drivers/net/wireless/marvell/mwifiex/txrx.c     | 4 ++--
 drivers/net/wireless/marvell/mwifiex/wmm.c      | 8 ++++----
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
index cbf3bc2..8041f2d 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
@@ -254,15 +254,15 @@
 		return 0;
 	}
 
-	if (adapter->iface_type == MWIFIEX_USB) {
-		ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
-						   skb_aggr, NULL);
-	} else {
 		if (skb_src)
 			tx_param.next_pkt_len =
 					skb_src->len + sizeof(struct txpd);
 		else
 			tx_param.next_pkt_len = 0;
+	if (adapter->iface_type == MWIFIEX_USB) {
+		ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
+						   skb_aggr, &tx_param);
+	} else {
 
 		ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
 						   skb_aggr, &tx_param);
diff --git a/drivers/net/wireless/marvell/mwifiex/txrx.c b/drivers/net/wireless/marvell/mwifiex/txrx.c
index 15e92af..d848933 100644
--- a/drivers/net/wireless/marvell/mwifiex/txrx.c
+++ b/drivers/net/wireless/marvell/mwifiex/txrx.c
@@ -117,7 +117,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
 		if (adapter->iface_type == MWIFIEX_USB) {
 			ret = adapter->if_ops.host_to_card(adapter,
 							   priv->usb_port,
-							   skb, NULL);
+							   skb, tx_param);
 		} else {
 			ret = adapter->if_ops.host_to_card(adapter,
 							   MWIFIEX_TYPE_DATA,
@@ -185,7 +185,7 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
 	if (adapter->iface_type == MWIFIEX_USB) {
 		ret = adapter->if_ops.host_to_card(adapter,
 						   priv->usb_port,
-						   skb, NULL);
+						   skb, tx_param);
 	} else {
 		ret = adapter->if_ops.host_to_card(adapter,
 						   MWIFIEX_TYPE_DATA,
diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c
index e4ff3b9..75cdd55 100644
--- a/drivers/net/wireless/marvell/mwifiex/wmm.c
+++ b/drivers/net/wireless/marvell/mwifiex/wmm.c
@@ -1363,13 +1363,13 @@ void mwifiex_rotate_priolists(struct mwifiex_private *priv,
 
 	spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
 
+	tx_param.next_pkt_len =
+		((skb_next) ? skb_next->len +
+		 sizeof(struct txpd) : 0);
 	if (adapter->iface_type == MWIFIEX_USB) {
 		ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
-						   skb, NULL);
+						   skb, &tx_param);
 	} else {
-		tx_param.next_pkt_len =
-			((skb_next) ? skb_next->len +
-			 sizeof(struct txpd) : 0);
 		ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
 						   skb, &tx_param);
 	}
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 6/6] mwifiex: check next packet length for usb tx aggregation
  2017-05-19  9:06 ` [PATCH v3 6/6] mwifiex: check next packet length for usb tx aggregation Xinming Hu
@ 2017-05-19 16:28   ` Brian Norris
  0 siblings, 0 replies; 10+ messages in thread
From: Brian Norris @ 2017-05-19 16:28 UTC (permalink / raw)
  To: Xinming Hu
  Cc: Linux Wireless, Kalle Valo, Dmitry Torokhov, rajatja,
	Zhiyuan Yang, Cathy Luo, Xinming Hu, Ganapathi Bhat

On Fri, May 19, 2017 at 09:06:45AM +0000, Xinming Hu wrote:
> From: Xinming Hu <huxm@marvell.com>
> 
> The next packet length will be used by interface driver, to check if the
> next packet still could be aggregated.
> 
> Signed-off-by: Xinming Hu <huxm@marvell.com>
> Signed-off-by: Cathy Luo <cluo@marvell.com>
> Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
> ---
> v3: same as v1,v2
> ---
>  drivers/net/wireless/marvell/mwifiex/11n_aggr.c | 8 ++++----
>  drivers/net/wireless/marvell/mwifiex/txrx.c     | 4 ++--
>  drivers/net/wireless/marvell/mwifiex/wmm.c      | 8 ++++----
>  3 files changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
> index cbf3bc2..8041f2d 100644
> --- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
> +++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
> @@ -254,15 +254,15 @@
>  		return 0;
>  	}
>  
> -	if (adapter->iface_type == MWIFIEX_USB) {
> -		ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
> -						   skb_aggr, NULL);
> -	} else {
>  		if (skb_src)
>  			tx_param.next_pkt_len =
>  					skb_src->len + sizeof(struct txpd);
>  		else
>  			tx_param.next_pkt_len = 0;

The above if/else is now improperly indented.

> +	if (adapter->iface_type == MWIFIEX_USB) {
> +		ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
> +						   skb_aggr, &tx_param);
> +	} else {
>  
>  		ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
>  						   skb_aggr, &tx_param);

[...]

Brian

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 5/6] mwifiex: do not aggregate tcp ack in usb tx aggregation queue
  2017-05-19  9:06 ` [PATCH v3 5/6] mwifiex: do not aggregate tcp ack in usb tx aggregation queue Xinming Hu
@ 2017-05-19 16:42   ` Brian Norris
  2017-05-23  7:08     ` [EXT] " Xinming Hu
  2017-05-23  7:10     ` Xinming Hu
  0 siblings, 2 replies; 10+ messages in thread
From: Brian Norris @ 2017-05-19 16:42 UTC (permalink / raw)
  To: Xinming Hu
  Cc: Linux Wireless, Kalle Valo, Dmitry Torokhov, rajatja,
	Zhiyuan Yang, Cathy Luo, Xinming Hu, Ganapathi Bhat

On Fri, May 19, 2017 at 09:06:44AM +0000, Xinming Hu wrote:
> From: Xinming Hu <huxm@marvell.com>
> 
> Tcp ack should be send as soon to avoid throuput drop during receive tcp
> traffic.
> 
> Signed-off-by: Xinming Hu <huxm@marvell.com>
> Signed-off-by: Cathy Luo <cluo@marvell.com>
> Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
> ---
> v2: same as v1
> v3: avoid to use magic tcp flag (Kalle)
> ---
>  drivers/net/wireless/marvell/mwifiex/11n_aggr.c |  4 ++++
>  drivers/net/wireless/marvell/mwifiex/decl.h     |  1 +
>  drivers/net/wireless/marvell/mwifiex/main.c     | 26 +++++++++++++++++++++++++
>  drivers/net/wireless/marvell/mwifiex/main.h     |  1 +
>  drivers/net/wireless/marvell/mwifiex/usb.c      |  6 ++++--
>  5 files changed, 36 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
> index e8ffb26..cbf3bc2 100644
> --- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
> +++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
> @@ -194,6 +194,10 @@
>  
>  	if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
>  		tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
> +
> +	if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TCP_ACK)
> +		tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TCP_ACK;
> +
>  	tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT;
>  	skb_aggr->priority = skb_src->priority;
>  	skb_aggr->tstamp = skb_src->tstamp;
> diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h
> index 188e4c3..0487420 100644
> --- a/drivers/net/wireless/marvell/mwifiex/decl.h
> +++ b/drivers/net/wireless/marvell/mwifiex/decl.h
> @@ -89,6 +89,7 @@
>  #define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS   BIT(3)
>  #define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS  BIT(4)
>  #define MWIFIEX_BUF_FLAG_AGGR_PKT          BIT(5)
> +#define MWIFIEX_BUF_FLAG_TCP_ACK           BIT(6)
>  
>  #define MWIFIEX_BRIDGED_PKTS_THR_HIGH      1024
>  #define MWIFIEX_BRIDGED_PKTS_THR_LOW        128
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
> index 2c42191..b7d835c 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.c
> +++ b/drivers/net/wireless/marvell/mwifiex/main.c
> @@ -851,6 +851,30 @@ struct sk_buff *
>  	return skb;
>  }
>  
> +static bool is_piggyback_tcp_ack(struct sk_buff *skb)
> +{
> +	struct ethhdr *ethh = NULL;
> +	struct iphdr  *iph = NULL;
> +	struct tcphdr *tcph = NULL;
> +
> +	ethh = (struct ethhdr *)skb->data;
> +	if (ntohs(ethh->h_proto) != ETH_P_IP)
> +		return false;

What about IPv6?

Also, what about all the protocols that you're *not* hacking this for?
Is the latency induced by aggregation really that poor?

I'm not really a networking expert here, but this whole patch smells bad
to me.

> +
> +	iph = (struct iphdr *)((u8 *)ethh + sizeof(struct ethhdr));
> +	if (iph->protocol != IPPROTO_TCP)
> +		return false;
> +
> +	tcph = (struct tcphdr *)((u8 *)iph + iph->ihl * 4);
> +	/* Piggyback ack without payload*/
> +	if (tcp_flag_word(tcph) == TCP_FLAG_ACK &&
> +	    ntohs(iph->tot_len) <= (iph->ihl + tcph->doff) * 4) {
> +		return true;
> +	}
> +
> +	return false;
> +}
> +
>  /*
>   * CFG802.11 network device handler for data transmission.
>   */
> @@ -904,6 +928,8 @@ struct sk_buff *
>  	tx_info->bss_num = priv->bss_num;
>  	tx_info->bss_type = priv->bss_type;
>  	tx_info->pkt_len = skb->len;
> +	if (is_piggyback_tcp_ack(skb))
> +		tx_info->flags |= MWIFIEX_BUF_FLAG_TCP_ACK;
>  
>  	multicast = is_multicast_ether_addr(skb->data);
>  
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
> index 1f7e6c3..b0010a9 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.h
> +++ b/drivers/net/wireless/marvell/mwifiex/main.h
> @@ -49,6 +49,7 @@
>  #include <linux/pm_runtime.h>
>  #include <linux/slab.h>
>  #include <linux/of_irq.h>
> +#include <linux/tcp.h>

I dislike polluting the (driver-global) main.h with #include's that only
are used in one file. Especially when you talk about seemingly
layer-violating TCP hacks. Can you move this to main.c instead?

Brian

>  
>  #include "decl.h"
>  #include "ioctl.h"
> diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
> index f230017..e9c3d43 100644
> --- a/drivers/net/wireless/marvell/mwifiex/usb.c
> +++ b/drivers/net/wireless/marvell/mwifiex/usb.c
> @@ -934,6 +934,7 @@ static int mwifiex_usb_aggr_tx_data(struct mwifiex_adapter *adapter, u8 ep,
>  	struct urb_context *context = NULL;
>  	struct txpd *local_tx_pd =
>  		(struct txpd *)((u8 *)skb->data + adapter->intf_hdr_len);
> +	struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
>  	u8 f_send_aggr_buf = 0;
>  	u8 f_send_cur_buf = 0;
>  	u8 f_precopy_cur_buf = 0;
> @@ -989,8 +990,9 @@ static int mwifiex_usb_aggr_tx_data(struct mwifiex_adapter *adapter, u8 ep,
>  		}
>  	}
>  
> -	if (local_tx_pd->flags & MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET) {
> -		/* Send NULL packet immediately*/
> +	if (local_tx_pd->flags & MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET ||
> +	    tx_info->flags & MWIFIEX_BUF_FLAG_TCP_ACK) {
> +		/* Send NULL data/TCP ACK packet immediately*/
>  		if (f_precopy_cur_buf) {
>  			if (skb_queue_empty(&port->tx_aggr.aggr_list)) {
>  				f_precopy_cur_buf = 0;
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [EXT] Re: [PATCH v3 5/6] mwifiex: do not aggregate tcp ack in usb tx aggregation queue
  2017-05-19 16:42   ` Brian Norris
@ 2017-05-23  7:08     ` Xinming Hu
  2017-05-23  7:10     ` Xinming Hu
  1 sibling, 0 replies; 10+ messages in thread
From: Xinming Hu @ 2017-05-23  7:08 UTC (permalink / raw)
  To: Brian Norris, Xinming Hu
  Cc: Linux Wireless, Kalle Valo, Dmitry Torokhov, rajatja,
	Zhiyuan Yang, Cathy Luo, Ganapathi Bhat

SGkgQnJhaW4sDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQnJpYW4g
Tm9ycmlzIFttYWlsdG86YnJpYW5ub3JyaXNAY2hyb21pdW0ub3JnXQ0KPiBTZW50OiAyMDE3xOo1
1MIyMMjVIDA6NDMNCj4gVG86IFhpbm1pbmcgSHUNCj4gQ2M6IExpbnV4IFdpcmVsZXNzOyBLYWxs
ZSBWYWxvOyBEbWl0cnkgVG9yb2tob3Y7IHJhamF0amFAZ29vZ2xlLmNvbTsgWmhpeXVhbg0KPiBZ
YW5nOyBDYXRoeSBMdW87IFhpbm1pbmcgSHU7IEdhbmFwYXRoaSBCaGF0DQo+IFN1YmplY3Q6IFtF
WFRdIFJlOiBbUEFUQ0ggdjMgNS82XSBtd2lmaWV4OiBkbyBub3QgYWdncmVnYXRlIHRjcCBhY2sg
aW4gdXNiIHR4DQo+IGFnZ3JlZ2F0aW9uIHF1ZXVlDQo+IA0KPiBFeHRlcm5hbCBFbWFpbA0KPiAN
Cj4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLQ0KPiBPbiBGcmksIE1heSAxOSwgMjAxNyBhdCAwOTowNjo0NEFNICsw
MDAwLCBYaW5taW5nIEh1IHdyb3RlOg0KPiA+IEZyb206IFhpbm1pbmcgSHUgPGh1eG1AbWFydmVs
bC5jb20+DQo+ID4NCj4gPiBUY3AgYWNrIHNob3VsZCBiZSBzZW5kIGFzIHNvb24gdG8gYXZvaWQg
dGhyb3VwdXQgZHJvcCBkdXJpbmcgcmVjZWl2ZQ0KPiA+IHRjcCB0cmFmZmljLg0KPiA+DQo+ID4g
U2lnbmVkLW9mZi1ieTogWGlubWluZyBIdSA8aHV4bUBtYXJ2ZWxsLmNvbT4NCj4gPiBTaWduZWQt
b2ZmLWJ5OiBDYXRoeSBMdW8gPGNsdW9AbWFydmVsbC5jb20+DQo+ID4gU2lnbmVkLW9mZi1ieTog
R2FuYXBhdGhpIEJoYXQgPGdiaGF0QG1hcnZlbGwuY29tPg0KPiA+IC0tLQ0KPiA+IHYyOiBzYW1l
IGFzIHYxDQo+ID4gdjM6IGF2b2lkIHRvIHVzZSBtYWdpYyB0Y3AgZmxhZyAoS2FsbGUpDQo+ID4g
LS0tDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC8xMW5fYWdnci5j
IHwgIDQgKysrKw0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvZGVj
bC5oICAgICB8ICAxICsNCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4
L21haW4uYyAgICAgfCAyNg0KPiArKysrKysrKysrKysrKysrKysrKysrKysrDQo+ID4gIGRyaXZl
cnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9tYWluLmggICAgIHwgIDEgKw0KPiA+ICBk
cml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvdXNiLmMgICAgICB8ICA2ICsrKyst
LQ0KPiA+ICA1IGZpbGVzIGNoYW5nZWQsIDM2IGluc2VydGlvbnMoKyksIDIgZGVsZXRpb25zKC0p
DQo+ID4NCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lm
aWV4LzExbl9hZ2dyLmMNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmll
eC8xMW5fYWdnci5jDQo+ID4gaW5kZXggZThmZmIyNi4uY2JmM2JjMiAxMDA2NDQNCj4gPiAtLS0g
YS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvMTFuX2FnZ3IuYw0KPiA+ICsr
KyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC8xMW5fYWdnci5jDQo+ID4g
QEAgLTE5NCw2ICsxOTQsMTAgQEANCj4gPg0KPiA+ICAJaWYgKHR4X2luZm9fc3JjLT5mbGFncyAm
IE1XSUZJRVhfQlVGX0ZMQUdfVERMU19QS1QpDQo+ID4gIAkJdHhfaW5mb19hZ2dyLT5mbGFncyB8
PSBNV0lGSUVYX0JVRl9GTEFHX1RETFNfUEtUOw0KPiA+ICsNCj4gPiArCWlmICh0eF9pbmZvX3Ny
Yy0+ZmxhZ3MgJiBNV0lGSUVYX0JVRl9GTEFHX1RDUF9BQ0spDQo+ID4gKwkJdHhfaW5mb19hZ2dy
LT5mbGFncyB8PSBNV0lGSUVYX0JVRl9GTEFHX1RDUF9BQ0s7DQo+ID4gKw0KPiA+ICAJdHhfaW5m
b19hZ2dyLT5mbGFncyB8PSBNV0lGSUVYX0JVRl9GTEFHX0FHR1JfUEtUOw0KPiA+ICAJc2tiX2Fn
Z3ItPnByaW9yaXR5ID0gc2tiX3NyYy0+cHJpb3JpdHk7DQo+ID4gIAlza2JfYWdnci0+dHN0YW1w
ID0gc2tiX3NyYy0+dHN0YW1wOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVz
cy9tYXJ2ZWxsL213aWZpZXgvZGVjbC5oDQo+ID4gYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2
ZWxsL213aWZpZXgvZGVjbC5oDQo+ID4gaW5kZXggMTg4ZTRjMy4uMDQ4NzQyMCAxMDA2NDQNCj4g
PiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvZGVjbC5oDQo+ID4g
KysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L2RlY2wuaA0KPiA+IEBA
IC04OSw2ICs4OSw3IEBADQo+ID4gICNkZWZpbmUgTVdJRklFWF9CVUZfRkxBR19FQVBPTF9UWF9T
VEFUVVMgICBCSVQoMykNCj4gPiAgI2RlZmluZSBNV0lGSUVYX0JVRl9GTEFHX0FDVElPTl9UWF9T
VEFUVVMgIEJJVCg0KQ0KPiA+ICAjZGVmaW5lIE1XSUZJRVhfQlVGX0ZMQUdfQUdHUl9QS1QgICAg
ICAgICAgQklUKDUpDQo+ID4gKyNkZWZpbmUgTVdJRklFWF9CVUZfRkxBR19UQ1BfQUNLICAgICAg
ICAgICBCSVQoNikNCj4gPg0KPiA+ICAjZGVmaW5lIE1XSUZJRVhfQlJJREdFRF9QS1RTX1RIUl9I
SUdIICAgICAgMTAyNA0KPiA+ICAjZGVmaW5lIE1XSUZJRVhfQlJJREdFRF9QS1RTX1RIUl9MT1cg
ICAgICAgIDEyOA0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxs
L213aWZpZXgvbWFpbi5jDQo+ID4gYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZp
ZXgvbWFpbi5jDQo+ID4gaW5kZXggMmM0MjE5MS4uYjdkODM1YyAxMDA2NDQNCj4gPiAtLS0gYS9k
cml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvbWFpbi5jDQo+ID4gKysrIGIvZHJp
dmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21haW4uYw0KPiA+IEBAIC04NTEsNiAr
ODUxLDMwIEBAIHN0cnVjdCBza19idWZmICoNCj4gPiAgCXJldHVybiBza2I7DQo+ID4gIH0NCj4g
Pg0KPiA+ICtzdGF0aWMgYm9vbCBpc19waWdneWJhY2tfdGNwX2FjayhzdHJ1Y3Qgc2tfYnVmZiAq
c2tiKSB7DQo+ID4gKwlzdHJ1Y3QgZXRoaGRyICpldGhoID0gTlVMTDsNCj4gPiArCXN0cnVjdCBp
cGhkciAgKmlwaCA9IE5VTEw7DQo+ID4gKwlzdHJ1Y3QgdGNwaGRyICp0Y3BoID0gTlVMTDsNCj4g
PiArDQo+ID4gKwlldGhoID0gKHN0cnVjdCBldGhoZHIgKilza2ItPmRhdGE7DQo+ID4gKwlpZiAo
bnRvaHMoZXRoaC0+aF9wcm90bykgIT0gRVRIX1BfSVApDQo+ID4gKwkJcmV0dXJuIGZhbHNlOw0K
PiANCj4gV2hhdCBhYm91dCBJUHY2Pw0KPiANCj4gQWxzbywgd2hhdCBhYm91dCBhbGwgdGhlIHBy
b3RvY29scyB0aGF0IHlvdSdyZSAqbm90KiBoYWNraW5nIHRoaXMgZm9yPw0KPiBJcyB0aGUgbGF0
ZW5jeSBpbmR1Y2VkIGJ5IGFnZ3JlZ2F0aW9uIHJlYWxseSB0aGF0IHBvb3I/DQo+IA0KPiBJJ20g
bm90IHJlYWxseSBhIG5ldHdvcmtpbmcgZXhwZXJ0IGhlcmUsIGJ1dCB0aGlzIHdob2xlIHBhdGNo
IHNtZWxscyBiYWQgdG8gbWUuDQo+IA0KDQpXZSBkaWRuJ3Qgb2JzZXJ2ZSB0aHJvdWdocHV0IGRy
b3AgZHVlIHRvIGFjayBibG9jayB5ZXQuLg0KSXQgd2FzIGNvbnNpZGVyZWQgdG8gYmUgYW4gb3B0
aW9uYWwgZW5oYW5jZS4NCkxldCdzIGRyb3AgaXQgaW4gdGhpcyBwYXRjaCBzZXJpYWxzLg0KDQpS
ZWdhcmRzLA0KU2ltb24NCj4gPiArDQo+ID4gKwlpcGggPSAoc3RydWN0IGlwaGRyICopKCh1OCAq
KWV0aGggKyBzaXplb2Yoc3RydWN0IGV0aGhkcikpOw0KPiA+ICsJaWYgKGlwaC0+cHJvdG9jb2wg
IT0gSVBQUk9UT19UQ1ApDQo+ID4gKwkJcmV0dXJuIGZhbHNlOw0KPiA+ICsNCj4gPiArCXRjcGgg
PSAoc3RydWN0IHRjcGhkciAqKSgodTggKilpcGggKyBpcGgtPmlobCAqIDQpOw0KPiA+ICsJLyog
UGlnZ3liYWNrIGFjayB3aXRob3V0IHBheWxvYWQqLw0KPiA+ICsJaWYgKHRjcF9mbGFnX3dvcmQo
dGNwaCkgPT0gVENQX0ZMQUdfQUNLICYmDQo+ID4gKwkgICAgbnRvaHMoaXBoLT50b3RfbGVuKSA8
PSAoaXBoLT5paGwgKyB0Y3BoLT5kb2ZmKSAqIDQpIHsNCj4gPiArCQlyZXR1cm4gdHJ1ZTsNCj4g
PiArCX0NCj4gPiArDQo+ID4gKwlyZXR1cm4gZmFsc2U7DQo+ID4gK30NCj4gPiArDQo+ID4gIC8q
DQo+ID4gICAqIENGRzgwMi4xMSBuZXR3b3JrIGRldmljZSBoYW5kbGVyIGZvciBkYXRhIHRyYW5z
bWlzc2lvbi4NCj4gPiAgICovDQo+ID4gQEAgLTkwNCw2ICs5MjgsOCBAQCBzdHJ1Y3Qgc2tfYnVm
ZiAqDQo+ID4gIAl0eF9pbmZvLT5ic3NfbnVtID0gcHJpdi0+YnNzX251bTsNCj4gPiAgCXR4X2lu
Zm8tPmJzc190eXBlID0gcHJpdi0+YnNzX3R5cGU7DQo+ID4gIAl0eF9pbmZvLT5wa3RfbGVuID0g
c2tiLT5sZW47DQo+ID4gKwlpZiAoaXNfcGlnZ3liYWNrX3RjcF9hY2soc2tiKSkNCj4gPiArCQl0
eF9pbmZvLT5mbGFncyB8PSBNV0lGSUVYX0JVRl9GTEFHX1RDUF9BQ0s7DQo+ID4NCj4gPiAgCW11
bHRpY2FzdCA9IGlzX211bHRpY2FzdF9ldGhlcl9hZGRyKHNrYi0+ZGF0YSk7DQo+ID4NCj4gPiBk
aWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21haW4uaA0K
PiA+IGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21haW4uaA0KPiA+IGlu
ZGV4IDFmN2U2YzMuLmIwMDEwYTkgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxl
c3MvbWFydmVsbC9td2lmaWV4L21haW4uaA0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNz
L21hcnZlbGwvbXdpZmlleC9tYWluLmgNCj4gPiBAQCAtNDksNiArNDksNyBAQA0KPiA+ICAjaW5j
bHVkZSA8bGludXgvcG1fcnVudGltZS5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvc2xhYi5oPg0K
PiA+ICAjaW5jbHVkZSA8bGludXgvb2ZfaXJxLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC90Y3Au
aD4NCj4gDQo+IEkgZGlzbGlrZSBwb2xsdXRpbmcgdGhlIChkcml2ZXItZ2xvYmFsKSBtYWluLmgg
d2l0aCAjaW5jbHVkZSdzIHRoYXQgb25seSBhcmUgdXNlZA0KPiBpbiBvbmUgZmlsZS4gRXNwZWNp
YWxseSB3aGVuIHlvdSB0YWxrIGFib3V0IHNlZW1pbmdseSBsYXllci12aW9sYXRpbmcgVENQIGhh
Y2tzLg0KPiBDYW4geW91IG1vdmUgdGhpcyB0byBtYWluLmMgaW5zdGVhZD8NCj4gDQo+IEJyaWFu
DQo+IA0KPiA+DQo+ID4gICNpbmNsdWRlICJkZWNsLmgiDQo+ID4gICNpbmNsdWRlICJpb2N0bC5o
Ig0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgv
dXNiLmMNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC91c2IuYw0K
PiA+IGluZGV4IGYyMzAwMTcuLmU5YzNkNDMgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQv
d2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3VzYi5jDQo+ID4gKysrIGIvZHJpdmVycy9uZXQvd2ly
ZWxlc3MvbWFydmVsbC9td2lmaWV4L3VzYi5jDQo+ID4gQEAgLTkzNCw2ICs5MzQsNyBAQCBzdGF0
aWMgaW50IG13aWZpZXhfdXNiX2FnZ3JfdHhfZGF0YShzdHJ1Y3QNCj4gbXdpZmlleF9hZGFwdGVy
ICphZGFwdGVyLCB1OCBlcCwNCj4gPiAgCXN0cnVjdCB1cmJfY29udGV4dCAqY29udGV4dCA9IE5V
TEw7DQo+ID4gIAlzdHJ1Y3QgdHhwZCAqbG9jYWxfdHhfcGQgPQ0KPiA+ICAJCShzdHJ1Y3QgdHhw
ZCAqKSgodTggKilza2ItPmRhdGEgKyBhZGFwdGVyLT5pbnRmX2hkcl9sZW4pOw0KPiA+ICsJc3Ry
dWN0IG13aWZpZXhfdHhpbmZvICp0eF9pbmZvID0gTVdJRklFWF9TS0JfVFhDQihza2IpOw0KPiA+
ICAJdTggZl9zZW5kX2FnZ3JfYnVmID0gMDsNCj4gPiAgCXU4IGZfc2VuZF9jdXJfYnVmID0gMDsN
Cj4gPiAgCXU4IGZfcHJlY29weV9jdXJfYnVmID0gMDsNCj4gPiBAQCAtOTg5LDggKzk5MCw5IEBA
IHN0YXRpYyBpbnQgbXdpZmlleF91c2JfYWdncl90eF9kYXRhKHN0cnVjdA0KPiBtd2lmaWV4X2Fk
YXB0ZXIgKmFkYXB0ZXIsIHU4IGVwLA0KPiA+ICAJCX0NCj4gPiAgCX0NCj4gPg0KPiA+IC0JaWYg
KGxvY2FsX3R4X3BkLT5mbGFncyAmIE1XSUZJRVhfVHhQRF9QT1dFUl9NR01UX05VTExfUEFDS0VU
KSB7DQo+ID4gLQkJLyogU2VuZCBOVUxMIHBhY2tldCBpbW1lZGlhdGVseSovDQo+ID4gKwlpZiAo
bG9jYWxfdHhfcGQtPmZsYWdzICYgTVdJRklFWF9UeFBEX1BPV0VSX01HTVRfTlVMTF9QQUNLRVQg
fHwNCj4gPiArCSAgICB0eF9pbmZvLT5mbGFncyAmIE1XSUZJRVhfQlVGX0ZMQUdfVENQX0FDSykg
ew0KPiA+ICsJCS8qIFNlbmQgTlVMTCBkYXRhL1RDUCBBQ0sgcGFja2V0IGltbWVkaWF0ZWx5Ki8N
Cj4gPiAgCQlpZiAoZl9wcmVjb3B5X2N1cl9idWYpIHsNCj4gPiAgCQkJaWYgKHNrYl9xdWV1ZV9l
bXB0eSgmcG9ydC0+dHhfYWdnci5hZ2dyX2xpc3QpKSB7DQo+ID4gIAkJCQlmX3ByZWNvcHlfY3Vy
X2J1ZiA9IDA7DQo+ID4gLS0NCj4gPiAxLjkuMQ0KPiA+DQo=

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Re: [PATCH v3 5/6] mwifiex: do not aggregate tcp ack in usb tx aggregation queue
  2017-05-19 16:42   ` Brian Norris
  2017-05-23  7:08     ` [EXT] " Xinming Hu
@ 2017-05-23  7:10     ` Xinming Hu
  1 sibling, 0 replies; 10+ messages in thread
From: Xinming Hu @ 2017-05-23  7:10 UTC (permalink / raw)
  To: Brian Norris, Xinming Hu
  Cc: Linux Wireless, Kalle Valo, Dmitry Torokhov, rajatja,
	Zhiyuan Yang, Cathy Luo, Ganapathi Bhat

SGkgQnJhaW4sDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQnJpYW4g
Tm9ycmlzIFttYWlsdG86YnJpYW5ub3JyaXNAY2hyb21pdW0ub3JnXQ0KPiBTZW50OiAyMDE3xOo1
1MIyMMjVIDA6NDMNCj4gVG86IFhpbm1pbmcgSHUNCj4gQ2M6IExpbnV4IFdpcmVsZXNzOyBLYWxs
ZSBWYWxvOyBEbWl0cnkgVG9yb2tob3Y7IHJhamF0amFAZ29vZ2xlLmNvbTsgWmhpeXVhbg0KPiBZ
YW5nOyBDYXRoeSBMdW87IFhpbm1pbmcgSHU7IEdhbmFwYXRoaSBCaGF0DQo+IFN1YmplY3Q6IFtF
WFRdIFJlOiBbUEFUQ0ggdjMgNS82XSBtd2lmaWV4OiBkbyBub3QgYWdncmVnYXRlIHRjcCBhY2sg
aW4gdXNiIHR4DQo+IGFnZ3JlZ2F0aW9uIHF1ZXVlDQo+IA0KPiBFeHRlcm5hbCBFbWFpbA0KPiAN
Cj4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLQ0KPiBPbiBGcmksIE1heSAxOSwgMjAxNyBhdCAwOTowNjo0NEFNICsw
MDAwLCBYaW5taW5nIEh1IHdyb3RlOg0KPiA+IEZyb206IFhpbm1pbmcgSHUgPGh1eG1AbWFydmVs
bC5jb20+DQo+ID4NCj4gPiBUY3AgYWNrIHNob3VsZCBiZSBzZW5kIGFzIHNvb24gdG8gYXZvaWQg
dGhyb3VwdXQgZHJvcCBkdXJpbmcgcmVjZWl2ZQ0KPiA+IHRjcCB0cmFmZmljLg0KPiA+DQo+ID4g
U2lnbmVkLW9mZi1ieTogWGlubWluZyBIdSA8aHV4bUBtYXJ2ZWxsLmNvbT4NCj4gPiBTaWduZWQt
b2ZmLWJ5OiBDYXRoeSBMdW8gPGNsdW9AbWFydmVsbC5jb20+DQo+ID4gU2lnbmVkLW9mZi1ieTog
R2FuYXBhdGhpIEJoYXQgPGdiaGF0QG1hcnZlbGwuY29tPg0KPiA+IC0tLQ0KPiA+IHYyOiBzYW1l
IGFzIHYxDQo+ID4gdjM6IGF2b2lkIHRvIHVzZSBtYWdpYyB0Y3AgZmxhZyAoS2FsbGUpDQo+ID4g
LS0tDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC8xMW5fYWdnci5j
IHwgIDQgKysrKw0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvZGVj
bC5oICAgICB8ICAxICsNCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4
L21haW4uYyAgICAgfCAyNg0KPiArKysrKysrKysrKysrKysrKysrKysrKysrDQo+ID4gIGRyaXZl
cnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9tYWluLmggICAgIHwgIDEgKw0KPiA+ICBk
cml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvdXNiLmMgICAgICB8ICA2ICsrKyst
LQ0KPiA+ICA1IGZpbGVzIGNoYW5nZWQsIDM2IGluc2VydGlvbnMoKyksIDIgZGVsZXRpb25zKC0p
DQo+ID4NCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lm
aWV4LzExbl9hZ2dyLmMNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmll
eC8xMW5fYWdnci5jDQo+ID4gaW5kZXggZThmZmIyNi4uY2JmM2JjMiAxMDA2NDQNCj4gPiAtLS0g
YS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvMTFuX2FnZ3IuYw0KPiA+ICsr
KyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC8xMW5fYWdnci5jDQo+ID4g
QEAgLTE5NCw2ICsxOTQsMTAgQEANCj4gPg0KPiA+ICAJaWYgKHR4X2luZm9fc3JjLT5mbGFncyAm
IE1XSUZJRVhfQlVGX0ZMQUdfVERMU19QS1QpDQo+ID4gIAkJdHhfaW5mb19hZ2dyLT5mbGFncyB8
PSBNV0lGSUVYX0JVRl9GTEFHX1RETFNfUEtUOw0KPiA+ICsNCj4gPiArCWlmICh0eF9pbmZvX3Ny
Yy0+ZmxhZ3MgJiBNV0lGSUVYX0JVRl9GTEFHX1RDUF9BQ0spDQo+ID4gKwkJdHhfaW5mb19hZ2dy
LT5mbGFncyB8PSBNV0lGSUVYX0JVRl9GTEFHX1RDUF9BQ0s7DQo+ID4gKw0KPiA+ICAJdHhfaW5m
b19hZ2dyLT5mbGFncyB8PSBNV0lGSUVYX0JVRl9GTEFHX0FHR1JfUEtUOw0KPiA+ICAJc2tiX2Fn
Z3ItPnByaW9yaXR5ID0gc2tiX3NyYy0+cHJpb3JpdHk7DQo+ID4gIAlza2JfYWdnci0+dHN0YW1w
ID0gc2tiX3NyYy0+dHN0YW1wOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVz
cy9tYXJ2ZWxsL213aWZpZXgvZGVjbC5oDQo+ID4gYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2
ZWxsL213aWZpZXgvZGVjbC5oDQo+ID4gaW5kZXggMTg4ZTRjMy4uMDQ4NzQyMCAxMDA2NDQNCj4g
PiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvZGVjbC5oDQo+ID4g
KysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L2RlY2wuaA0KPiA+IEBA
IC04OSw2ICs4OSw3IEBADQo+ID4gICNkZWZpbmUgTVdJRklFWF9CVUZfRkxBR19FQVBPTF9UWF9T
VEFUVVMgICBCSVQoMykNCj4gPiAgI2RlZmluZSBNV0lGSUVYX0JVRl9GTEFHX0FDVElPTl9UWF9T
VEFUVVMgIEJJVCg0KQ0KPiA+ICAjZGVmaW5lIE1XSUZJRVhfQlVGX0ZMQUdfQUdHUl9QS1QgICAg
ICAgICAgQklUKDUpDQo+ID4gKyNkZWZpbmUgTVdJRklFWF9CVUZfRkxBR19UQ1BfQUNLICAgICAg
ICAgICBCSVQoNikNCj4gPg0KPiA+ICAjZGVmaW5lIE1XSUZJRVhfQlJJREdFRF9QS1RTX1RIUl9I
SUdIICAgICAgMTAyNA0KPiA+ICAjZGVmaW5lIE1XSUZJRVhfQlJJREdFRF9QS1RTX1RIUl9MT1cg
ICAgICAgIDEyOA0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxs
L213aWZpZXgvbWFpbi5jDQo+ID4gYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZp
ZXgvbWFpbi5jDQo+ID4gaW5kZXggMmM0MjE5MS4uYjdkODM1YyAxMDA2NDQNCj4gPiAtLS0gYS9k
cml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvbWFpbi5jDQo+ID4gKysrIGIvZHJp
dmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21haW4uYw0KPiA+IEBAIC04NTEsNiAr
ODUxLDMwIEBAIHN0cnVjdCBza19idWZmICoNCj4gPiAgCXJldHVybiBza2I7DQo+ID4gIH0NCj4g
Pg0KPiA+ICtzdGF0aWMgYm9vbCBpc19waWdneWJhY2tfdGNwX2FjayhzdHJ1Y3Qgc2tfYnVmZiAq
c2tiKSB7DQo+ID4gKwlzdHJ1Y3QgZXRoaGRyICpldGhoID0gTlVMTDsNCj4gPiArCXN0cnVjdCBp
cGhkciAgKmlwaCA9IE5VTEw7DQo+ID4gKwlzdHJ1Y3QgdGNwaGRyICp0Y3BoID0gTlVMTDsNCj4g
PiArDQo+ID4gKwlldGhoID0gKHN0cnVjdCBldGhoZHIgKilza2ItPmRhdGE7DQo+ID4gKwlpZiAo
bnRvaHMoZXRoaC0+aF9wcm90bykgIT0gRVRIX1BfSVApDQo+ID4gKwkJcmV0dXJuIGZhbHNlOw0K
PiANCj4gV2hhdCBhYm91dCBJUHY2Pw0KPiANCj4gQWxzbywgd2hhdCBhYm91dCBhbGwgdGhlIHBy
b3RvY29scyB0aGF0IHlvdSdyZSAqbm90KiBoYWNraW5nIHRoaXMgZm9yPw0KPiBJcyB0aGUgbGF0
ZW5jeSBpbmR1Y2VkIGJ5IGFnZ3JlZ2F0aW9uIHJlYWxseSB0aGF0IHBvb3I/DQo+IA0KPiBJJ20g
bm90IHJlYWxseSBhIG5ldHdvcmtpbmcgZXhwZXJ0IGhlcmUsIGJ1dCB0aGlzIHdob2xlIHBhdGNo
IHNtZWxscyBiYWQgdG8gbWUuDQo+IA0KDQoNCldlIGRpZG4ndCBvYnNlcnZlIHRocm91Z2hwdXQg
ZHJvcCBkdWUgdG8gYWNrIGJsb2NrIHlldC4uDQpJdCB3YXMgY29uc2lkZXJlZCB0byBiZSBhbiBv
cHRpb25hbCBlbmhhbmNlLg0KTGV0J3MgZHJvcCBpdCBpbiB0aGlzIHBhdGNoIHNlcmlhbHMuDQoN
ClJlZ2FyZHMsDQpTaW1vbg0KPiA+ICsNCj4gPiArCWlwaCA9IChzdHJ1Y3QgaXBoZHIgKikoKHU4
ICopZXRoaCArIHNpemVvZihzdHJ1Y3QgZXRoaGRyKSk7DQo+ID4gKwlpZiAoaXBoLT5wcm90b2Nv
bCAhPSBJUFBST1RPX1RDUCkNCj4gPiArCQlyZXR1cm4gZmFsc2U7DQo+ID4gKw0KPiA+ICsJdGNw
aCA9IChzdHJ1Y3QgdGNwaGRyICopKCh1OCAqKWlwaCArIGlwaC0+aWhsICogNCk7DQo+ID4gKwkv
KiBQaWdneWJhY2sgYWNrIHdpdGhvdXQgcGF5bG9hZCovDQo+ID4gKwlpZiAodGNwX2ZsYWdfd29y
ZCh0Y3BoKSA9PSBUQ1BfRkxBR19BQ0sgJiYNCj4gPiArCSAgICBudG9ocyhpcGgtPnRvdF9sZW4p
IDw9IChpcGgtPmlobCArIHRjcGgtPmRvZmYpICogNCkgew0KPiA+ICsJCXJldHVybiB0cnVlOw0K
PiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiBmYWxzZTsNCj4gPiArfQ0KPiA+ICsNCj4gPiAg
LyoNCj4gPiAgICogQ0ZHODAyLjExIG5ldHdvcmsgZGV2aWNlIGhhbmRsZXIgZm9yIGRhdGEgdHJh
bnNtaXNzaW9uLg0KPiA+ICAgKi8NCj4gPiBAQCAtOTA0LDYgKzkyOCw4IEBAIHN0cnVjdCBza19i
dWZmICoNCj4gPiAgCXR4X2luZm8tPmJzc19udW0gPSBwcml2LT5ic3NfbnVtOw0KPiA+ICAJdHhf
aW5mby0+YnNzX3R5cGUgPSBwcml2LT5ic3NfdHlwZTsNCj4gPiAgCXR4X2luZm8tPnBrdF9sZW4g
PSBza2ItPmxlbjsNCj4gPiArCWlmIChpc19waWdneWJhY2tfdGNwX2Fjayhza2IpKQ0KPiA+ICsJ
CXR4X2luZm8tPmZsYWdzIHw9IE1XSUZJRVhfQlVGX0ZMQUdfVENQX0FDSzsNCj4gPg0KPiA+ICAJ
bXVsdGljYXN0ID0gaXNfbXVsdGljYXN0X2V0aGVyX2FkZHIoc2tiLT5kYXRhKTsNCj4gPg0KPiA+
IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvbWFpbi5o
DQo+ID4gYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvbWFpbi5oDQo+ID4g
aW5kZXggMWY3ZTZjMy4uYjAwMTBhOSAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJl
bGVzcy9tYXJ2ZWxsL213aWZpZXgvbWFpbi5oDQo+ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxl
c3MvbWFydmVsbC9td2lmaWV4L21haW4uaA0KPiA+IEBAIC00OSw2ICs0OSw3IEBADQo+ID4gICNp
bmNsdWRlIDxsaW51eC9wbV9ydW50aW1lLmg+DQo+ID4gICNpbmNsdWRlIDxsaW51eC9zbGFiLmg+
DQo+ID4gICNpbmNsdWRlIDxsaW51eC9vZl9pcnEuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3Rj
cC5oPg0KPiANCj4gSSBkaXNsaWtlIHBvbGx1dGluZyB0aGUgKGRyaXZlci1nbG9iYWwpIG1haW4u
aCB3aXRoICNpbmNsdWRlJ3MgdGhhdCBvbmx5IGFyZSB1c2VkDQo+IGluIG9uZSBmaWxlLiBFc3Bl
Y2lhbGx5IHdoZW4geW91IHRhbGsgYWJvdXQgc2VlbWluZ2x5IGxheWVyLXZpb2xhdGluZyBUQ1Ag
aGFja3MuDQo+IENhbiB5b3UgbW92ZSB0aGlzIHRvIG1haW4uYyBpbnN0ZWFkPw0KPiANCj4gQnJp
YW4NCj4gDQo+ID4NCj4gPiAgI2luY2x1ZGUgImRlY2wuaCINCj4gPiAgI2luY2x1ZGUgImlvY3Rs
LmgiDQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmll
eC91c2IuYw0KPiA+IGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3VzYi5j
DQo+ID4gaW5kZXggZjIzMDAxNy4uZTljM2Q0MyAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25l
dC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvdXNiLmMNCj4gPiArKysgYi9kcml2ZXJzL25ldC93
aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvdXNiLmMNCj4gPiBAQCAtOTM0LDYgKzkzNCw3IEBAIHN0
YXRpYyBpbnQgbXdpZmlleF91c2JfYWdncl90eF9kYXRhKHN0cnVjdA0KPiBtd2lmaWV4X2FkYXB0
ZXIgKmFkYXB0ZXIsIHU4IGVwLA0KPiA+ICAJc3RydWN0IHVyYl9jb250ZXh0ICpjb250ZXh0ID0g
TlVMTDsNCj4gPiAgCXN0cnVjdCB0eHBkICpsb2NhbF90eF9wZCA9DQo+ID4gIAkJKHN0cnVjdCB0
eHBkICopKCh1OCAqKXNrYi0+ZGF0YSArIGFkYXB0ZXItPmludGZfaGRyX2xlbik7DQo+ID4gKwlz
dHJ1Y3QgbXdpZmlleF90eGluZm8gKnR4X2luZm8gPSBNV0lGSUVYX1NLQl9UWENCKHNrYik7DQo+
ID4gIAl1OCBmX3NlbmRfYWdncl9idWYgPSAwOw0KPiA+ICAJdTggZl9zZW5kX2N1cl9idWYgPSAw
Ow0KPiA+ICAJdTggZl9wcmVjb3B5X2N1cl9idWYgPSAwOw0KPiA+IEBAIC05ODksOCArOTkwLDkg
QEAgc3RhdGljIGludCBtd2lmaWV4X3VzYl9hZ2dyX3R4X2RhdGEoc3RydWN0DQo+IG13aWZpZXhf
YWRhcHRlciAqYWRhcHRlciwgdTggZXAsDQo+ID4gIAkJfQ0KPiA+ICAJfQ0KPiA+DQo+ID4gLQlp
ZiAobG9jYWxfdHhfcGQtPmZsYWdzICYgTVdJRklFWF9UeFBEX1BPV0VSX01HTVRfTlVMTF9QQUNL
RVQpIHsNCj4gPiAtCQkvKiBTZW5kIE5VTEwgcGFja2V0IGltbWVkaWF0ZWx5Ki8NCj4gPiArCWlm
IChsb2NhbF90eF9wZC0+ZmxhZ3MgJiBNV0lGSUVYX1R4UERfUE9XRVJfTUdNVF9OVUxMX1BBQ0tF
VCB8fA0KPiA+ICsJICAgIHR4X2luZm8tPmZsYWdzICYgTVdJRklFWF9CVUZfRkxBR19UQ1BfQUNL
KSB7DQo+ID4gKwkJLyogU2VuZCBOVUxMIGRhdGEvVENQIEFDSyBwYWNrZXQgaW1tZWRpYXRlbHkq
Lw0KPiA+ICAJCWlmIChmX3ByZWNvcHlfY3VyX2J1Zikgew0KPiA+ICAJCQlpZiAoc2tiX3F1ZXVl
X2VtcHR5KCZwb3J0LT50eF9hZ2dyLmFnZ3JfbGlzdCkpIHsNCj4gPiAgCQkJCWZfcHJlY29weV9j
dXJfYnVmID0gMDsNCj4gPiAtLQ0KPiA+IDEuOS4xDQo+ID4NCg==

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-05-23  7:10 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-19  9:06 [PATCH v3 1/6] mwifiex: use variable interface header length Xinming Hu
2017-05-19  9:06 ` [PATCH v3 2/6] mwifiex: usb: kill urb before free its memory Xinming Hu
2017-05-19  9:06 ` [PATCH v3 3/6] mwifiex: usb: transmit aggregation packets Xinming Hu
2017-05-19  9:06 ` [PATCH v3 4/6] mwifiex: usb: add timer to flush " Xinming Hu
2017-05-19  9:06 ` [PATCH v3 5/6] mwifiex: do not aggregate tcp ack in usb tx aggregation queue Xinming Hu
2017-05-19 16:42   ` Brian Norris
2017-05-23  7:08     ` [EXT] " Xinming Hu
2017-05-23  7:10     ` Xinming Hu
2017-05-19  9:06 ` [PATCH v3 6/6] mwifiex: check next packet length for usb tx aggregation Xinming Hu
2017-05-19 16:28   ` Brian Norris

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).