Search Linux Wireless

Re: mwifiex_usb_submit_rx_urb: dev_alloc_skb failed when conected to 5GHz

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Amitkumar,

On Thu, Oct 23, 2014 at 2:40 PM, Amitkumar Karwar <akarwar@xxxxxxxxxxx> wrote:
> Hi Marek,
>
>>> I tried to capture logs but when enable DYNAMIC_DEBUG I cannot
>>> reproduce issue (running test > 30 minutes without allocation
>>> failure).
>
> Thanks for the testing. Yes. Sometimes timing issues won't get reproduced with debug messages enabled.
>
>>Any update on this? Should I provide some other logs?
>
> What's the size of Rx data packets? Is the Rx data AMSDU aggregated?(You can check if "if (rx_pkt_type == PKT_TYPE_AMSDU)" check is passed in mwifiex code) If so, disable AMSDU option in AP and try to reproduce the issue.
Size of Rx data packets are : pkt type == 2, size - 1574bytes + BAR
pkt type, size - 34bytes. AMSDU isn't enabled on AP (verified by
adding debug message in mwifiex_process_sta_rx_packet()).
>
> As you suspected earlier, we might have missed to free skbs allocated for Rx data which leads to SKB allocation failure. There is very less probability for this. But we can try below experiment.
>
> 1) I observed that debug variable "adapter->rx_pending" doesn;t get decremented when packet is submitted to kernel. Add below code change(valid only for AMSDU disabled case. Because multiple packets are submitted to kernel when AMSDU is enabled)
>
> ----------
> --- a/drivers/net/wireless/mwifiex/util.c
> +++ b/drivers/net/wireless/mwifiex/util.c
> @@ -218,6 +218,7 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
>
>         priv->stats.rx_bytes += skb->len;
>         priv->stats.rx_packets++;
> +       atomic_dec(&priv->adapter->rx_pending);
>         if (in_interrupt())
>                 netif_rx(skb);
> ----------
OK, patch applied.
>
> 2) Add BUG_ON when first time SKB allocation is failed and print "rx_pending". If it's a huge number, we have missed freeing allocated SKB.
[  167.624452] usb 1-1: mwifiex_usb_submit_rx_urb: dev_alloc_skb
failed, rx_pending:26893
[  167.632885] ------------[ cut here ]------------
[  167.637743] Kernel BUG at bf8a22ae [verbose debug info unavailable]
so number seems to be huge and we seems miss free allocated skb.

I did some hacks to code which shows how many packets are received
between 2 BAR packets + I print every 500ms rx_pending packets (when
packet is received) and
also when packet is send to kernel. I also update counter how many
packets after reordering are sent to kernel. Log:
[   71.973800] usb 1-1: rx_pending:11
[   72.077308] usb 1-1: rx_pending kernel:10
[   72.477546] usb 1-1: rx_pending:868
[   72.587877] usb 1-1: rx_pending kernel:1096
[   72.818041] usb 1-1: Received between 2 BAR:6275
[   72.823127] usb 1-1: Networking send size:6271
[   72.987375] usb 1-1: rx_pending:1940
[   73.097504] usb 1-1: rx_pending kernel:2159
[   73.431973] usb 1-1: Received between 2 BAR:1602
[   73.437106] usb 1-1: Networking send size:1608
[   73.497381] usb 1-1: rx_pending:2983
[   73.608315] usb 1-1: rx_pending kernel:3091
[   74.007379] usb 1-1: rx_pending:3767
[   74.117879] usb 1-1: rx_pending kernel:3998
[   74.517375] usb 1-1: rx_pending:4854
[   74.543168] usb 1-1: Received between 2 BAR:3152
[   74.548371] usb 1-1: Networking send size:3152
[   74.627509] usb 1-1: rx_pending kernel:5062
[   74.743362] usb 1-1: Received between 2 BAR:495
[   74.748483] usb 1-1: Networking send size:494
[   75.027523] usb 1-1: rx_pending:5872
[   75.137961] usb 1-1: rx_pending kernel:6106
[   75.537485] usb 1-1: rx_pending:6959
[   75.647934] usb 1-1: rx_pending kernel:7188
[   75.656273] usb 1-1: Received between 2 BAR:2383
[   75.661528] usb 1-1: Networking send size:2382
[   76.047441] usb 1-1: rx_pending:8004
[   76.157712] usb 1-1: rx_pending kernel:8240
[   76.557547] usb 1-1: rx_pending:9095
[   76.667991] usb 1-1: rx_pending kernel:9326
[   76.769662] usb 1-1: Received between 2 BAR:2918
[   76.775047] usb 1-1: Networking send size:2914
[   77.067491] usb 1-1: rx_pending:10155
[   77.177524] usb 1-1: rx_pending kernel:10383
[   77.577547] usb 1-1: rx_pending:11237
[   77.687859] usb 1-1: rx_pending kernel:11461
[   78.087401] usb 1-1: rx_pending:12304
[   78.197992] usb 1-1: rx_pending kernel:12539
[   78.597442] usb 1-1: rx_pending:13391
[   78.707786] usb 1-1: rx_pending kernel:13628
[   79.107487] usb 1-1: rx_pending:14469
[   79.217812] usb 1-1: rx_pending kernel:14704
[   79.617528] usb 1-1: rx_pending:15555
[   79.727734] usb 1-1: rx_pending kernel:15781
[   80.127486] usb 1-1: rx_pending:16624
[   80.237756] usb 1-1: rx_pending kernel:16855
[   80.637423] usb 1-1: rx_pending:17699
[   80.747868] usb 1-1: rx_pending kernel:17926
[   81.147446] usb 1-1: rx_pending:18769
[   81.257800] usb 1-1: rx_pending kernel:18995
[   81.657399] usb 1-1: rx_pending:19851
[   81.767785] usb 1-1: rx_pending kernel:20083
[   82.167341] usb 1-1: rx_pending:20938
[   82.278005] usb 1-1: rx_pending kernel:21174
[   82.677527] usb 1-1: rx_pending:22025
[   82.787508] usb 1-1: rx_pending kernel:22246
[   83.187390] usb 1-1: rx_pending:23103
[   83.297690] usb 1-1: rx_pending kernel:23326
[   83.697376] usb 1-1: rx_pending:24182
[   83.807711] usb 1-1: rx_pending kernel:24404
[   84.207487] usb 1-1: rx_pending:25236
[   84.317747] usb 1-1: rx_pending kernel:25466
[   84.717378] usb 1-1: rx_pending:26308
[   84.827806] usb 1-1: rx_pending kernel:26522
[   85.070931] usb 1-1: mwifiex_usb_submit_rx_urb: dev_alloc_skb
failed - rx_pending:27017
[   85.079788] usb 1-1: mwifiex_usb_submit_rx_urb: dev_alloc_skb
failed - rx_pending:27019
[   85.088424] usb 1-1: mwifiex_usb_submit_rx_urb: dev_alloc_skb
failed - rx_pending:27020
[   85.097029] usb 1-1: mwifiex_usb_submit_rx_urb: dev_alloc_skb
failed - rx_pending:27020
[   85.105845] usb 1-1: mwifiex_usb_submit_rx_urb: dev_alloc_skb
failed - rx_pending:27022
[   85.114468] usb 1-1: mwifiex_usb_submit_rx_urb: dev_alloc_skb
failed - rx_pending:27023
[   85.337391] usb 1-1: rx_pending kernel:22327
[   85.400153] usb 1-1: Received between 2 BAR:27875
[   85.405135] usb 1-1: Networking send size:27881
[   85.766194] usb 1-1: Received between 2 BAR:7781
[   85.771152] usb 1-1: Networking send size:7781
[   85.847374] usb 1-1: rx_pending kernel:11681
[   86.112809] usb 1-1: Received between 2 BAR:7263
[   86.117755] usb 1-1: Networking send size:7262
[   86.357378] usb 1-1: rx_pending kernel:827

According log it seems rx_pending is slowly increasing until
allocation fails. Code hacks are attached.

>
> 3) Also, get rx_pending info when Rx traffic works fine with 40M bandwidth option.
when -b40 is set then IMO 11n reordering isn't applied. I added some
debug code to mwifiex_11n_rx_reorder_pkt()
.. snip ..
tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
 if (!tbl) {
.. snip ..

is always true (!tbl) so rx_pending after session is 0.

>
> Btw, could you move to the firmware image (14.68.29.p38)
> shared recently?
Tested with  14.68.29.p38 FW version. Issue still reproducible.
>
> By any means(redirecting the log to serial console etc.), could you please capture and share kernel trace logs when system becomes unresponsive. It may give some clue and help us debug further.
As I wrote earlier with DYNAMIC_DEBUG I cannot reproduce issue. Maybe
when we drop some debug code (received packet over USB) issue can be
reproducible again, but it's just guess.
>
> Best Regards,
> Amit

BR,

marek

-- 
as simple and primitive as possible
-------------------------------------------------
Marek Belisko - OPEN-NANDRA
Freelance Developer

Ruska Nova Ves 219 | Presov, 08005 Slovak Republic
Tel: +421 915 052 184
skype: marekwhite
twitter: #opennandra
web: http://open-nandra.com
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 5e796f8..f6a8d0d 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -26,6 +26,7 @@
 #include "11n.h"
 #include "11n_rxreorder.h"
 
+static int pkt_send = 0;
 /*
  * This function dispatches all packets in the Rx reorder table until the
  * start window.
@@ -36,7 +37,7 @@
  */
 static void
 mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
-			 struct mwifiex_rx_reorder_tbl *tbl, int start_win)
+			 struct mwifiex_rx_reorder_tbl *tbl, int start_win, int *send_size)
 {
 	int pkt_to_send, i;
 	void *rx_tmp_ptr;
@@ -45,6 +46,7 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
 	pkt_to_send = (start_win > tbl->start_win) ?
 		      min((start_win - tbl->start_win), tbl->win_size) :
 		      tbl->win_size;
+//	pr_info("%s - pkt_to_send:%d\n", __func__, pkt_to_send);
 
 	for (i = 0; i < pkt_to_send; ++i) {
 		spin_lock_irqsave(&priv->rx_pkt_lock, flags);
@@ -57,8 +59,11 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
 		if (rx_tmp_ptr) {
 			if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
 				mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
-			else
+			else {
 				mwifiex_process_rx_packet(priv, rx_tmp_ptr);
+				if (send_size)
+					*send_size += 1;
+			}
 		}
 	}
 
@@ -86,7 +91,7 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
  */
 static void
 mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
-			      struct mwifiex_rx_reorder_tbl *tbl)
+			      struct mwifiex_rx_reorder_tbl *tbl, int *send_size)
 {
 	int i, j, xchg;
 	void *rx_tmp_ptr;
@@ -104,8 +109,10 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
 
 		if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
 			mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
-		else
+		else {
 			mwifiex_process_rx_packet(priv, rx_tmp_ptr);
+			*send_size += 1;
+		}
 	}
 
 	spin_lock_irqsave(&priv->rx_pkt_lock, flags);
@@ -140,7 +147,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
 		return;
 
 	mwifiex_11n_dispatch_pkt(priv, tbl, (tbl->start_win + tbl->win_size) &
-					    (MAX_TID_VALUE - 1));
+					    (MAX_TID_VALUE - 1), NULL);
 
 	del_timer(&tbl->timer_context.timer);
 
@@ -238,7 +245,7 @@ mwifiex_flush_data(unsigned long context)
 	dev_dbg(ctx->priv->adapter->dev, "info: flush data %d\n", start_win);
 	mwifiex_11n_dispatch_pkt(ctx->priv, ctx->ptr,
 				 (ctx->ptr->start_win + start_win + 1) &
-				 (MAX_TID_VALUE - 1));
+				 (MAX_TID_VALUE - 1), NULL);
 }
 
 /*
@@ -267,7 +274,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
 	 */
 	tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
 	if (tbl) {
-		mwifiex_11n_dispatch_pkt(priv, tbl, seq_num);
+		mwifiex_11n_dispatch_pkt(priv, tbl, seq_num, NULL);
 		return;
 	}
 	/* if !tbl then create one */
@@ -434,11 +441,15 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
 
 	tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
 	if (!tbl) {
+		pr_info("!tbl\n");
 		if (pkt_type != PKT_TYPE_BAR) {
 			if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
 				mwifiex_handle_uap_rx_forward(priv, payload);
 			else
 				mwifiex_process_rx_packet(priv, payload);
+		} else {
+			// missing free (maybe also rx_pending)
+			dev_kfree_skb_any(payload);
 		}
 		return 0;
 	}
@@ -485,7 +496,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
 			start_win = (end_win - win_size) + 1;
 		else
 			start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1;
-		mwifiex_11n_dispatch_pkt(priv, tbl, start_win);
+		mwifiex_11n_dispatch_pkt(priv, tbl, start_win, &pkt_send);
 	}
 
 	if (pkt_type != PKT_TYPE_BAR) {
@@ -498,13 +509,16 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
 			return -1;
 
 		tbl->rx_reorder_ptr[pkt_index] = payload;
+	} else if (pkt_type == PKT_TYPE_BAR) {
+		dev_info(priv->adapter->dev, "Networking send size:%d\n", pkt_send);
+		pkt_send = 0;
 	}
 
 	/*
 	 * Dispatch all packets sequentially from start_win until a
 	 * hole is found and adjust the start_win appropriately
 	 */
-	mwifiex_11n_scan_and_dispatch(priv, tbl);
+	mwifiex_11n_scan_and_dispatch(priv, tbl, &pkt_send);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index b5c1095..bc1c0d7 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -122,6 +122,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
 	struct rx_packet_hdr *rx_pkt_hdr;
 	u8 ta[ETH_ALEN];
 	u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
+	static int pkts_received = 0;
 
 	local_rx_pd = (struct rxpd *) (skb->data);
 	rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
@@ -146,6 +147,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
 	}
 
 	if (rx_pkt_type == PKT_TYPE_AMSDU) {
+		pr_info("AMSDU\n");
 		struct sk_buff_head list;
 		struct sk_buff *rx_skb;
 
@@ -168,6 +170,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
 		ret = mwifiex_process_mgmt_packet(priv, skb);
 		if (ret)
 			dev_err(adapter->dev, "Rx of mgmt packet failed");
+		atomic_dec(&priv->adapter->rx_pending);
 		dev_kfree_skb_any(skb);
 		return ret;
 	}
@@ -191,10 +194,19 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
 		       ETH_ALEN);
 	}
 
+	if (rx_pkt_type != PKT_TYPE_BAR && skb->len > 1500) {
+			pkts_received++;
+	}
+
+	if (rx_pkt_type == PKT_TYPE_BAR) {
+		dev_info(priv->adapter->dev, "Received between 2 BAR:%d\n", pkts_received);
+		pkts_received = 0;
+	}
 	/* Reorder and send to OS */
 	ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority,
 					 ta, (u8) rx_pkt_type, skb);
 
+
 	if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
 		if (adapter->if_ops.data_complete)
 			adapter->if_ops.data_complete(adapter, skb);
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index 7d9d10b..959daed 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -38,6 +38,7 @@ static struct usb_device_id mwifiex_usb_table[] = {
 
 MODULE_DEVICE_TABLE(usb, mwifiex_usb_table);
 
+unsigned long timeout = 0;
 /* Indicate if load FW in MFG (testing) mode */
 static int mfg_mode = 0;
 
@@ -178,8 +179,14 @@ static void mwifiex_usb_rx_complete(struct urb *urb)
 		atomic_inc(&adapter->rx_pending);
 		status = mwifiex_usb_recv(adapter, skb, context->ep);
 
+		if (time_after(jiffies, timeout)) {
+			dev_info(adapter->dev, "rx_pending:%d\n", atomic_read(&adapter->rx_pending));
+			timeout = jiffies + msecs_to_jiffies(500);
+		}
+
 		dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n",
 			recv_length, status);
+
 		if (status == -EINPROGRESS) {
 			queue_work(adapter->workqueue, &adapter->main_work);
 
@@ -259,7 +266,7 @@ static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size)
 		ctx->skb = dev_alloc_skb(size);
 		if (!ctx->skb) {
 			dev_err(adapter->dev,
-				"%s: dev_alloc_skb failed\n", __func__);
+				"%s: dev_alloc_skb failed - rx_pending:%d\n", __func__, atomic_read(&adapter->rx_pending));
 			return -ENOMEM;
 		}
 	}
@@ -344,6 +351,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
 	bcd_usb = le16_to_cpu(udev->descriptor.bcdUSB);
 	pr_debug("info: VID/PID = %X/%X, Boot2 version = %X\n",
 		 id_vendor, id_product, bcd_device);
+	timeout = jiffies + msecs_to_jiffies(1000);
 
 	/* PID_1 is used for firmware downloading only */
 	if (id_product == USB8797_PID_1)
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index 2155397..b18ee13 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -25,6 +25,7 @@
 #include "wmm.h"
 #include "11n.h"
 
+unsigned long timeout = 0;
 /*
  * Firmware initialization complete callback handler.
  *
@@ -195,6 +196,9 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
 	skb->protocol = eth_type_trans(skb, priv->netdev);
 	skb->ip_summed = CHECKSUM_NONE;
 
+	if (timeout == 0)
+		timeout = jiffies;
+
 	/* This is required only in case of 11n and USB as we alloc
 	 * a buffer of 4K only if its 11N (to be able to receive 4K
 	 * AMSDU packets). In case of SD we allocate buffers based
@@ -218,6 +222,12 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
 
 	priv->stats.rx_bytes += skb->len;
 	priv->stats.rx_packets++;
+	atomic_dec(&priv->adapter->rx_pending);
+	if (time_after(jiffies, timeout)) {
+		dev_info(priv->adapter->dev, "rx_pending kernel:%d\n", atomic_read(&priv->adapter->rx_pending));
+		timeout = jiffies + msecs_to_jiffies(500);
+	}
+
 	if (in_interrupt())
 		netif_rx(skb);
 	else

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux