All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Repair soft lockup with monitor mode of ath9k_htc card
@ 2015-01-29  4:09 ` zhengyuwei at 360.cn
  0 siblings, 0 replies; 10+ messages in thread
From: zhengyuwei @ 2015-01-29  4:09 UTC (permalink / raw)
  To: linux-kernel, ath9k-devel, linux-wireless, kvalo, ath9k-devel
  Cc: netdev, Yuwei Zheng

From: Yuwei Zheng <zhengyuwei@360.cn>

In the environment with heavy wifi traffic, set the ar9271 into monitor mode, will
trigger a deadloop panic. 

The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and ath9k_rx_tasklet excute
on the soft irq context. In other words, the ath9k_hif_usb_rx_cb have more chance to excute than
ath9k_rx_tasklet.  So in the worst condition,  the rx.rxbuf receive list is always full,
and the do {}while(true) loop will not be break. The kernel get a soft lockup panic.  
  
[59011.007210] BUG: soft lockup - CPU#0 stuck for 23s! 
[kworker/0:0:30609]
[59011.030560] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
[59013.804486] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
[59013.858522] Kernel panic - not syncing: softlockup: hung tasks

[59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
[59014.046834] bc20:                                                       de57b950 60000113
[59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 dc7bb440 df4bbcd0 00000000
[59014.072337] bc60: de57b950 60000113 df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff
[59014.085233] [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10)
[59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc])
[59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) from [<c0036d23>] (tasklet_action+0x3b/0x98)
[59014.134132] [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] (__do_softirq+0x99/0x16c)
[59014.147784] [<c0036709>] (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c)
[59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] (handle_IRQ+0x37/0x78)
[59014.173124] [<c000cfc3>] (handle_IRQ+0x37/0x78) from [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68)
[59014.187225] [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68) from [<c04c28db>](__irq_svc+0x3b/0x5c)

This bug can be see with low performance board, such as uniprocessor beagle bone board.


Signed-off-by: Yuwei Zheng <zhengyuwei@360.cn>

---
 drivers/net/wireless/ath/ath9k/hif_usb.c       | 53 ++++++++++++++++++++++----
 drivers/net/wireless/ath/ath9k/hif_usb.h       |  5 +++
 drivers/net/wireless/ath/ath9k/htc.h           | 13 +++++++
 drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 49 ++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 26 +++++++++++++
 5 files changed, 139 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 8e7153b..febea5e 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -658,7 +658,6 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
 	default:
 		goto resubmit;
 	}
-
 	if (likely(urb->actual_length != 0)) {
 		skb_put(skb, urb->actual_length);
 		ath9k_hif_usb_rx_stream(hif_dev, skb);
@@ -667,12 +666,18 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
 resubmit:
 	skb_reset_tail_pointer(skb);
 	skb_trim(skb, 0);
-
-	usb_anchor_urb(urb, &hif_dev->rx_submitted);
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret) {
-		usb_unanchor_urb(urb);
-		goto free;
+	if (atomic_read(&hif_dev->rx_urb_submit_delay) > 0) {
+		usb_anchor_urb(urb, &hif_dev->rx_delayed_submitted);
+		ret = tasklet_hrtimer_start(&hif_dev->rx_submit_timer,
+					    ktime_set(0, atomic_read(&hif_dev->rx_urb_submit_delay)*1000),
+					    HRTIMER_MODE_REL);
+	} else {
+		usb_anchor_urb(urb, &hif_dev->rx_submitted);
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+		if (ret) {
+			usb_unanchor_urb(urb);
+			goto free;
+		}
 	}
 
 	return;
@@ -818,9 +823,37 @@ err:
 	return -ENOMEM;
 }
 
+static enum hrtimer_restart rx_urb_submit_timer_handler(struct hrtimer *me)
+{
+	struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
+	struct  hif_device_usb *hif_dev = container_of(thr, struct hif_device_usb, rx_submit_timer);
+	struct urb *urb = NULL;
+	struct sk_buff *skb = NULL;
+	int ret;
+
+	while (true) {
+		urb = usb_get_from_anchor(&hif_dev->rx_delayed_submitted);
+		if (urb != NULL) {
+			skb = (struct sk_buff *)urb->context;
+			ret = usb_submit_urb(urb, GFP_ATOMIC);
+			if (ret != -EBUSY) {
+				usb_unanchor_urb(urb);
+				dev_kfree_skb_any(skb);
+				urb->context = NULL;
+			}
+		} else {
+			break;
+		}
+	}
+
+	return HRTIMER_NORESTART;
+}
+
 static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
 {
 	usb_kill_anchored_urbs(&hif_dev->rx_submitted);
+	usb_kill_anchored_urbs(&hif_dev->rx_delayed_submitted);
+	tasklet_hrtimer_cancel(&hif_dev->rx_submit_timer);
 }
 
 static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
@@ -830,6 +863,8 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
 	int i, ret;
 
 	init_usb_anchor(&hif_dev->rx_submitted);
+	init_usb_anchor(&hif_dev->rx_delayed_submitted);
+
 	spin_lock_init(&hif_dev->rx_lock);
 
 	for (i = 0; i < MAX_RX_URB_NUM; i++) {
@@ -871,6 +906,10 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
 		usb_free_urb(urb);
 	}
 
+	/* add for flow control*/
+	atomic_set(&hif_dev->rx_urb_submit_delay, 0);
+	tasklet_hrtimer_init(&hif_dev->rx_submit_timer, rx_urb_submit_timer_handler, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+
 	return 0;
 
 err_submit:
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index 51496e7..56d6be8 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -98,9 +98,14 @@ struct hif_device_usb {
 	struct hif_usb_tx tx;
 	struct usb_anchor regout_submitted;
 	struct usb_anchor rx_submitted;
+	struct usb_anchor rx_delayed_submitted; /* delayed submit anchor */
 	struct usb_anchor reg_in_submitted;
 	struct usb_anchor mgmt_submitted;
 	struct sk_buff *remain_skb;
+
+	struct tasklet_hrtimer  rx_submit_timer;/* delayed submit hrtimer */
+	atomic_t  rx_urb_submit_delay; /*us*/
+
 	const char *fw_name;
 	int rx_remain_len;
 	int rx_pkt_len;
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 9dde265..453d0a8 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -331,6 +331,10 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
 
 #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
 
+#define TASKLETRX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c++)
+#define TASKLETRX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c += a)
+#define TASKLETRX_STAT_SET(c, a) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c = a)
+
 void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
 			   struct ath_rx_status *rs);
 
@@ -352,11 +356,20 @@ struct ath_skbrx_stats {
 	u32 skb_dropped;
 };
 
+struct ath_taskletrx_stats {
+	u32 taskletrx_looptimes;
+	u32 taskletrx_highwater;
+	u32 taskletrx_lowwater;
+	u32 taskletrx_watermark_triggered;
+	u32 taskletrx_urb_submit_delay;
+};
+
 struct ath9k_debug {
 	struct dentry *debugfs_phy;
 	struct ath_tx_stats tx_stats;
 	struct ath_rx_stats rx_stats;
 	struct ath_skbrx_stats skbrx_stats;
+	struct ath_taskletrx_stats taskletrx_stats;
 };
 
 void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index 8cef1ed..7c8322e 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -286,6 +286,51 @@ static const struct file_operations fops_skb_rx = {
 	.llseek = default_llseek,
 };
 
+static ssize_t read_file_tasklet_rx(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	struct ath9k_htc_priv *priv = file->private_data;
+	char *buf;
+	unsigned int len = 0, size = 1500;
+	ssize_t retval = 0;
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "Loop times",
+			priv->debug.taskletrx_stats.taskletrx_looptimes);
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "High watermark",
+			priv->debug.taskletrx_stats.taskletrx_highwater);
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "Low watermark",
+			priv->debug.taskletrx_stats.taskletrx_lowwater);
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "WM triggered",
+			priv->debug.taskletrx_stats.taskletrx_watermark_triggered);
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "URB delay",
+			priv->debug.taskletrx_stats.taskletrx_urb_submit_delay);
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+static const struct file_operations fops_tasklet_rx = {
+	.read = read_file_tasklet_rx,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 static ssize_t read_file_slot(struct file *file, char __user *user_buf,
 			      size_t count, loff_t *ppos)
 {
@@ -518,7 +563,11 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
 	debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
 			    priv, &fops_skb_rx);
 
+	debugfs_create_file("tasklet_rx", S_IRUSR, priv->debug.debugfs_phy,
+			    priv, &fops_tasklet_rx);
+
 	ath9k_cmn_debug_recv(priv->debug.debugfs_phy, &priv->debug.rx_stats);
+
 	ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, &priv->debug.rx_stats);
 
 	debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index a0f58e2..f5e6217 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -1061,7 +1061,28 @@ void ath9k_rx_tasklet(unsigned long data)
 	unsigned long flags;
 	struct ieee80211_hdr *hdr;
 
+	/* add for adaptive flow control*/
+	int looptimes = 0;
+	int highwatermark = ATH9K_HTC_RXBUF*3/4;
+	int lowwatermark = ATH9K_HTC_RXBUF/4;
+	unsigned int delay = 0;
+
+	struct htc_target *htc = priv->htc;
+	struct hif_device_usb *hif_dev = htc->hif_dev;
+
+	TASKLETRX_STAT_SET(taskletrx_highwater, highwatermark);
+	TASKLETRX_STAT_SET(taskletrx_lowwater, lowwatermark);
+
 	do {
+		looptimes++;
+		TASKLETRX_STAT_SET(taskletrx_looptimes, looptimes);
+		if (looptimes > highwatermark) {
+			delay = looptimes*10;
+			atomic_set(&hif_dev->rx_urb_submit_delay, delay);
+			TASKLETRX_STAT_INC(taskletrx_watermark_triggered);
+			TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, delay);
+		}
+
 		spin_lock_irqsave(&priv->rx.rxbuflock, flags);
 		list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
 			if (tmp_buf->in_process) {
@@ -1072,6 +1093,11 @@ void ath9k_rx_tasklet(unsigned long data)
 
 		if (rxbuf == NULL) {
 			spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
+			if (looptimes < lowwatermark) {
+				atomic_set(&hif_dev->rx_urb_submit_delay, 0);
+				TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, 0);
+			}
+
 			break;
 		}
 
-- 
1.9.1


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

* [ath9k-devel] [PATCH] Repair soft lockup with monitor mode of ath9k_htc card
@ 2015-01-29  4:09 ` zhengyuwei at 360.cn
  0 siblings, 0 replies; 10+ messages in thread
From: zhengyuwei at 360.cn @ 2015-01-29  4:09 UTC (permalink / raw)
  To: ath9k-devel

From: Yuwei Zheng <zhengyuwei@360.cn>

In the environment with heavy wifi traffic, set the ar9271 into monitor mode, will
trigger a deadloop panic. 

The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and ath9k_rx_tasklet excute
on the soft irq context. In other words, the ath9k_hif_usb_rx_cb have more chance to excute than
ath9k_rx_tasklet.  So in the worst condition,  the rx.rxbuf receive list is always full,
and the do {}while(true) loop will not be break. The kernel get a soft lockup panic.  
  
[59011.007210] BUG: soft lockup - CPU#0 stuck for 23s! 
[kworker/0:0:30609]
[59011.030560] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
[59013.804486] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
[59013.858522] Kernel panic - not syncing: softlockup: hung tasks

[59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
[59014.046834] bc20:                                                       de57b950 60000113
[59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 dc7bb440 df4bbcd0 00000000
[59014.072337] bc60: de57b950 60000113 df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff
[59014.085233] [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10)
[59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc])
[59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) from [<c0036d23>] (tasklet_action+0x3b/0x98)
[59014.134132] [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] (__do_softirq+0x99/0x16c)
[59014.147784] [<c0036709>] (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c)
[59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] (handle_IRQ+0x37/0x78)
[59014.173124] [<c000cfc3>] (handle_IRQ+0x37/0x78) from [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68)
[59014.187225] [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68) from [<c04c28db>](__irq_svc+0x3b/0x5c)

This bug can be see with low performance board, such as uniprocessor beagle bone board.


Signed-off-by: Yuwei Zheng <zhengyuwei@360.cn>

---
 drivers/net/wireless/ath/ath9k/hif_usb.c       | 53 ++++++++++++++++++++++----
 drivers/net/wireless/ath/ath9k/hif_usb.h       |  5 +++
 drivers/net/wireless/ath/ath9k/htc.h           | 13 +++++++
 drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 49 ++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 26 +++++++++++++
 5 files changed, 139 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 8e7153b..febea5e 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -658,7 +658,6 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
 	default:
 		goto resubmit;
 	}
-
 	if (likely(urb->actual_length != 0)) {
 		skb_put(skb, urb->actual_length);
 		ath9k_hif_usb_rx_stream(hif_dev, skb);
@@ -667,12 +666,18 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
 resubmit:
 	skb_reset_tail_pointer(skb);
 	skb_trim(skb, 0);
-
-	usb_anchor_urb(urb, &hif_dev->rx_submitted);
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret) {
-		usb_unanchor_urb(urb);
-		goto free;
+	if (atomic_read(&hif_dev->rx_urb_submit_delay) > 0) {
+		usb_anchor_urb(urb, &hif_dev->rx_delayed_submitted);
+		ret = tasklet_hrtimer_start(&hif_dev->rx_submit_timer,
+					    ktime_set(0, atomic_read(&hif_dev->rx_urb_submit_delay)*1000),
+					    HRTIMER_MODE_REL);
+	} else {
+		usb_anchor_urb(urb, &hif_dev->rx_submitted);
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+		if (ret) {
+			usb_unanchor_urb(urb);
+			goto free;
+		}
 	}
 
 	return;
@@ -818,9 +823,37 @@ err:
 	return -ENOMEM;
 }
 
+static enum hrtimer_restart rx_urb_submit_timer_handler(struct hrtimer *me)
+{
+	struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
+	struct  hif_device_usb *hif_dev = container_of(thr, struct hif_device_usb, rx_submit_timer);
+	struct urb *urb = NULL;
+	struct sk_buff *skb = NULL;
+	int ret;
+
+	while (true) {
+		urb = usb_get_from_anchor(&hif_dev->rx_delayed_submitted);
+		if (urb != NULL) {
+			skb = (struct sk_buff *)urb->context;
+			ret = usb_submit_urb(urb, GFP_ATOMIC);
+			if (ret != -EBUSY) {
+				usb_unanchor_urb(urb);
+				dev_kfree_skb_any(skb);
+				urb->context = NULL;
+			}
+		} else {
+			break;
+		}
+	}
+
+	return HRTIMER_NORESTART;
+}
+
 static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
 {
 	usb_kill_anchored_urbs(&hif_dev->rx_submitted);
+	usb_kill_anchored_urbs(&hif_dev->rx_delayed_submitted);
+	tasklet_hrtimer_cancel(&hif_dev->rx_submit_timer);
 }
 
 static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
@@ -830,6 +863,8 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
 	int i, ret;
 
 	init_usb_anchor(&hif_dev->rx_submitted);
+	init_usb_anchor(&hif_dev->rx_delayed_submitted);
+
 	spin_lock_init(&hif_dev->rx_lock);
 
 	for (i = 0; i < MAX_RX_URB_NUM; i++) {
@@ -871,6 +906,10 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
 		usb_free_urb(urb);
 	}
 
+	/* add for flow control*/
+	atomic_set(&hif_dev->rx_urb_submit_delay, 0);
+	tasklet_hrtimer_init(&hif_dev->rx_submit_timer, rx_urb_submit_timer_handler, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+
 	return 0;
 
 err_submit:
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index 51496e7..56d6be8 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -98,9 +98,14 @@ struct hif_device_usb {
 	struct hif_usb_tx tx;
 	struct usb_anchor regout_submitted;
 	struct usb_anchor rx_submitted;
+	struct usb_anchor rx_delayed_submitted; /* delayed submit anchor */
 	struct usb_anchor reg_in_submitted;
 	struct usb_anchor mgmt_submitted;
 	struct sk_buff *remain_skb;
+
+	struct tasklet_hrtimer  rx_submit_timer;/* delayed submit hrtimer */
+	atomic_t  rx_urb_submit_delay; /*us*/
+
 	const char *fw_name;
 	int rx_remain_len;
 	int rx_pkt_len;
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 9dde265..453d0a8 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -331,6 +331,10 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
 
 #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
 
+#define TASKLETRX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c++)
+#define TASKLETRX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c += a)
+#define TASKLETRX_STAT_SET(c, a) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c = a)
+
 void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
 			   struct ath_rx_status *rs);
 
@@ -352,11 +356,20 @@ struct ath_skbrx_stats {
 	u32 skb_dropped;
 };
 
+struct ath_taskletrx_stats {
+	u32 taskletrx_looptimes;
+	u32 taskletrx_highwater;
+	u32 taskletrx_lowwater;
+	u32 taskletrx_watermark_triggered;
+	u32 taskletrx_urb_submit_delay;
+};
+
 struct ath9k_debug {
 	struct dentry *debugfs_phy;
 	struct ath_tx_stats tx_stats;
 	struct ath_rx_stats rx_stats;
 	struct ath_skbrx_stats skbrx_stats;
+	struct ath_taskletrx_stats taskletrx_stats;
 };
 
 void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index 8cef1ed..7c8322e 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -286,6 +286,51 @@ static const struct file_operations fops_skb_rx = {
 	.llseek = default_llseek,
 };
 
+static ssize_t read_file_tasklet_rx(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	struct ath9k_htc_priv *priv = file->private_data;
+	char *buf;
+	unsigned int len = 0, size = 1500;
+	ssize_t retval = 0;
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "Loop times",
+			priv->debug.taskletrx_stats.taskletrx_looptimes);
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "High watermark",
+			priv->debug.taskletrx_stats.taskletrx_highwater);
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "Low watermark",
+			priv->debug.taskletrx_stats.taskletrx_lowwater);
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "WM triggered",
+			priv->debug.taskletrx_stats.taskletrx_watermark_triggered);
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "URB delay",
+			priv->debug.taskletrx_stats.taskletrx_urb_submit_delay);
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+static const struct file_operations fops_tasklet_rx = {
+	.read = read_file_tasklet_rx,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 static ssize_t read_file_slot(struct file *file, char __user *user_buf,
 			      size_t count, loff_t *ppos)
 {
@@ -518,7 +563,11 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
 	debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
 			    priv, &fops_skb_rx);
 
+	debugfs_create_file("tasklet_rx", S_IRUSR, priv->debug.debugfs_phy,
+			    priv, &fops_tasklet_rx);
+
 	ath9k_cmn_debug_recv(priv->debug.debugfs_phy, &priv->debug.rx_stats);
+
 	ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, &priv->debug.rx_stats);
 
 	debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index a0f58e2..f5e6217 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -1061,7 +1061,28 @@ void ath9k_rx_tasklet(unsigned long data)
 	unsigned long flags;
 	struct ieee80211_hdr *hdr;
 
+	/* add for adaptive flow control*/
+	int looptimes = 0;
+	int highwatermark = ATH9K_HTC_RXBUF*3/4;
+	int lowwatermark = ATH9K_HTC_RXBUF/4;
+	unsigned int delay = 0;
+
+	struct htc_target *htc = priv->htc;
+	struct hif_device_usb *hif_dev = htc->hif_dev;
+
+	TASKLETRX_STAT_SET(taskletrx_highwater, highwatermark);
+	TASKLETRX_STAT_SET(taskletrx_lowwater, lowwatermark);
+
 	do {
+		looptimes++;
+		TASKLETRX_STAT_SET(taskletrx_looptimes, looptimes);
+		if (looptimes > highwatermark) {
+			delay = looptimes*10;
+			atomic_set(&hif_dev->rx_urb_submit_delay, delay);
+			TASKLETRX_STAT_INC(taskletrx_watermark_triggered);
+			TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, delay);
+		}
+
 		spin_lock_irqsave(&priv->rx.rxbuflock, flags);
 		list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
 			if (tmp_buf->in_process) {
@@ -1072,6 +1093,11 @@ void ath9k_rx_tasklet(unsigned long data)
 
 		if (rxbuf == NULL) {
 			spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
+			if (looptimes < lowwatermark) {
+				atomic_set(&hif_dev->rx_urb_submit_delay, 0);
+				TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, 0);
+			}
+
 			break;
 		}
 
-- 
1.9.1

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

* Re: [ath9k-devel] [PATCH] Repair soft lockup with monitor mode of ath9k_htc card
  2015-01-29  4:09 ` [ath9k-devel] " zhengyuwei at 360.cn
@ 2015-01-29 10:52   ` Oleksij Rempel
  -1 siblings, 0 replies; 10+ messages in thread
From: Oleksij Rempel @ 2015-01-29 10:52 UTC (permalink / raw)
  To: zhengyuwei, linux-kernel, ath9k-devel, linux-wireless, kvalo,
	ath9k-devel
  Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 12559 bytes --]

Am 29.01.2015 um 05:09 schrieb zhengyuwei@360.cn:
> From: Yuwei Zheng <zhengyuwei@360.cn>
> 
> In the environment with heavy wifi traffic, set the ar9271 into monitor mode, will
> trigger a deadloop panic. 
> 
> The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and ath9k_rx_tasklet excute
> on the soft irq context. In other words, the ath9k_hif_usb_rx_cb have more chance to excute than
> ath9k_rx_tasklet.  So in the worst condition,  the rx.rxbuf receive list is always full,
> and the do {}while(true) loop will not be break. The kernel get a soft lockup panic.  
>   
> [59011.007210] BUG: soft lockup - CPU#0 stuck for 23s! 
> [kworker/0:0:30609]
> [59011.030560] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
> [59013.804486] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
> [59013.858522] Kernel panic - not syncing: softlockup: hung tasks
> 
> [59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
> [59014.046834] bc20:                                                       de57b950 60000113
> [59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 dc7bb440 df4bbcd0 00000000
> [59014.072337] bc60: de57b950 60000113 df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff
> [59014.085233] [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10)
> [59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc])
> [59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) from [<c0036d23>] (tasklet_action+0x3b/0x98)
> [59014.134132] [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] (__do_softirq+0x99/0x16c)
> [59014.147784] [<c0036709>] (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c)
> [59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] (handle_IRQ+0x37/0x78)
> [59014.173124] [<c000cfc3>] (handle_IRQ+0x37/0x78) from [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68)
> [59014.187225] [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68) from [<c04c28db>](__irq_svc+0x3b/0x5c)
> 
> This bug can be see with low performance board, such as uniprocessor beagle bone board.
> Signed-off-by: Yuwei Zheng <zhengyuwei@360.cn>
> 
> ---
>  drivers/net/wireless/ath/ath9k/hif_usb.c       | 53 ++++++++++++++++++++++----
>  drivers/net/wireless/ath/ath9k/hif_usb.h       |  5 +++
>  drivers/net/wireless/ath/ath9k/htc.h           | 13 +++++++
>  drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 49 ++++++++++++++++++++++++
>  drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 26 +++++++++++++
>  5 files changed, 139 insertions(+), 7 deletions(-)

First of all, thank you for you work! :D

Please run ./scripts/checkpatch.pl yourpatch_path
i get:
total: 139 errors, 12 warnings, 2 checks, 231 lines checked

You use tasklet_hrtimer_start. So far i know, there is no this kind of
hrtimer which is actually hidden behind this word on this SoC.
Especially if requested value is any way in 1 millisecond range you
probably can and should use normal priority tasklet. (correct me if i'm
wrong)

> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
> index 8e7153b..febea5e 100644
> --- a/drivers/net/wireless/ath/ath9k/hif_usb.c
> +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
> @@ -658,7 +658,6 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
>  	default:
>  		goto resubmit;
>  	}
> -
>  	if (likely(urb->actual_length != 0)) {
>  		skb_put(skb, urb->actual_length);
>  		ath9k_hif_usb_rx_stream(hif_dev, skb);
> @@ -667,12 +666,18 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
>  resubmit:
>  	skb_reset_tail_pointer(skb);
>  	skb_trim(skb, 0);
> -
> -	usb_anchor_urb(urb, &hif_dev->rx_submitted);
> -	ret = usb_submit_urb(urb, GFP_ATOMIC);
> -	if (ret) {
> -		usb_unanchor_urb(urb);
> -		goto free;
> +	if (atomic_read(&hif_dev->rx_urb_submit_delay) > 0) {
> +		usb_anchor_urb(urb, &hif_dev->rx_delayed_submitted);
> +		ret = tasklet_hrtimer_start(&hif_dev->rx_submit_timer,
> +					    ktime_set(0, atomic_read(&hif_dev->rx_urb_submit_delay)*1000),
> +					    HRTIMER_MODE_REL);
> +	} else {
> +		usb_anchor_urb(urb, &hif_dev->rx_submitted);
> +		ret = usb_submit_urb(urb, GFP_ATOMIC);
> +		if (ret) {
> +			usb_unanchor_urb(urb);
> +			goto free;
> +		}
>  	}
>  
>  	return;
> @@ -818,9 +823,37 @@ err:
>  	return -ENOMEM;
>  }
>  
> +static enum hrtimer_restart rx_urb_submit_timer_handler(struct hrtimer *me)
> +{
> +	struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
> +	struct  hif_device_usb *hif_dev = container_of(thr, struct hif_device_usb, rx_submit_timer);
> +	struct urb *urb = NULL;
> +	struct sk_buff *skb = NULL;
> +	int ret;
> +
> +	while (true) {
> +		urb = usb_get_from_anchor(&hif_dev->rx_delayed_submitted);
> +		if (urb != NULL) {
> +			skb = (struct sk_buff *)urb->context;
> +			ret = usb_submit_urb(urb, GFP_ATOMIC);
> +			if (ret != -EBUSY) {
> +				usb_unanchor_urb(urb);
> +				dev_kfree_skb_any(skb);
> +				urb->context = NULL;
> +			}
> +		} else {
> +			break;
> +		}
> +	}
> +
> +	return HRTIMER_NORESTART;
> +}
> +
>  static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
>  {
>  	usb_kill_anchored_urbs(&hif_dev->rx_submitted);
> +	usb_kill_anchored_urbs(&hif_dev->rx_delayed_submitted);
> +	tasklet_hrtimer_cancel(&hif_dev->rx_submit_timer);
>  }
>  
>  static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
> @@ -830,6 +863,8 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
>  	int i, ret;
>  
>  	init_usb_anchor(&hif_dev->rx_submitted);
> +	init_usb_anchor(&hif_dev->rx_delayed_submitted);
> +
>  	spin_lock_init(&hif_dev->rx_lock);
>  
>  	for (i = 0; i < MAX_RX_URB_NUM; i++) {
> @@ -871,6 +906,10 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
>  		usb_free_urb(urb);
>  	}
>  
> +	/* add for flow control*/
> +	atomic_set(&hif_dev->rx_urb_submit_delay, 0);
> +	tasklet_hrtimer_init(&hif_dev->rx_submit_timer, rx_urb_submit_timer_handler, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +
>  	return 0;
>  
>  err_submit:
> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
> index 51496e7..56d6be8 100644
> --- a/drivers/net/wireless/ath/ath9k/hif_usb.h
> +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
> @@ -98,9 +98,14 @@ struct hif_device_usb {
>  	struct hif_usb_tx tx;
>  	struct usb_anchor regout_submitted;
>  	struct usb_anchor rx_submitted;
> +	struct usb_anchor rx_delayed_submitted; /* delayed submit anchor */
>  	struct usb_anchor reg_in_submitted;
>  	struct usb_anchor mgmt_submitted;
>  	struct sk_buff *remain_skb;
> +
> +	struct tasklet_hrtimer  rx_submit_timer;/* delayed submit hrtimer */
> +	atomic_t  rx_urb_submit_delay; /*us*/
> +
>  	const char *fw_name;
>  	int rx_remain_len;
>  	int rx_pkt_len;
> diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
> index 9dde265..453d0a8 100644
> --- a/drivers/net/wireless/ath/ath9k/htc.h
> +++ b/drivers/net/wireless/ath/ath9k/htc.h
> @@ -331,6 +331,10 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
>  
>  #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
>  
> +#define TASKLETRX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c++)
> +#define TASKLETRX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c += a)
> +#define TASKLETRX_STAT_SET(c, a) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c = a)
> +
>  void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
>  			   struct ath_rx_status *rs);
>  
> @@ -352,11 +356,20 @@ struct ath_skbrx_stats {
>  	u32 skb_dropped;
>  };
>  
> +struct ath_taskletrx_stats {
> +	u32 taskletrx_looptimes;
> +	u32 taskletrx_highwater;
> +	u32 taskletrx_lowwater;
> +	u32 taskletrx_watermark_triggered;
> +	u32 taskletrx_urb_submit_delay;
> +};
> +
>  struct ath9k_debug {
>  	struct dentry *debugfs_phy;
>  	struct ath_tx_stats tx_stats;
>  	struct ath_rx_stats rx_stats;
>  	struct ath_skbrx_stats skbrx_stats;
> +	struct ath_taskletrx_stats taskletrx_stats;
>  };
>  
>  void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
> diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> index 8cef1ed..7c8322e 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> @@ -286,6 +286,51 @@ static const struct file_operations fops_skb_rx = {
>  	.llseek = default_llseek,
>  };
>  
> +static ssize_t read_file_tasklet_rx(struct file *file, char __user *user_buf,
> +				    size_t count, loff_t *ppos)
> +{
> +	struct ath9k_htc_priv *priv = file->private_data;
> +	char *buf;
> +	unsigned int len = 0, size = 1500;
> +	ssize_t retval = 0;
> +
> +	buf = kzalloc(size, GFP_KERNEL);
> +	if (buf == NULL)
> +		return -ENOMEM;
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "Loop times",
> +			priv->debug.taskletrx_stats.taskletrx_looptimes);
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "High watermark",
> +			priv->debug.taskletrx_stats.taskletrx_highwater);
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "Low watermark",
> +			priv->debug.taskletrx_stats.taskletrx_lowwater);
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "WM triggered",
> +			priv->debug.taskletrx_stats.taskletrx_watermark_triggered);
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "URB delay",
> +			priv->debug.taskletrx_stats.taskletrx_urb_submit_delay);
> +	if (len > size)
> +		len = size;
> +
> +	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
> +	kfree(buf);
> +
> +	return retval;
> +}
> +
> +static const struct file_operations fops_tasklet_rx = {
> +	.read = read_file_tasklet_rx,
> +	.open = simple_open,
> +	.owner = THIS_MODULE,
> +	.llseek = default_llseek,
> +};
> +
>  static ssize_t read_file_slot(struct file *file, char __user *user_buf,
>  			      size_t count, loff_t *ppos)
>  {
> @@ -518,7 +563,11 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
>  	debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
>  			    priv, &fops_skb_rx);
>  
> +	debugfs_create_file("tasklet_rx", S_IRUSR, priv->debug.debugfs_phy,
> +			    priv, &fops_tasklet_rx);
> +
>  	ath9k_cmn_debug_recv(priv->debug.debugfs_phy, &priv->debug.rx_stats);
> +
>  	ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, &priv->debug.rx_stats);
>  
>  	debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy,
> diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> index a0f58e2..f5e6217 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> @@ -1061,7 +1061,28 @@ void ath9k_rx_tasklet(unsigned long data)
>  	unsigned long flags;
>  	struct ieee80211_hdr *hdr;
>  
> +	/* add for adaptive flow control*/
> +	int looptimes = 0;
> +	int highwatermark = ATH9K_HTC_RXBUF*3/4;
> +	int lowwatermark = ATH9K_HTC_RXBUF/4;
> +	unsigned int delay = 0;
> +
> +	struct htc_target *htc = priv->htc;
> +	struct hif_device_usb *hif_dev = htc->hif_dev;
> +
> +	TASKLETRX_STAT_SET(taskletrx_highwater, highwatermark);
> +	TASKLETRX_STAT_SET(taskletrx_lowwater, lowwatermark);
> +
>  	do {
> +		looptimes++;
> +		TASKLETRX_STAT_SET(taskletrx_looptimes, looptimes);
> +		if (looptimes > highwatermark) {
> +			delay = looptimes*10;
> +			atomic_set(&hif_dev->rx_urb_submit_delay, delay);
> +			TASKLETRX_STAT_INC(taskletrx_watermark_triggered);
> +			TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, delay);
> +		}
> +
>  		spin_lock_irqsave(&priv->rx.rxbuflock, flags);
>  		list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
>  			if (tmp_buf->in_process) {
> @@ -1072,6 +1093,11 @@ void ath9k_rx_tasklet(unsigned long data)
>  
>  		if (rxbuf == NULL) {
>  			spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
> +			if (looptimes < lowwatermark) {
> +				atomic_set(&hif_dev->rx_urb_submit_delay, 0);
> +				TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, 0);
> +			}
> +
>  			break;
>  		}
>  
> 


-- 
Regards,
Oleksij


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

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

* [ath9k-devel] [PATCH] Repair soft lockup with monitor mode of ath9k_htc card
@ 2015-01-29 10:52   ` Oleksij Rempel
  0 siblings, 0 replies; 10+ messages in thread
From: Oleksij Rempel @ 2015-01-29 10:52 UTC (permalink / raw)
  To: ath9k-devel

Am 29.01.2015 um 05:09 schrieb zhengyuwei at 360.cn:
> From: Yuwei Zheng <zhengyuwei@360.cn>
> 
> In the environment with heavy wifi traffic, set the ar9271 into monitor mode, will
> trigger a deadloop panic. 
> 
> The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and ath9k_rx_tasklet excute
> on the soft irq context. In other words, the ath9k_hif_usb_rx_cb have more chance to excute than
> ath9k_rx_tasklet.  So in the worst condition,  the rx.rxbuf receive list is always full,
> and the do {}while(true) loop will not be break. The kernel get a soft lockup panic.  
>   
> [59011.007210] BUG: soft lockup - CPU#0 stuck for 23s! 
> [kworker/0:0:30609]
> [59011.030560] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
> [59013.804486] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
> [59013.858522] Kernel panic - not syncing: softlockup: hung tasks
> 
> [59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
> [59014.046834] bc20:                                                       de57b950 60000113
> [59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 dc7bb440 df4bbcd0 00000000
> [59014.072337] bc60: de57b950 60000113 df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff
> [59014.085233] [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10)
> [59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc])
> [59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) from [<c0036d23>] (tasklet_action+0x3b/0x98)
> [59014.134132] [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] (__do_softirq+0x99/0x16c)
> [59014.147784] [<c0036709>] (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c)
> [59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] (handle_IRQ+0x37/0x78)
> [59014.173124] [<c000cfc3>] (handle_IRQ+0x37/0x78) from [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68)
> [59014.187225] [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68) from [<c04c28db>](__irq_svc+0x3b/0x5c)
> 
> This bug can be see with low performance board, such as uniprocessor beagle bone board.
> Signed-off-by: Yuwei Zheng <zhengyuwei@360.cn>
> 
> ---
>  drivers/net/wireless/ath/ath9k/hif_usb.c       | 53 ++++++++++++++++++++++----
>  drivers/net/wireless/ath/ath9k/hif_usb.h       |  5 +++
>  drivers/net/wireless/ath/ath9k/htc.h           | 13 +++++++
>  drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 49 ++++++++++++++++++++++++
>  drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 26 +++++++++++++
>  5 files changed, 139 insertions(+), 7 deletions(-)

First of all, thank you for you work! :D

Please run ./scripts/checkpatch.pl yourpatch_path
i get:
total: 139 errors, 12 warnings, 2 checks, 231 lines checked

You use tasklet_hrtimer_start. So far i know, there is no this kind of
hrtimer which is actually hidden behind this word on this SoC.
Especially if requested value is any way in 1 millisecond range you
probably can and should use normal priority tasklet. (correct me if i'm
wrong)

> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
> index 8e7153b..febea5e 100644
> --- a/drivers/net/wireless/ath/ath9k/hif_usb.c
> +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
> @@ -658,7 +658,6 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
>  	default:
>  		goto resubmit;
>  	}
> -
>  	if (likely(urb->actual_length != 0)) {
>  		skb_put(skb, urb->actual_length);
>  		ath9k_hif_usb_rx_stream(hif_dev, skb);
> @@ -667,12 +666,18 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
>  resubmit:
>  	skb_reset_tail_pointer(skb);
>  	skb_trim(skb, 0);
> -
> -	usb_anchor_urb(urb, &hif_dev->rx_submitted);
> -	ret = usb_submit_urb(urb, GFP_ATOMIC);
> -	if (ret) {
> -		usb_unanchor_urb(urb);
> -		goto free;
> +	if (atomic_read(&hif_dev->rx_urb_submit_delay) > 0) {
> +		usb_anchor_urb(urb, &hif_dev->rx_delayed_submitted);
> +		ret = tasklet_hrtimer_start(&hif_dev->rx_submit_timer,
> +					    ktime_set(0, atomic_read(&hif_dev->rx_urb_submit_delay)*1000),
> +					    HRTIMER_MODE_REL);
> +	} else {
> +		usb_anchor_urb(urb, &hif_dev->rx_submitted);
> +		ret = usb_submit_urb(urb, GFP_ATOMIC);
> +		if (ret) {
> +			usb_unanchor_urb(urb);
> +			goto free;
> +		}
>  	}
>  
>  	return;
> @@ -818,9 +823,37 @@ err:
>  	return -ENOMEM;
>  }
>  
> +static enum hrtimer_restart rx_urb_submit_timer_handler(struct hrtimer *me)
> +{
> +	struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
> +	struct  hif_device_usb *hif_dev = container_of(thr, struct hif_device_usb, rx_submit_timer);
> +	struct urb *urb = NULL;
> +	struct sk_buff *skb = NULL;
> +	int ret;
> +
> +	while (true) {
> +		urb = usb_get_from_anchor(&hif_dev->rx_delayed_submitted);
> +		if (urb != NULL) {
> +			skb = (struct sk_buff *)urb->context;
> +			ret = usb_submit_urb(urb, GFP_ATOMIC);
> +			if (ret != -EBUSY) {
> +				usb_unanchor_urb(urb);
> +				dev_kfree_skb_any(skb);
> +				urb->context = NULL;
> +			}
> +		} else {
> +			break;
> +		}
> +	}
> +
> +	return HRTIMER_NORESTART;
> +}
> +
>  static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
>  {
>  	usb_kill_anchored_urbs(&hif_dev->rx_submitted);
> +	usb_kill_anchored_urbs(&hif_dev->rx_delayed_submitted);
> +	tasklet_hrtimer_cancel(&hif_dev->rx_submit_timer);
>  }
>  
>  static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
> @@ -830,6 +863,8 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
>  	int i, ret;
>  
>  	init_usb_anchor(&hif_dev->rx_submitted);
> +	init_usb_anchor(&hif_dev->rx_delayed_submitted);
> +
>  	spin_lock_init(&hif_dev->rx_lock);
>  
>  	for (i = 0; i < MAX_RX_URB_NUM; i++) {
> @@ -871,6 +906,10 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
>  		usb_free_urb(urb);
>  	}
>  
> +	/* add for flow control*/
> +	atomic_set(&hif_dev->rx_urb_submit_delay, 0);
> +	tasklet_hrtimer_init(&hif_dev->rx_submit_timer, rx_urb_submit_timer_handler, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +
>  	return 0;
>  
>  err_submit:
> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
> index 51496e7..56d6be8 100644
> --- a/drivers/net/wireless/ath/ath9k/hif_usb.h
> +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
> @@ -98,9 +98,14 @@ struct hif_device_usb {
>  	struct hif_usb_tx tx;
>  	struct usb_anchor regout_submitted;
>  	struct usb_anchor rx_submitted;
> +	struct usb_anchor rx_delayed_submitted; /* delayed submit anchor */
>  	struct usb_anchor reg_in_submitted;
>  	struct usb_anchor mgmt_submitted;
>  	struct sk_buff *remain_skb;
> +
> +	struct tasklet_hrtimer  rx_submit_timer;/* delayed submit hrtimer */
> +	atomic_t  rx_urb_submit_delay; /*us*/
> +
>  	const char *fw_name;
>  	int rx_remain_len;
>  	int rx_pkt_len;
> diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
> index 9dde265..453d0a8 100644
> --- a/drivers/net/wireless/ath/ath9k/htc.h
> +++ b/drivers/net/wireless/ath/ath9k/htc.h
> @@ -331,6 +331,10 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
>  
>  #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
>  
> +#define TASKLETRX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c++)
> +#define TASKLETRX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c += a)
> +#define TASKLETRX_STAT_SET(c, a) (hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c = a)
> +
>  void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
>  			   struct ath_rx_status *rs);
>  
> @@ -352,11 +356,20 @@ struct ath_skbrx_stats {
>  	u32 skb_dropped;
>  };
>  
> +struct ath_taskletrx_stats {
> +	u32 taskletrx_looptimes;
> +	u32 taskletrx_highwater;
> +	u32 taskletrx_lowwater;
> +	u32 taskletrx_watermark_triggered;
> +	u32 taskletrx_urb_submit_delay;
> +};
> +
>  struct ath9k_debug {
>  	struct dentry *debugfs_phy;
>  	struct ath_tx_stats tx_stats;
>  	struct ath_rx_stats rx_stats;
>  	struct ath_skbrx_stats skbrx_stats;
> +	struct ath_taskletrx_stats taskletrx_stats;
>  };
>  
>  void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
> diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> index 8cef1ed..7c8322e 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> @@ -286,6 +286,51 @@ static const struct file_operations fops_skb_rx = {
>  	.llseek = default_llseek,
>  };
>  
> +static ssize_t read_file_tasklet_rx(struct file *file, char __user *user_buf,
> +				    size_t count, loff_t *ppos)
> +{
> +	struct ath9k_htc_priv *priv = file->private_data;
> +	char *buf;
> +	unsigned int len = 0, size = 1500;
> +	ssize_t retval = 0;
> +
> +	buf = kzalloc(size, GFP_KERNEL);
> +	if (buf == NULL)
> +		return -ENOMEM;
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "Loop times",
> +			priv->debug.taskletrx_stats.taskletrx_looptimes);
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "High watermark",
> +			priv->debug.taskletrx_stats.taskletrx_highwater);
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "Low watermark",
> +			priv->debug.taskletrx_stats.taskletrx_lowwater);
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "WM triggered",
> +			priv->debug.taskletrx_stats.taskletrx_watermark_triggered);
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "URB delay",
> +			priv->debug.taskletrx_stats.taskletrx_urb_submit_delay);
> +	if (len > size)
> +		len = size;
> +
> +	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
> +	kfree(buf);
> +
> +	return retval;
> +}
> +
> +static const struct file_operations fops_tasklet_rx = {
> +	.read = read_file_tasklet_rx,
> +	.open = simple_open,
> +	.owner = THIS_MODULE,
> +	.llseek = default_llseek,
> +};
> +
>  static ssize_t read_file_slot(struct file *file, char __user *user_buf,
>  			      size_t count, loff_t *ppos)
>  {
> @@ -518,7 +563,11 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
>  	debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
>  			    priv, &fops_skb_rx);
>  
> +	debugfs_create_file("tasklet_rx", S_IRUSR, priv->debug.debugfs_phy,
> +			    priv, &fops_tasklet_rx);
> +
>  	ath9k_cmn_debug_recv(priv->debug.debugfs_phy, &priv->debug.rx_stats);
> +
>  	ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, &priv->debug.rx_stats);
>  
>  	debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy,
> diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> index a0f58e2..f5e6217 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> @@ -1061,7 +1061,28 @@ void ath9k_rx_tasklet(unsigned long data)
>  	unsigned long flags;
>  	struct ieee80211_hdr *hdr;
>  
> +	/* add for adaptive flow control*/
> +	int looptimes = 0;
> +	int highwatermark = ATH9K_HTC_RXBUF*3/4;
> +	int lowwatermark = ATH9K_HTC_RXBUF/4;
> +	unsigned int delay = 0;
> +
> +	struct htc_target *htc = priv->htc;
> +	struct hif_device_usb *hif_dev = htc->hif_dev;
> +
> +	TASKLETRX_STAT_SET(taskletrx_highwater, highwatermark);
> +	TASKLETRX_STAT_SET(taskletrx_lowwater, lowwatermark);
> +
>  	do {
> +		looptimes++;
> +		TASKLETRX_STAT_SET(taskletrx_looptimes, looptimes);
> +		if (looptimes > highwatermark) {
> +			delay = looptimes*10;
> +			atomic_set(&hif_dev->rx_urb_submit_delay, delay);
> +			TASKLETRX_STAT_INC(taskletrx_watermark_triggered);
> +			TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, delay);
> +		}
> +
>  		spin_lock_irqsave(&priv->rx.rxbuflock, flags);
>  		list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
>  			if (tmp_buf->in_process) {
> @@ -1072,6 +1093,11 @@ void ath9k_rx_tasklet(unsigned long data)
>  
>  		if (rxbuf == NULL) {
>  			spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
> +			if (looptimes < lowwatermark) {
> +				atomic_set(&hif_dev->rx_urb_submit_delay, 0);
> +				TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, 0);
> +			}
> +
>  			break;
>  		}
>  
> 


-- 
Regards,
Oleksij

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 213 bytes
Desc: OpenPGP digital signature
Url : http://lists.ath9k.org/pipermail/ath9k-devel/attachments/20150129/588dfdbb/attachment.pgp 

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

* Re: [ath9k-devel] [PATCH] Repair soft lockup with monitor mode of ath9k_htc card
  2015-01-29 10:52   ` Oleksij Rempel
@ 2015-01-29 11:01     ` Kalle Valo
  -1 siblings, 0 replies; 10+ messages in thread
From: Kalle Valo @ 2015-01-29 11:01 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: zhengyuwei, linux-kernel, ath9k-devel, linux-wireless,
	ath9k-devel, netdev

Oleksij Rempel <linux@rempel-privat.de> writes:

> Am 29.01.2015 um 05:09 schrieb zhengyuwei@360.cn:
>> From: Yuwei Zheng <zhengyuwei@360.cn>
>> 
>> In the environment with heavy wifi traffic, set the ar9271 into monitor mode, will
>> trigger a deadloop panic. 
>> 
>> The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and ath9k_rx_tasklet excute
>> on the soft irq context. In other words, the ath9k_hif_usb_rx_cb have more chance to excute than
>> ath9k_rx_tasklet.  So in the worst condition,  the rx.rxbuf receive list is always full,
>> and the do {}while(true) loop will not be break. The kernel get a soft lockup panic.  
>>   
>> [59011.007210] BUG: soft lockup - CPU#0 stuck for 23s! 
>> [kworker/0:0:30609]
>> [59011.030560] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
>> [59013.804486] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
>> [59013.858522] Kernel panic - not syncing: softlockup: hung tasks
>> 
>> [59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
>> [59014.046834] bc20:                                                       de57b950 60000113
>> [59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 dc7bb440 df4bbcd0 00000000
>> [59014.072337] bc60: de57b950 60000113 df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff
>> [59014.085233] [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10)
>> [59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc])
>> [59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) from [<c0036d23>] (tasklet_action+0x3b/0x98)
>> [59014.134132] [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] (__do_softirq+0x99/0x16c)
>> [59014.147784] [<c0036709>] (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c)
>> [59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] (handle_IRQ+0x37/0x78)
>> [59014.173124] [<c000cfc3>] (handle_IRQ+0x37/0x78) from [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68)
>> [59014.187225] [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68) from [<c04c28db>](__irq_svc+0x3b/0x5c)
>> 
>> This bug can be see with low performance board, such as uniprocessor beagle bone board.
>> Signed-off-by: Yuwei Zheng <zhengyuwei@360.cn>
>> 
>> ---
>>  drivers/net/wireless/ath/ath9k/hif_usb.c       | 53 ++++++++++++++++++++++----
>>  drivers/net/wireless/ath/ath9k/hif_usb.h       |  5 +++
>>  drivers/net/wireless/ath/ath9k/htc.h           | 13 +++++++
>>  drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 49 ++++++++++++++++++++++++
>>  drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 26 +++++++++++++
>>  5 files changed, 139 insertions(+), 7 deletions(-)
>
> First of all, thank you for you work! :D
>
> Please run ./scripts/checkpatch.pl yourpatch_path
> i get:
> total: 139 errors, 12 warnings, 2 checks, 231 lines checked

Also please add "ath9k_htc:" prefix to the title.

-- 
Kalle Valo

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

* [ath9k-devel] [PATCH] Repair soft lockup with monitor mode of ath9k_htc card
@ 2015-01-29 11:01     ` Kalle Valo
  0 siblings, 0 replies; 10+ messages in thread
From: Kalle Valo @ 2015-01-29 11:01 UTC (permalink / raw)
  To: ath9k-devel

Oleksij Rempel <linux@rempel-privat.de> writes:

> Am 29.01.2015 um 05:09 schrieb zhengyuwei at 360.cn:
>> From: Yuwei Zheng <zhengyuwei@360.cn>
>> 
>> In the environment with heavy wifi traffic, set the ar9271 into monitor mode, will
>> trigger a deadloop panic. 
>> 
>> The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and ath9k_rx_tasklet excute
>> on the soft irq context. In other words, the ath9k_hif_usb_rx_cb have more chance to excute than
>> ath9k_rx_tasklet.  So in the worst condition,  the rx.rxbuf receive list is always full,
>> and the do {}while(true) loop will not be break. The kernel get a soft lockup panic.  
>>   
>> [59011.007210] BUG: soft lockup - CPU#0 stuck for 23s! 
>> [kworker/0:0:30609]
>> [59011.030560] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
>> [59013.804486] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
>> [59013.858522] Kernel panic - not syncing: softlockup: hung tasks
>> 
>> [59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
>> [59014.046834] bc20:                                                       de57b950 60000113
>> [59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 dc7bb440 df4bbcd0 00000000
>> [59014.072337] bc60: de57b950 60000113 df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff
>> [59014.085233] [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10)
>> [59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc])
>> [59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) from [<c0036d23>] (tasklet_action+0x3b/0x98)
>> [59014.134132] [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] (__do_softirq+0x99/0x16c)
>> [59014.147784] [<c0036709>] (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c)
>> [59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] (handle_IRQ+0x37/0x78)
>> [59014.173124] [<c000cfc3>] (handle_IRQ+0x37/0x78) from [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68)
>> [59014.187225] [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68) from [<c04c28db>](__irq_svc+0x3b/0x5c)
>> 
>> This bug can be see with low performance board, such as uniprocessor beagle bone board.
>> Signed-off-by: Yuwei Zheng <zhengyuwei@360.cn>
>> 
>> ---
>>  drivers/net/wireless/ath/ath9k/hif_usb.c       | 53 ++++++++++++++++++++++----
>>  drivers/net/wireless/ath/ath9k/hif_usb.h       |  5 +++
>>  drivers/net/wireless/ath/ath9k/htc.h           | 13 +++++++
>>  drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 49 ++++++++++++++++++++++++
>>  drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 26 +++++++++++++
>>  5 files changed, 139 insertions(+), 7 deletions(-)
>
> First of all, thank you for you work! :D
>
> Please run ./scripts/checkpatch.pl yourpatch_path
> i get:
> total: 139 errors, 12 warnings, 2 checks, 231 lines checked

Also please add "ath9k_htc:" prefix to the title.

-- 
Kalle Valo

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

* 答复: [ath9k-devel] [PATCH] Repair soft lockup with monitor mode of ath9k_htc card
  2015-01-29 10:52   ` Oleksij Rempel
  (?)
  (?)
@ 2015-01-30 10:24     ` 郑玉伟
  -1 siblings, 0 replies; 10+ messages in thread
From: 郑玉伟 @ 2015-01-30 10:24 UTC (permalink / raw)
  To: Oleksij Rempel, linux-kernel, ath9k-devel, linux-wireless, kvalo,
	ath9k-devel
  Cc: netdev

U29ycnksIHRoZSBwYXRjaCBydWluZWQgYnkgdGhlIG1haWwgZWRpdG9yLCBJIHdpbGwgc2VuZCB0
aGUgcGF0Y2ggd2l0aCBhbm90aGVyIG1haWwgYWNjb3VudCB3aXRjaCBzdXBwb3J0IHNtdHAuIA0K
DQpJIHVzZSB0YXNrbGV0X2hydGltZXJfc3RhcnQgZm9yIGRlbGF5ZWQgc3VibWl0LCBhbmQgdGhl
IGhydGltZXIgY2FsbGJhY2sgZnVuY3Rpb24gaXMgZXhjdXRlZCBpbiB0aGUgbG93ZXIgcHJpb3Jp
dHkgdGhhbiBub3JtYWwgdGFza2xldC4gKFRBU0tMRVRfU09GVElSUSA1LCBIUlRJTUVSX1NPRlRJ
UlEgNyApDQoNClRoZSBocnRpbWVyIG1vZGUgaGFzIGJlZW4gdGVzdGVkIHNldmVyYWwgd2Vla3Mu
ICBTbyBJIHNlbGVjdCB0aGlzIHdheSBjdXJyZW50bHkuDQoNCg0KLS0tLS3pgq7ku7bljp/ku7Yt
LS0tLQ0K5Y+R5Lu25Lq6OiBPbGVrc2lqIFJlbXBlbCBbbWFpbHRvOmxpbnV4QHJlbXBlbC1wcml2
YXQuZGVdIA0K5Y+R6YCB5pe26Ze0OiAyMDE15bm0MeaciDI55pelIDE4OjUyDQrmlLbku7bkuro6
IOmDkeeOieS8nzsgbGludXgta2VybmVsQHZnZXIua2VybmVsLm9yZzsgYXRoOWstZGV2ZWxAdmVu
ZW1hLmg0Y2tyLm5ldDsgbGludXgtd2lyZWxlc3NAdmdlci5rZXJuZWwub3JnOyBrdmFsb0Bjb2Rl
YXVyb3JhLm9yZzsgYXRoOWstZGV2ZWxAcWNhLnF1YWxjb21tLmNvbQ0K5oqE6YCBOiBuZXRkZXZA
dmdlci5rZXJuZWwub3JnDQrkuLvpopg6IFJlOiBbYXRoOWstZGV2ZWxdIFtQQVRDSF0gUmVwYWly
IHNvZnQgbG9ja3VwIHdpdGggbW9uaXRvciBtb2RlIG9mIGF0aDlrX2h0YyBjYXJkDQoNCkFtIDI5
LjAxLjIwMTUgdW0gMDU6MDkgc2NocmllYiB6aGVuZ3l1d2VpQDM2MC5jbjoNCj4gRnJvbTogWXV3
ZWkgWmhlbmcgPHpoZW5neXV3ZWlAMzYwLmNuPg0KPiANCj4gSW4gdGhlIGVudmlyb25tZW50IHdp
dGggaGVhdnkgd2lmaSB0cmFmZmljLCBzZXQgdGhlIGFyOTI3MSBpbnRvIA0KPiBtb25pdG9yIG1v
ZGUsIHdpbGwgdHJpZ2dlciBhIGRlYWRsb29wIHBhbmljLg0KPiANCj4gVGhlIGF0aDlrX2hpZl91
c2JfcnhfY2IgZnVuY3Rpb24gZXhjdXRlIG9uICB0aGUgaW50ZXJydXB0IGNvbnRleHQsIGFuZCAN
Cj4gYXRoOWtfcnhfdGFza2xldCBleGN1dGUgb24gdGhlIHNvZnQgaXJxIGNvbnRleHQuIEluIG90
aGVyIHdvcmRzLCB0aGUgDQo+IGF0aDlrX2hpZl91c2JfcnhfY2IgaGF2ZSBtb3JlIGNoYW5jZSB0
byBleGN1dGUgdGhhbiBhdGg5a19yeF90YXNrbGV0LiAgDQo+IFNvIGluIHRoZSB3b3JzdCBjb25k
aXRpb24sICB0aGUgcngucnhidWYgcmVjZWl2ZSBsaXN0IGlzIGFsd2F5cyBmdWxsLCBhbmQgdGhl
IGRvIHt9d2hpbGUodHJ1ZSkgbG9vcCB3aWxsIG5vdCBiZSBicmVhay4gVGhlIGtlcm5lbCBnZXQg
YSBzb2Z0IGxvY2t1cCBwYW5pYy4NCj4gICANCj4gWzU5MDExLjAwNzIxMF0gQlVHOiBzb2Z0IGxv
Y2t1cCAtIENQVSMwIHN0dWNrIGZvciAyM3MhIA0KPiBba3dvcmtlci8wOjA6MzA2MDldDQo+IFs1
OTAxMS4wMzA1NjBdIEJVRzogc2NoZWR1bGluZyB3aGlsZSBhdG9taWM6IA0KPiBrd29ya2VyLzA6
MC8zMDYwOS8weDQwMDEwMTAwIFs1OTAxMy44MDQ0ODZdIEJVRzogc2NoZWR1bGluZyB3aGlsZSAN
Cj4gYXRvbWljOiBrd29ya2VyLzA6MC8zMDYwOS8weDQwMDEwMTAwIFs1OTAxMy44NTg1MjJdIEtl
cm5lbCBwYW5pYyAtIG5vdCANCj4gc3luY2luZzogc29mdGxvY2t1cDogaHVuZyB0YXNrcw0KPiAN
Cj4gWzU5MDE0LjAzODg5MV0gRXhjZXB0aW9uIHN0YWNrKDB4ZGY0YmJjMzggdG8gMHhkZjRiYmM4
MCkNCj4gWzU5MDE0LjA0NjgzNF0gYmMyMDogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgZGU1N2I5NTAgNjAwMDAxMTMNCj4gWzU5MDE0LjA1OTU3
OV0gYmM0MDogMDAwMDAwMDAgYmIzMmJiMzIgNjAwMDAxMTMgZGU1N2I5NDggZGU1N2I1MDAgDQo+
IGRjN2JiNDQwIGRmNGJiY2QwIDAwMDAwMDAwIFs1OTAxNC4wNzIzMzddIGJjNjA6IGRlNTdiOTUw
IDYwMDAwMTEzIA0KPiBkZjRiYmNkMCBkZjRiYmM4MCBjMDRjMjU5ZCBjMDRjMjVhMCA2MDAwMDEz
MyBmZmZmZmZmZiBbNTkwMTQuMDg1MjMzXSANCj4gWzxjMDRjMjhkYj5dIChfX2lycV9zdmMrMHgz
Yi8weDVjKSBmcm9tIFs8YzA0YzI1YTA+XSANCj4gKF9yYXdfc3Bpbl91bmxvY2tfaXJxcmVzdG9y
ZSsweGMvMHgxMCkNCj4gWzU5MDE0LjEwMDQzN10gWzxjMDRjMjVhMD5dIChfcmF3X3NwaW5fdW5s
b2NrX2lycXJlc3RvcmUrMHhjLzB4MTApIA0KPiBmcm9tIFs8YmY5YzIwODk+XSAoYXRoOWtfcnhf
dGFza2xldCsweDI5MC8weDQ5MCBbYXRoOWtfaHRjXSkgDQo+IFs1OTAxNC4xMTgyNjddIFs8YmY5
YzIwODk+XSAoYXRoOWtfcnhfdGFza2xldCsweDI5MC8weDQ5MCBbYXRoOWtfaHRjXSkgDQo+IGZy
b20gWzxjMDAzNmQyMz5dICh0YXNrbGV0X2FjdGlvbisweDNiLzB4OTgpIFs1OTAxNC4xMzQxMzJd
IA0KPiBbPGMwMDM2ZDIzPl0gKHRhc2tsZXRfYWN0aW9uKzB4M2IvMHg5OCkgZnJvbSBbPGMwMDM2
NzA5Pl0gDQo+IChfX2RvX3NvZnRpcnErMHg5OS8weDE2YykgWzU5MDE0LjE0Nzc4NF0gWzxjMDAz
NjcwOT5dIA0KPiAoX19kb19zb2Z0aXJxKzB4OTkvMHgxNmMpIGZyb20gWzxjMDAzNjlmNz5dIChp
cnFfZXhpdCsweDViLzB4NWMpIA0KPiBbNTkwMTQuMTYwNjUzXSBbPGMwMDM2OWY3Pl0gKGlycV9l
eGl0KzB4NWIvMHg1YykgZnJvbSBbPGMwMDBjZmMzPl0gDQo+IChoYW5kbGVfSVJRKzB4MzcvMHg3
OCkgWzU5MDE0LjE3MzEyNF0gWzxjMDAwY2ZjMz5dIA0KPiAoaGFuZGxlX0lSUSsweDM3LzB4Nzgp
IGZyb20gWzxjMDAwODVkZj5dIA0KPiAob21hcDNfaW50Y19oYW5kbGVfaXJxKzB4NWYvMHg2OCkg
WzU5MDE0LjE4NzIyNV0gWzxjMDAwODVkZj5dIA0KPiAob21hcDNfaW50Y19oYW5kbGVfaXJxKzB4
NWYvMHg2OCkgZnJvbSANCj4gWzxjMDRjMjhkYj5dKF9faXJxX3N2YysweDNiLzB4NWMpDQo+IA0K
PiBUaGlzIGJ1ZyBjYW4gYmUgc2VlIHdpdGggbG93IHBlcmZvcm1hbmNlIGJvYXJkLCBzdWNoIGFz
IHVuaXByb2Nlc3NvciBiZWFnbGUgYm9uZSBib2FyZC4NCj4gU2lnbmVkLW9mZi1ieTogWXV3ZWkg
WmhlbmcgPHpoZW5neXV3ZWlAMzYwLmNuPg0KPiANCj4gLS0tDQo+ICBkcml2ZXJzL25ldC93aXJl
bGVzcy9hdGgvYXRoOWsvaGlmX3VzYi5jICAgICAgIHwgNTMgKysrKysrKysrKysrKysrKysrKysr
Ky0tLS0NCj4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg5ay9oaWZfdXNiLmggICAgICAg
fCAgNSArKysNCj4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg5ay9odGMuaCAgICAgICAg
ICAgfCAxMyArKysrKysrDQo+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoOWsvaHRjX2Ry
dl9kZWJ1Zy5jIHwgNDkgDQo+ICsrKysrKysrKysrKysrKysrKysrKysrKyAgDQo+IGRyaXZlcnMv
bmV0L3dpcmVsZXNzL2F0aC9hdGg5ay9odGNfZHJ2X3R4cnguYyAgfCAyNiArKysrKysrKysrKysr
DQo+ICA1IGZpbGVzIGNoYW5nZWQsIDEzOSBpbnNlcnRpb25zKCspLCA3IGRlbGV0aW9ucygtKQ0K
DQpGaXJzdCBvZiBhbGwsIHRoYW5rIHlvdSBmb3IgeW91IHdvcmshIDpEDQoNClBsZWFzZSBydW4g
Li9zY3JpcHRzL2NoZWNrcGF0Y2gucGwgeW91cnBhdGNoX3BhdGggaSBnZXQ6DQp0b3RhbDogMTM5
IGVycm9ycywgMTIgd2FybmluZ3MsIDIgY2hlY2tzLCAyMzEgbGluZXMgY2hlY2tlZA0KDQpZb3Ug
dXNlIHRhc2tsZXRfaHJ0aW1lcl9zdGFydC4gU28gZmFyIGkga25vdywgdGhlcmUgaXMgbm8gdGhp
cyBraW5kIG9mIGhydGltZXIgd2hpY2ggaXMgYWN0dWFsbHkgaGlkZGVuIGJlaGluZCB0aGlzIHdv
cmQgb24gdGhpcyBTb0MuDQpFc3BlY2lhbGx5IGlmIHJlcXVlc3RlZCB2YWx1ZSBpcyBhbnkgd2F5
IGluIDEgbWlsbGlzZWNvbmQgcmFuZ2UgeW91IHByb2JhYmx5IGNhbiBhbmQgc2hvdWxkIHVzZSBu
b3JtYWwgcHJpb3JpdHkgdGFza2xldC4gKGNvcnJlY3QgbWUgaWYgaSdtDQp3cm9uZykNCg0KPiBk
aWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDlrL2hpZl91c2IuYyANCj4g
Yi9kcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoOWsvaGlmX3VzYi5jDQo+IGluZGV4IDhlNzE1
M2IuLmZlYmVhNWUgMTAwNjQ0DQo+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg5
ay9oaWZfdXNiLmMNCj4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDlrL2hpZl91
c2IuYw0KPiBAQCAtNjU4LDcgKzY1OCw2IEBAIHN0YXRpYyB2b2lkIGF0aDlrX2hpZl91c2Jfcnhf
Y2Ioc3RydWN0IHVyYiAqdXJiKQ0KPiAgCWRlZmF1bHQ6DQo+ICAJCWdvdG8gcmVzdWJtaXQ7DQo+
ICAJfQ0KPiAtDQo+ICAJaWYgKGxpa2VseSh1cmItPmFjdHVhbF9sZW5ndGggIT0gMCkpIHsNCj4g
IAkJc2tiX3B1dChza2IsIHVyYi0+YWN0dWFsX2xlbmd0aCk7DQo+ICAJCWF0aDlrX2hpZl91c2Jf
cnhfc3RyZWFtKGhpZl9kZXYsIHNrYik7IEBAIC02NjcsMTIgKzY2NiwxOCBAQCBzdGF0aWMgDQo+
IHZvaWQgYXRoOWtfaGlmX3VzYl9yeF9jYihzdHJ1Y3QgdXJiICp1cmIpDQo+ICByZXN1Ym1pdDoN
Cj4gIAlza2JfcmVzZXRfdGFpbF9wb2ludGVyKHNrYik7DQo+ICAJc2tiX3RyaW0oc2tiLCAwKTsN
Cj4gLQ0KPiAtCXVzYl9hbmNob3JfdXJiKHVyYiwgJmhpZl9kZXYtPnJ4X3N1Ym1pdHRlZCk7DQo+
IC0JcmV0ID0gdXNiX3N1Ym1pdF91cmIodXJiLCBHRlBfQVRPTUlDKTsNCj4gLQlpZiAocmV0KSB7
DQo+IC0JCXVzYl91bmFuY2hvcl91cmIodXJiKTsNCj4gLQkJZ290byBmcmVlOw0KPiArCWlmIChh
dG9taWNfcmVhZCgmaGlmX2Rldi0+cnhfdXJiX3N1Ym1pdF9kZWxheSkgPiAwKSB7DQo+ICsJCXVz
Yl9hbmNob3JfdXJiKHVyYiwgJmhpZl9kZXYtPnJ4X2RlbGF5ZWRfc3VibWl0dGVkKTsNCj4gKwkJ
cmV0ID0gdGFza2xldF9ocnRpbWVyX3N0YXJ0KCZoaWZfZGV2LT5yeF9zdWJtaXRfdGltZXIsDQo+
ICsJCQkJCSAgICBrdGltZV9zZXQoMCwgYXRvbWljX3JlYWQoJmhpZl9kZXYtPnJ4X3VyYl9zdWJt
aXRfZGVsYXkpKjEwMDApLA0KPiArCQkJCQkgICAgSFJUSU1FUl9NT0RFX1JFTCk7DQo+ICsJfSBl
bHNlIHsNCj4gKwkJdXNiX2FuY2hvcl91cmIodXJiLCAmaGlmX2Rldi0+cnhfc3VibWl0dGVkKTsN
Cj4gKwkJcmV0ID0gdXNiX3N1Ym1pdF91cmIodXJiLCBHRlBfQVRPTUlDKTsNCj4gKwkJaWYgKHJl
dCkgew0KPiArCQkJdXNiX3VuYW5jaG9yX3VyYih1cmIpOw0KPiArCQkJZ290byBmcmVlOw0KPiAr
CQl9DQo+ICAJfQ0KPiAgDQo+ICAJcmV0dXJuOw0KPiBAQCAtODE4LDkgKzgyMywzNyBAQCBlcnI6
DQo+ICAJcmV0dXJuIC1FTk9NRU07DQo+ICB9DQo+ICANCj4gK3N0YXRpYyBlbnVtIGhydGltZXJf
cmVzdGFydCByeF91cmJfc3VibWl0X3RpbWVyX2hhbmRsZXIoc3RydWN0IA0KPiAraHJ0aW1lciAq
bWUpIHsNCj4gKwlzdHJ1Y3QgdGFza2xldF9ocnRpbWVyICp0aHIgPSBjb250YWluZXJfb2YobWUs
IHN0cnVjdCB0YXNrbGV0X2hydGltZXIsIHRpbWVyKTsNCj4gKwlzdHJ1Y3QgIGhpZl9kZXZpY2Vf
dXNiICpoaWZfZGV2ID0gY29udGFpbmVyX29mKHRociwgc3RydWN0IGhpZl9kZXZpY2VfdXNiLCBy
eF9zdWJtaXRfdGltZXIpOw0KPiArCXN0cnVjdCB1cmIgKnVyYiA9IE5VTEw7DQo+ICsJc3RydWN0
IHNrX2J1ZmYgKnNrYiA9IE5VTEw7DQo+ICsJaW50IHJldDsNCj4gKw0KPiArCXdoaWxlICh0cnVl
KSB7DQo+ICsJCXVyYiA9IHVzYl9nZXRfZnJvbV9hbmNob3IoJmhpZl9kZXYtPnJ4X2RlbGF5ZWRf
c3VibWl0dGVkKTsNCj4gKwkJaWYgKHVyYiAhPSBOVUxMKSB7DQo+ICsJCQlza2IgPSAoc3RydWN0
IHNrX2J1ZmYgKil1cmItPmNvbnRleHQ7DQo+ICsJCQlyZXQgPSB1c2Jfc3VibWl0X3VyYih1cmIs
IEdGUF9BVE9NSUMpOw0KPiArCQkJaWYgKHJldCAhPSAtRUJVU1kpIHsNCj4gKwkJCQl1c2JfdW5h
bmNob3JfdXJiKHVyYik7DQo+ICsJCQkJZGV2X2tmcmVlX3NrYl9hbnkoc2tiKTsNCj4gKwkJCQl1
cmItPmNvbnRleHQgPSBOVUxMOw0KPiArCQkJfQ0KPiArCQl9IGVsc2Ugew0KPiArCQkJYnJlYWs7
DQo+ICsJCX0NCj4gKwl9DQo+ICsNCj4gKwlyZXR1cm4gSFJUSU1FUl9OT1JFU1RBUlQ7DQo+ICt9
DQo+ICsNCj4gIHN0YXRpYyB2b2lkIGF0aDlrX2hpZl91c2JfZGVhbGxvY19yeF91cmJzKHN0cnVj
dCBoaWZfZGV2aWNlX3VzYiANCj4gKmhpZl9kZXYpICB7DQo+ICAJdXNiX2tpbGxfYW5jaG9yZWRf
dXJicygmaGlmX2Rldi0+cnhfc3VibWl0dGVkKTsNCj4gKwl1c2Jfa2lsbF9hbmNob3JlZF91cmJz
KCZoaWZfZGV2LT5yeF9kZWxheWVkX3N1Ym1pdHRlZCk7DQo+ICsJdGFza2xldF9ocnRpbWVyX2Nh
bmNlbCgmaGlmX2Rldi0+cnhfc3VibWl0X3RpbWVyKTsNCj4gIH0NCj4gIA0KPiAgc3RhdGljIGlu
dCBhdGg5a19oaWZfdXNiX2FsbG9jX3J4X3VyYnMoc3RydWN0IGhpZl9kZXZpY2VfdXNiIA0KPiAq
aGlmX2RldikgQEAgLTgzMCw2ICs4NjMsOCBAQCBzdGF0aWMgaW50IGF0aDlrX2hpZl91c2JfYWxs
b2NfcnhfdXJicyhzdHJ1Y3QgaGlmX2RldmljZV91c2IgKmhpZl9kZXYpDQo+ICAJaW50IGksIHJl
dDsNCj4gIA0KPiAgCWluaXRfdXNiX2FuY2hvcigmaGlmX2Rldi0+cnhfc3VibWl0dGVkKTsNCj4g
Kwlpbml0X3VzYl9hbmNob3IoJmhpZl9kZXYtPnJ4X2RlbGF5ZWRfc3VibWl0dGVkKTsNCj4gKw0K
PiAgCXNwaW5fbG9ja19pbml0KCZoaWZfZGV2LT5yeF9sb2NrKTsNCj4gIA0KPiAgCWZvciAoaSA9
IDA7IGkgPCBNQVhfUlhfVVJCX05VTTsgaSsrKSB7IEBAIC04NzEsNiArOTA2LDEwIEBAIHN0YXRp
YyANCj4gaW50IGF0aDlrX2hpZl91c2JfYWxsb2NfcnhfdXJicyhzdHJ1Y3QgaGlmX2RldmljZV91
c2IgKmhpZl9kZXYpDQo+ICAJCXVzYl9mcmVlX3VyYih1cmIpOw0KPiAgCX0NCj4gIA0KPiArCS8q
IGFkZCBmb3IgZmxvdyBjb250cm9sKi8NCj4gKwlhdG9taWNfc2V0KCZoaWZfZGV2LT5yeF91cmJf
c3VibWl0X2RlbGF5LCAwKTsNCj4gKwl0YXNrbGV0X2hydGltZXJfaW5pdCgmaGlmX2Rldi0+cnhf
c3VibWl0X3RpbWVyLCANCj4gK3J4X3VyYl9zdWJtaXRfdGltZXJfaGFuZGxlciwgQ0xPQ0tfTU9O
T1RPTklDLCBIUlRJTUVSX01PREVfUkVMKTsNCj4gKw0KPiAgCXJldHVybiAwOw0KPiAgDQo+ICBl
cnJfc3VibWl0Og0KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDlr
L2hpZl91c2IuaCANCj4gYi9kcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoOWsvaGlmX3VzYi5o
DQo+IGluZGV4IDUxNDk2ZTcuLjU2ZDZiZTggMTAwNjQ0DQo+IC0tLSBhL2RyaXZlcnMvbmV0L3dp
cmVsZXNzL2F0aC9hdGg5ay9oaWZfdXNiLmgNCj4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3Mv
YXRoL2F0aDlrL2hpZl91c2IuaA0KPiBAQCAtOTgsOSArOTgsMTQgQEAgc3RydWN0IGhpZl9kZXZp
Y2VfdXNiIHsNCj4gIAlzdHJ1Y3QgaGlmX3VzYl90eCB0eDsNCj4gIAlzdHJ1Y3QgdXNiX2FuY2hv
ciByZWdvdXRfc3VibWl0dGVkOw0KPiAgCXN0cnVjdCB1c2JfYW5jaG9yIHJ4X3N1Ym1pdHRlZDsN
Cj4gKwlzdHJ1Y3QgdXNiX2FuY2hvciByeF9kZWxheWVkX3N1Ym1pdHRlZDsgLyogZGVsYXllZCBz
dWJtaXQgYW5jaG9yICovDQo+ICAJc3RydWN0IHVzYl9hbmNob3IgcmVnX2luX3N1Ym1pdHRlZDsN
Cj4gIAlzdHJ1Y3QgdXNiX2FuY2hvciBtZ210X3N1Ym1pdHRlZDsNCj4gIAlzdHJ1Y3Qgc2tfYnVm
ZiAqcmVtYWluX3NrYjsNCj4gKw0KPiArCXN0cnVjdCB0YXNrbGV0X2hydGltZXIgIHJ4X3N1Ym1p
dF90aW1lcjsvKiBkZWxheWVkIHN1Ym1pdCBocnRpbWVyICovDQo+ICsJYXRvbWljX3QgIHJ4X3Vy
Yl9zdWJtaXRfZGVsYXk7IC8qdXMqLw0KPiArDQo+ICAJY29uc3QgY2hhciAqZndfbmFtZTsNCj4g
IAlpbnQgcnhfcmVtYWluX2xlbjsNCj4gIAlpbnQgcnhfcGt0X2xlbjsNCj4gZGlmZiAtLWdpdCBh
L2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg5ay9odGMuaCANCj4gYi9kcml2ZXJzL25ldC93
aXJlbGVzcy9hdGgvYXRoOWsvaHRjLmgNCj4gaW5kZXggOWRkZTI2NS4uNDUzZDBhOCAxMDA2NDQN
Cj4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDlrL2h0Yy5oDQo+ICsrKyBiL2Ry
aXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg5ay9odGMuaA0KPiBAQCAtMzMxLDYgKzMzMSwxMCBA
QCBzdGF0aWMgaW5saW5lIHN0cnVjdCBhdGg5a19odGNfdHhfY3RsIA0KPiAqSFRDX1NLQl9DQihz
dHJ1Y3Qgc2tfYnVmZiAqc2tiKQ0KPiAgDQo+ICAjZGVmaW5lIFRYX1FTVEFUX0lOQyhxKSAocHJp
di0+ZGVidWcudHhfc3RhdHMucXVldWVfc3RhdHNbcV0rKykNCj4gIA0KPiArI2RlZmluZSBUQVNL
TEVUUlhfU1RBVF9JTkMoYykgDQo+ICsoaGlmX2Rldi0+aHRjX2hhbmRsZS0+ZHJ2X3ByaXYtPmRl
YnVnLnRhc2tsZXRyeF9zdGF0cy5jKyspDQo+ICsjZGVmaW5lIFRBU0tMRVRSWF9TVEFUX0FERChj
LCBhKSANCj4gKyhoaWZfZGV2LT5odGNfaGFuZGxlLT5kcnZfcHJpdi0+ZGVidWcudGFza2xldHJ4
X3N0YXRzLmMgKz0gYSkgI2RlZmluZSANCj4gK1RBU0tMRVRSWF9TVEFUX1NFVChjLCBhKSANCj4g
KyhoaWZfZGV2LT5odGNfaGFuZGxlLT5kcnZfcHJpdi0+ZGVidWcudGFza2xldHJ4X3N0YXRzLmMg
PSBhKQ0KPiArDQo+ICB2b2lkIGF0aDlrX2h0Y19lcnJfc3RhdF9yeChzdHJ1Y3QgYXRoOWtfaHRj
X3ByaXYgKnByaXYsDQo+ICAJCQkgICBzdHJ1Y3QgYXRoX3J4X3N0YXR1cyAqcnMpOw0KPiAgDQo+
IEBAIC0zNTIsMTEgKzM1NiwyMCBAQCBzdHJ1Y3QgYXRoX3NrYnJ4X3N0YXRzIHsNCj4gIAl1MzIg
c2tiX2Ryb3BwZWQ7DQo+ICB9Ow0KPiAgDQo+ICtzdHJ1Y3QgYXRoX3Rhc2tsZXRyeF9zdGF0cyB7
DQo+ICsJdTMyIHRhc2tsZXRyeF9sb29wdGltZXM7DQo+ICsJdTMyIHRhc2tsZXRyeF9oaWdod2F0
ZXI7DQo+ICsJdTMyIHRhc2tsZXRyeF9sb3d3YXRlcjsNCj4gKwl1MzIgdGFza2xldHJ4X3dhdGVy
bWFya190cmlnZ2VyZWQ7DQo+ICsJdTMyIHRhc2tsZXRyeF91cmJfc3VibWl0X2RlbGF5Ow0KPiAr
fTsNCj4gKw0KPiAgc3RydWN0IGF0aDlrX2RlYnVnIHsNCj4gIAlzdHJ1Y3QgZGVudHJ5ICpkZWJ1
Z2ZzX3BoeTsNCj4gIAlzdHJ1Y3QgYXRoX3R4X3N0YXRzIHR4X3N0YXRzOw0KPiAgCXN0cnVjdCBh
dGhfcnhfc3RhdHMgcnhfc3RhdHM7DQo+ICAJc3RydWN0IGF0aF9za2JyeF9zdGF0cyBza2JyeF9z
dGF0czsNCj4gKwlzdHJ1Y3QgYXRoX3Rhc2tsZXRyeF9zdGF0cyB0YXNrbGV0cnhfc3RhdHM7DQo+
ICB9Ow0KPiAgDQo+ICB2b2lkIGF0aDlrX2h0Y19nZXRfZXRfc3RyaW5ncyhzdHJ1Y3QgaWVlZTgw
MjExX2h3ICpodywgZGlmZiAtLWdpdCANCj4gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRo
OWsvaHRjX2Rydl9kZWJ1Zy5jIA0KPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg5ay9o
dGNfZHJ2X2RlYnVnLmMNCj4gaW5kZXggOGNlZjFlZC4uN2M4MzIyZSAxMDA2NDQNCj4gLS0tIGEv
ZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDlrL2h0Y19kcnZfZGVidWcuYw0KPiArKysgYi9k
cml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoOWsvaHRjX2Rydl9kZWJ1Zy5jDQo+IEBAIC0yODYs
NiArMjg2LDUxIEBAIHN0YXRpYyBjb25zdCBzdHJ1Y3QgZmlsZV9vcGVyYXRpb25zIGZvcHNfc2ti
X3J4ID0gew0KPiAgCS5sbHNlZWsgPSBkZWZhdWx0X2xsc2VlaywNCj4gIH07DQo+ICANCj4gK3N0
YXRpYyBzc2l6ZV90IHJlYWRfZmlsZV90YXNrbGV0X3J4KHN0cnVjdCBmaWxlICpmaWxlLCBjaGFy
IF9fdXNlciAqdXNlcl9idWYsDQo+ICsJCQkJICAgIHNpemVfdCBjb3VudCwgbG9mZl90ICpwcG9z
KQ0KPiArew0KPiArCXN0cnVjdCBhdGg5a19odGNfcHJpdiAqcHJpdiA9IGZpbGUtPnByaXZhdGVf
ZGF0YTsNCj4gKwljaGFyICpidWY7DQo+ICsJdW5zaWduZWQgaW50IGxlbiA9IDAsIHNpemUgPSAx
NTAwOw0KPiArCXNzaXplX3QgcmV0dmFsID0gMDsNCj4gKw0KPiArCWJ1ZiA9IGt6YWxsb2Moc2l6
ZSwgR0ZQX0tFUk5FTCk7DQo+ICsJaWYgKGJ1ZiA9PSBOVUxMKQ0KPiArCQlyZXR1cm4gLUVOT01F
TTsNCj4gKw0KPiArCWxlbiArPSBzY25wcmludGYoYnVmICsgbGVuLCBzaXplIC0gbGVuLA0KPiAr
CQkJIiUyMHMgOiAlMTB1XG4iLCAiTG9vcCB0aW1lcyIsDQo+ICsJCQlwcml2LT5kZWJ1Zy50YXNr
bGV0cnhfc3RhdHMudGFza2xldHJ4X2xvb3B0aW1lcyk7DQo+ICsJbGVuICs9IHNjbnByaW50Zihi
dWYgKyBsZW4sIHNpemUgLSBsZW4sDQo+ICsJCQkiJTIwcyA6ICUxMHVcbiIsICJIaWdoIHdhdGVy
bWFyayIsDQo+ICsJCQlwcml2LT5kZWJ1Zy50YXNrbGV0cnhfc3RhdHMudGFza2xldHJ4X2hpZ2h3
YXRlcik7DQo+ICsJbGVuICs9IHNjbnByaW50ZihidWYgKyBsZW4sIHNpemUgLSBsZW4sDQo+ICsJ
CQkiJTIwcyA6ICUxMHVcbiIsICJMb3cgd2F0ZXJtYXJrIiwNCj4gKwkJCXByaXYtPmRlYnVnLnRh
c2tsZXRyeF9zdGF0cy50YXNrbGV0cnhfbG93d2F0ZXIpOw0KPiArDQo+ICsJbGVuICs9IHNjbnBy
aW50ZihidWYgKyBsZW4sIHNpemUgLSBsZW4sDQo+ICsJCQkiJTIwcyA6ICUxMHVcbiIsICJXTSB0
cmlnZ2VyZWQiLA0KPiArCQkJcHJpdi0+ZGVidWcudGFza2xldHJ4X3N0YXRzLnRhc2tsZXRyeF93
YXRlcm1hcmtfdHJpZ2dlcmVkKTsNCj4gKw0KPiArCWxlbiArPSBzY25wcmludGYoYnVmICsgbGVu
LCBzaXplIC0gbGVuLA0KPiArCQkJIiUyMHMgOiAlMTB1XG4iLCAiVVJCIGRlbGF5IiwNCj4gKwkJ
CXByaXYtPmRlYnVnLnRhc2tsZXRyeF9zdGF0cy50YXNrbGV0cnhfdXJiX3N1Ym1pdF9kZWxheSk7
DQo+ICsJaWYgKGxlbiA+IHNpemUpDQo+ICsJCWxlbiA9IHNpemU7DQo+ICsNCj4gKwlyZXR2YWwg
PSBzaW1wbGVfcmVhZF9mcm9tX2J1ZmZlcih1c2VyX2J1ZiwgY291bnQsIHBwb3MsIGJ1ZiwgbGVu
KTsNCj4gKwlrZnJlZShidWYpOw0KPiArDQo+ICsJcmV0dXJuIHJldHZhbDsNCj4gK30NCj4gKw0K
PiArc3RhdGljIGNvbnN0IHN0cnVjdCBmaWxlX29wZXJhdGlvbnMgZm9wc190YXNrbGV0X3J4ID0g
ew0KPiArCS5yZWFkID0gcmVhZF9maWxlX3Rhc2tsZXRfcngsDQo+ICsJLm9wZW4gPSBzaW1wbGVf
b3BlbiwNCj4gKwkub3duZXIgPSBUSElTX01PRFVMRSwNCj4gKwkubGxzZWVrID0gZGVmYXVsdF9s
bHNlZWssDQo+ICt9Ow0KPiArDQo+ICBzdGF0aWMgc3NpemVfdCByZWFkX2ZpbGVfc2xvdChzdHJ1
Y3QgZmlsZSAqZmlsZSwgY2hhciBfX3VzZXIgKnVzZXJfYnVmLA0KPiAgCQkJICAgICAgc2l6ZV90
IGNvdW50LCBsb2ZmX3QgKnBwb3MpDQo+ICB7DQo+IEBAIC01MTgsNyArNTYzLDExIEBAIGludCBh
dGg5a19odGNfaW5pdF9kZWJ1ZyhzdHJ1Y3QgYXRoX2h3ICphaCkNCj4gIAlkZWJ1Z2ZzX2NyZWF0
ZV9maWxlKCJza2JfcngiLCBTX0lSVVNSLCBwcml2LT5kZWJ1Zy5kZWJ1Z2ZzX3BoeSwNCj4gIAkJ
CSAgICBwcml2LCAmZm9wc19za2JfcngpOw0KPiAgDQo+ICsJZGVidWdmc19jcmVhdGVfZmlsZSgi
dGFza2xldF9yeCIsIFNfSVJVU1IsIHByaXYtPmRlYnVnLmRlYnVnZnNfcGh5LA0KPiArCQkJICAg
IHByaXYsICZmb3BzX3Rhc2tsZXRfcngpOw0KPiArDQo+ICAJYXRoOWtfY21uX2RlYnVnX3JlY3Yo
cHJpdi0+ZGVidWcuZGVidWdmc19waHksIA0KPiAmcHJpdi0+ZGVidWcucnhfc3RhdHMpOw0KPiAr
DQo+ICAJYXRoOWtfY21uX2RlYnVnX3BoeV9lcnIocHJpdi0+ZGVidWcuZGVidWdmc19waHksIA0K
PiAmcHJpdi0+ZGVidWcucnhfc3RhdHMpOw0KPiAgDQo+ICAJZGVidWdmc19jcmVhdGVfZmlsZSgi
c2xvdCIsIFNfSVJVU1IsIHByaXYtPmRlYnVnLmRlYnVnZnNfcGh5LCBkaWZmIA0KPiAtLWdpdCBh
L2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg5ay9odGNfZHJ2X3R4cnguYyANCj4gYi9kcml2
ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoOWsvaHRjX2Rydl90eHJ4LmMNCj4gaW5kZXggYTBmNThl
Mi4uZjVlNjIxNyAxMDA2NDQNCj4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDlr
L2h0Y19kcnZfdHhyeC5jDQo+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg5ay9o
dGNfZHJ2X3R4cnguYw0KPiBAQCAtMTA2MSw3ICsxMDYxLDI4IEBAIHZvaWQgYXRoOWtfcnhfdGFz
a2xldCh1bnNpZ25lZCBsb25nIGRhdGEpDQo+ICAJdW5zaWduZWQgbG9uZyBmbGFnczsNCj4gIAlz
dHJ1Y3QgaWVlZTgwMjExX2hkciAqaGRyOw0KPiAgDQo+ICsJLyogYWRkIGZvciBhZGFwdGl2ZSBm
bG93IGNvbnRyb2wqLw0KPiArCWludCBsb29wdGltZXMgPSAwOw0KPiArCWludCBoaWdod2F0ZXJt
YXJrID0gQVRIOUtfSFRDX1JYQlVGKjMvNDsNCj4gKwlpbnQgbG93d2F0ZXJtYXJrID0gQVRIOUtf
SFRDX1JYQlVGLzQ7DQo+ICsJdW5zaWduZWQgaW50IGRlbGF5ID0gMDsNCj4gKw0KPiArCXN0cnVj
dCBodGNfdGFyZ2V0ICpodGMgPSBwcml2LT5odGM7DQo+ICsJc3RydWN0IGhpZl9kZXZpY2VfdXNi
ICpoaWZfZGV2ID0gaHRjLT5oaWZfZGV2Ow0KPiArDQo+ICsJVEFTS0xFVFJYX1NUQVRfU0VUKHRh
c2tsZXRyeF9oaWdod2F0ZXIsIGhpZ2h3YXRlcm1hcmspOw0KPiArCVRBU0tMRVRSWF9TVEFUX1NF
VCh0YXNrbGV0cnhfbG93d2F0ZXIsIGxvd3dhdGVybWFyayk7DQo+ICsNCj4gIAlkbyB7DQo+ICsJ
CWxvb3B0aW1lcysrOw0KPiArCQlUQVNLTEVUUlhfU1RBVF9TRVQodGFza2xldHJ4X2xvb3B0aW1l
cywgbG9vcHRpbWVzKTsNCj4gKwkJaWYgKGxvb3B0aW1lcyA+IGhpZ2h3YXRlcm1hcmspIHsNCj4g
KwkJCWRlbGF5ID0gbG9vcHRpbWVzKjEwOw0KPiArCQkJYXRvbWljX3NldCgmaGlmX2Rldi0+cnhf
dXJiX3N1Ym1pdF9kZWxheSwgZGVsYXkpOw0KPiArCQkJVEFTS0xFVFJYX1NUQVRfSU5DKHRhc2ts
ZXRyeF93YXRlcm1hcmtfdHJpZ2dlcmVkKTsNCj4gKwkJCVRBU0tMRVRSWF9TVEFUX1NFVCh0YXNr
bGV0cnhfdXJiX3N1Ym1pdF9kZWxheSwgZGVsYXkpOw0KPiArCQl9DQo+ICsNCj4gIAkJc3Bpbl9s
b2NrX2lycXNhdmUoJnByaXYtPnJ4LnJ4YnVmbG9jaywgZmxhZ3MpOw0KPiAgCQlsaXN0X2Zvcl9l
YWNoX2VudHJ5KHRtcF9idWYsICZwcml2LT5yeC5yeGJ1ZiwgbGlzdCkgew0KPiAgCQkJaWYgKHRt
cF9idWYtPmluX3Byb2Nlc3MpIHsNCj4gQEAgLTEwNzIsNiArMTA5MywxMSBAQCB2b2lkIGF0aDlr
X3J4X3Rhc2tsZXQodW5zaWduZWQgbG9uZyBkYXRhKQ0KPiAgDQo+ICAJCWlmIChyeGJ1ZiA9PSBO
VUxMKSB7DQo+ICAJCQlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZwcml2LT5yeC5yeGJ1ZmxvY2ss
IGZsYWdzKTsNCj4gKwkJCWlmIChsb29wdGltZXMgPCBsb3d3YXRlcm1hcmspIHsNCj4gKwkJCQlh
dG9taWNfc2V0KCZoaWZfZGV2LT5yeF91cmJfc3VibWl0X2RlbGF5LCAwKTsNCj4gKwkJCQlUQVNL
TEVUUlhfU1RBVF9TRVQodGFza2xldHJ4X3VyYl9zdWJtaXRfZGVsYXksIDApOw0KPiArCQkJfQ0K
PiArDQo+ICAJCQlicmVhazsNCj4gIAkJfQ0KPiAgDQo+IA0KDQoNCi0tDQpSZWdhcmRzLA0KT2xl
a3Npag0KDQo=

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

* 答复: [ath9k-devel] [PATCH] Repair soft lockup with monitor mode of ath9k_htc card
@ 2015-01-30 10:24     ` 郑玉伟
  0 siblings, 0 replies; 10+ messages in thread
From: 郑玉伟 @ 2015-01-30 10:24 UTC (permalink / raw)
  To: Oleksij Rempel, linux-kernel, ath9k-devel, linux-wireless, kvalo,
	ath9k-devel
  Cc: netdev

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 13264 bytes --]

Sorry, the patch ruined by the mail editor, I will send the patch with another mail account witch support smtp. 

I use tasklet_hrtimer_start for delayed submit, and the hrtimer callback function is excuted in the lower priority than normal tasklet. (TASKLET_SOFTIRQ 5, HRTIMER_SOFTIRQ 7 )

The hrtimer mode has been tested several weeks.  So I select this way currently.


-----邮件原件-----
发件人: Oleksij Rempel [mailto:linux@rempel-privat.de] 
发送时间: 2015年1月29日 18:52
收件人: 郑玉伟; linux-kernel@vger.kernel.org; ath9k-devel@venema.h4ckr.net; linux-wireless@vger.kernel.org; kvalo@codeaurora.org; ath9k-devel@qca.qualcomm.com
抄送: netdev@vger.kernel.org
主题: Re: [ath9k-devel] [PATCH] Repair soft lockup with monitor mode of ath9k_htc card

Am 29.01.2015 um 05:09 schrieb zhengyuwei@360.cn:
> From: Yuwei Zheng <zhengyuwei@360.cn>
> 
> In the environment with heavy wifi traffic, set the ar9271 into 
> monitor mode, will trigger a deadloop panic.
> 
> The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and 
> ath9k_rx_tasklet excute on the soft irq context. In other words, the 
> ath9k_hif_usb_rx_cb have more chance to excute than ath9k_rx_tasklet.  
> So in the worst condition,  the rx.rxbuf receive list is always full, and the do {}while(true) loop will not be break. The kernel get a soft lockup panic.
>   
> [59011.007210] BUG: soft lockup - CPU#0 stuck for 23s! 
> [kworker/0:0:30609]
> [59011.030560] BUG: scheduling while atomic: 
> kworker/0:0/30609/0x40010100 [59013.804486] BUG: scheduling while 
> atomic: kworker/0:0/30609/0x40010100 [59013.858522] Kernel panic - not 
> syncing: softlockup: hung tasks
> 
> [59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
> [59014.046834] bc20:                                                       de57b950 60000113
> [59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 
> dc7bb440 df4bbcd0 00000000 [59014.072337] bc60: de57b950 60000113 
> df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff [59014.085233] 
> [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] 
> (_raw_spin_unlock_irqrestore+0xc/0x10)
> [59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) 
> from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) 
> [59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) 
> from [<c0036d23>] (tasklet_action+0x3b/0x98) [59014.134132] 
> [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] 
> (__do_softirq+0x99/0x16c) [59014.147784] [<c0036709>] 
> (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c) 
> [59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] 
> (handle_IRQ+0x37/0x78) [59014.173124] [<c000cfc3>] 
> (handle_IRQ+0x37/0x78) from [<c00085df>] 
> (omap3_intc_handle_irq+0x5f/0x68) [59014.187225] [<c00085df>] 
> (omap3_intc_handle_irq+0x5f/0x68) from 
> [<c04c28db>](__irq_svc+0x3b/0x5c)
> 
> This bug can be see with low performance board, such as uniprocessor beagle bone board.
> Signed-off-by: Yuwei Zheng <zhengyuwei@360.cn>
> 
> ---
>  drivers/net/wireless/ath/ath9k/hif_usb.c       | 53 ++++++++++++++++++++++----
>  drivers/net/wireless/ath/ath9k/hif_usb.h       |  5 +++
>  drivers/net/wireless/ath/ath9k/htc.h           | 13 +++++++
>  drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 49 
> ++++++++++++++++++++++++  
> drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 26 +++++++++++++
>  5 files changed, 139 insertions(+), 7 deletions(-)

First of all, thank you for you work! :D

Please run ./scripts/checkpatch.pl yourpatch_path i get:
total: 139 errors, 12 warnings, 2 checks, 231 lines checked

You use tasklet_hrtimer_start. So far i know, there is no this kind of hrtimer which is actually hidden behind this word on this SoC.
Especially if requested value is any way in 1 millisecond range you probably can and should use normal priority tasklet. (correct me if i'm
wrong)

> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c 
> b/drivers/net/wireless/ath/ath9k/hif_usb.c
> index 8e7153b..febea5e 100644
> --- a/drivers/net/wireless/ath/ath9k/hif_usb.c
> +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
> @@ -658,7 +658,6 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
>  	default:
>  		goto resubmit;
>  	}
> -
>  	if (likely(urb->actual_length != 0)) {
>  		skb_put(skb, urb->actual_length);
>  		ath9k_hif_usb_rx_stream(hif_dev, skb); @@ -667,12 +666,18 @@ static 
> void ath9k_hif_usb_rx_cb(struct urb *urb)
>  resubmit:
>  	skb_reset_tail_pointer(skb);
>  	skb_trim(skb, 0);
> -
> -	usb_anchor_urb(urb, &hif_dev->rx_submitted);
> -	ret = usb_submit_urb(urb, GFP_ATOMIC);
> -	if (ret) {
> -		usb_unanchor_urb(urb);
> -		goto free;
> +	if (atomic_read(&hif_dev->rx_urb_submit_delay) > 0) {
> +		usb_anchor_urb(urb, &hif_dev->rx_delayed_submitted);
> +		ret = tasklet_hrtimer_start(&hif_dev->rx_submit_timer,
> +					    ktime_set(0, atomic_read(&hif_dev->rx_urb_submit_delay)*1000),
> +					    HRTIMER_MODE_REL);
> +	} else {
> +		usb_anchor_urb(urb, &hif_dev->rx_submitted);
> +		ret = usb_submit_urb(urb, GFP_ATOMIC);
> +		if (ret) {
> +			usb_unanchor_urb(urb);
> +			goto free;
> +		}
>  	}
>  
>  	return;
> @@ -818,9 +823,37 @@ err:
>  	return -ENOMEM;
>  }
>  
> +static enum hrtimer_restart rx_urb_submit_timer_handler(struct 
> +hrtimer *me) {
> +	struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
> +	struct  hif_device_usb *hif_dev = container_of(thr, struct hif_device_usb, rx_submit_timer);
> +	struct urb *urb = NULL;
> +	struct sk_buff *skb = NULL;
> +	int ret;
> +
> +	while (true) {
> +		urb = usb_get_from_anchor(&hif_dev->rx_delayed_submitted);
> +		if (urb != NULL) {
> +			skb = (struct sk_buff *)urb->context;
> +			ret = usb_submit_urb(urb, GFP_ATOMIC);
> +			if (ret != -EBUSY) {
> +				usb_unanchor_urb(urb);
> +				dev_kfree_skb_any(skb);
> +				urb->context = NULL;
> +			}
> +		} else {
> +			break;
> +		}
> +	}
> +
> +	return HRTIMER_NORESTART;
> +}
> +
>  static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb 
> *hif_dev)  {
>  	usb_kill_anchored_urbs(&hif_dev->rx_submitted);
> +	usb_kill_anchored_urbs(&hif_dev->rx_delayed_submitted);
> +	tasklet_hrtimer_cancel(&hif_dev->rx_submit_timer);
>  }
>  
>  static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb 
> *hif_dev) @@ -830,6 +863,8 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
>  	int i, ret;
>  
>  	init_usb_anchor(&hif_dev->rx_submitted);
> +	init_usb_anchor(&hif_dev->rx_delayed_submitted);
> +
>  	spin_lock_init(&hif_dev->rx_lock);
>  
>  	for (i = 0; i < MAX_RX_URB_NUM; i++) { @@ -871,6 +906,10 @@ static 
> int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
>  		usb_free_urb(urb);
>  	}
>  
> +	/* add for flow control*/
> +	atomic_set(&hif_dev->rx_urb_submit_delay, 0);
> +	tasklet_hrtimer_init(&hif_dev->rx_submit_timer, 
> +rx_urb_submit_timer_handler, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +
>  	return 0;
>  
>  err_submit:
> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h 
> b/drivers/net/wireless/ath/ath9k/hif_usb.h
> index 51496e7..56d6be8 100644
> --- a/drivers/net/wireless/ath/ath9k/hif_usb.h
> +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
> @@ -98,9 +98,14 @@ struct hif_device_usb {
>  	struct hif_usb_tx tx;
>  	struct usb_anchor regout_submitted;
>  	struct usb_anchor rx_submitted;
> +	struct usb_anchor rx_delayed_submitted; /* delayed submit anchor */
>  	struct usb_anchor reg_in_submitted;
>  	struct usb_anchor mgmt_submitted;
>  	struct sk_buff *remain_skb;
> +
> +	struct tasklet_hrtimer  rx_submit_timer;/* delayed submit hrtimer */
> +	atomic_t  rx_urb_submit_delay; /*us*/
> +
>  	const char *fw_name;
>  	int rx_remain_len;
>  	int rx_pkt_len;
> diff --git a/drivers/net/wireless/ath/ath9k/htc.h 
> b/drivers/net/wireless/ath/ath9k/htc.h
> index 9dde265..453d0a8 100644
> --- a/drivers/net/wireless/ath/ath9k/htc.h
> +++ b/drivers/net/wireless/ath/ath9k/htc.h
> @@ -331,6 +331,10 @@ static inline struct ath9k_htc_tx_ctl 
> *HTC_SKB_CB(struct sk_buff *skb)
>  
>  #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
>  
> +#define TASKLETRX_STAT_INC(c) 
> +(hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c++)
> +#define TASKLETRX_STAT_ADD(c, a) 
> +(hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c += a) #define 
> +TASKLETRX_STAT_SET(c, a) 
> +(hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c = a)
> +
>  void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
>  			   struct ath_rx_status *rs);
>  
> @@ -352,11 +356,20 @@ struct ath_skbrx_stats {
>  	u32 skb_dropped;
>  };
>  
> +struct ath_taskletrx_stats {
> +	u32 taskletrx_looptimes;
> +	u32 taskletrx_highwater;
> +	u32 taskletrx_lowwater;
> +	u32 taskletrx_watermark_triggered;
> +	u32 taskletrx_urb_submit_delay;
> +};
> +
>  struct ath9k_debug {
>  	struct dentry *debugfs_phy;
>  	struct ath_tx_stats tx_stats;
>  	struct ath_rx_stats rx_stats;
>  	struct ath_skbrx_stats skbrx_stats;
> +	struct ath_taskletrx_stats taskletrx_stats;
>  };
>  
>  void ath9k_htc_get_et_strings(struct ieee80211_hw *hw, diff --git 
> a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c 
> b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> index 8cef1ed..7c8322e 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> @@ -286,6 +286,51 @@ static const struct file_operations fops_skb_rx = {
>  	.llseek = default_llseek,
>  };
>  
> +static ssize_t read_file_tasklet_rx(struct file *file, char __user *user_buf,
> +				    size_t count, loff_t *ppos)
> +{
> +	struct ath9k_htc_priv *priv = file->private_data;
> +	char *buf;
> +	unsigned int len = 0, size = 1500;
> +	ssize_t retval = 0;
> +
> +	buf = kzalloc(size, GFP_KERNEL);
> +	if (buf == NULL)
> +		return -ENOMEM;
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "Loop times",
> +			priv->debug.taskletrx_stats.taskletrx_looptimes);
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "High watermark",
> +			priv->debug.taskletrx_stats.taskletrx_highwater);
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "Low watermark",
> +			priv->debug.taskletrx_stats.taskletrx_lowwater);
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "WM triggered",
> +			priv->debug.taskletrx_stats.taskletrx_watermark_triggered);
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "URB delay",
> +			priv->debug.taskletrx_stats.taskletrx_urb_submit_delay);
> +	if (len > size)
> +		len = size;
> +
> +	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
> +	kfree(buf);
> +
> +	return retval;
> +}
> +
> +static const struct file_operations fops_tasklet_rx = {
> +	.read = read_file_tasklet_rx,
> +	.open = simple_open,
> +	.owner = THIS_MODULE,
> +	.llseek = default_llseek,
> +};
> +
>  static ssize_t read_file_slot(struct file *file, char __user *user_buf,
>  			      size_t count, loff_t *ppos)
>  {
> @@ -518,7 +563,11 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
>  	debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
>  			    priv, &fops_skb_rx);
>  
> +	debugfs_create_file("tasklet_rx", S_IRUSR, priv->debug.debugfs_phy,
> +			    priv, &fops_tasklet_rx);
> +
>  	ath9k_cmn_debug_recv(priv->debug.debugfs_phy, 
> &priv->debug.rx_stats);
> +
>  	ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, 
> &priv->debug.rx_stats);
>  
>  	debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, diff 
> --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c 
> b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> index a0f58e2..f5e6217 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> @@ -1061,7 +1061,28 @@ void ath9k_rx_tasklet(unsigned long data)
>  	unsigned long flags;
>  	struct ieee80211_hdr *hdr;
>  
> +	/* add for adaptive flow control*/
> +	int looptimes = 0;
> +	int highwatermark = ATH9K_HTC_RXBUF*3/4;
> +	int lowwatermark = ATH9K_HTC_RXBUF/4;
> +	unsigned int delay = 0;
> +
> +	struct htc_target *htc = priv->htc;
> +	struct hif_device_usb *hif_dev = htc->hif_dev;
> +
> +	TASKLETRX_STAT_SET(taskletrx_highwater, highwatermark);
> +	TASKLETRX_STAT_SET(taskletrx_lowwater, lowwatermark);
> +
>  	do {
> +		looptimes++;
> +		TASKLETRX_STAT_SET(taskletrx_looptimes, looptimes);
> +		if (looptimes > highwatermark) {
> +			delay = looptimes*10;
> +			atomic_set(&hif_dev->rx_urb_submit_delay, delay);
> +			TASKLETRX_STAT_INC(taskletrx_watermark_triggered);
> +			TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, delay);
> +		}
> +
>  		spin_lock_irqsave(&priv->rx.rxbuflock, flags);
>  		list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
>  			if (tmp_buf->in_process) {
> @@ -1072,6 +1093,11 @@ void ath9k_rx_tasklet(unsigned long data)
>  
>  		if (rxbuf == NULL) {
>  			spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
> +			if (looptimes < lowwatermark) {
> +				atomic_set(&hif_dev->rx_urb_submit_delay, 0);
> +				TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, 0);
> +			}
> +
>  			break;
>  		}
>  
> 


--
Regards,
Oleksij

ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

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

* 答复: [ath9k-devel] [PATCH] Repair soft lockup with monitor mode of ath9k_htc card
@ 2015-01-30 10:24     ` 郑玉伟
  0 siblings, 0 replies; 10+ messages in thread
From: 郑玉伟 @ 2015-01-30 10:24 UTC (permalink / raw)
  To: Oleksij Rempel, linux-kernel, ath9k-devel, linux-wireless, kvalo,
	ath9k-devel
  Cc: netdev

Sorry, the patch ruined by the mail editor, I will send the patch with another mail account witch support smtp. 

I use tasklet_hrtimer_start for delayed submit, and the hrtimer callback function is excuted in the lower priority than normal tasklet. (TASKLET_SOFTIRQ 5, HRTIMER_SOFTIRQ 7 )

The hrtimer mode has been tested several weeks.  So I select this way currently.


-----邮件原件-----
发件人: Oleksij Rempel [mailto:linux@rempel-privat.de] 
发送时间: 2015年1月29日 18:52
收件人: 郑玉伟; linux-kernel@vger.kernel.org; ath9k-devel@venema.h4ckr.net; linux-wireless@vger.kernel.org; kvalo@codeaurora.org; ath9k-devel@qca.qualcomm.com
抄送: netdev@vger.kernel.org
主题: Re: [ath9k-devel] [PATCH] Repair soft lockup with monitor mode of ath9k_htc card

Am 29.01.2015 um 05:09 schrieb zhengyuwei@360.cn:
> From: Yuwei Zheng <zhengyuwei@360.cn>
> 
> In the environment with heavy wifi traffic, set the ar9271 into 
> monitor mode, will trigger a deadloop panic.
> 
> The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and 
> ath9k_rx_tasklet excute on the soft irq context. In other words, the 
> ath9k_hif_usb_rx_cb have more chance to excute than ath9k_rx_tasklet.  
> So in the worst condition,  the rx.rxbuf receive list is always full, and the do {}while(true) loop will not be break. The kernel get a soft lockup panic.
>   
> [59011.007210] BUG: soft lockup - CPU#0 stuck for 23s! 
> [kworker/0:0:30609]
> [59011.030560] BUG: scheduling while atomic: 
> kworker/0:0/30609/0x40010100 [59013.804486] BUG: scheduling while 
> atomic: kworker/0:0/30609/0x40010100 [59013.858522] Kernel panic - not 
> syncing: softlockup: hung tasks
> 
> [59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
> [59014.046834] bc20:                                                       de57b950 60000113
> [59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 
> dc7bb440 df4bbcd0 00000000 [59014.072337] bc60: de57b950 60000113 
> df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff [59014.085233] 
> [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] 
> (_raw_spin_unlock_irqrestore+0xc/0x10)
> [59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) 
> from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) 
> [59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) 
> from [<c0036d23>] (tasklet_action+0x3b/0x98) [59014.134132] 
> [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] 
> (__do_softirq+0x99/0x16c) [59014.147784] [<c0036709>] 
> (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c) 
> [59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] 
> (handle_IRQ+0x37/0x78) [59014.173124] [<c000cfc3>] 
> (handle_IRQ+0x37/0x78) from [<c00085df>] 
> (omap3_intc_handle_irq+0x5f/0x68) [59014.187225] [<c00085df>] 
> (omap3_intc_handle_irq+0x5f/0x68) from 
> [<c04c28db>](__irq_svc+0x3b/0x5c)
> 
> This bug can be see with low performance board, such as uniprocessor beagle bone board.
> Signed-off-by: Yuwei Zheng <zhengyuwei@360.cn>
> 
> ---
>  drivers/net/wireless/ath/ath9k/hif_usb.c       | 53 ++++++++++++++++++++++----
>  drivers/net/wireless/ath/ath9k/hif_usb.h       |  5 +++
>  drivers/net/wireless/ath/ath9k/htc.h           | 13 +++++++
>  drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 49 
> ++++++++++++++++++++++++  
> drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 26 +++++++++++++
>  5 files changed, 139 insertions(+), 7 deletions(-)

First of all, thank you for you work! :D

Please run ./scripts/checkpatch.pl yourpatch_path i get:
total: 139 errors, 12 warnings, 2 checks, 231 lines checked

You use tasklet_hrtimer_start. So far i know, there is no this kind of hrtimer which is actually hidden behind this word on this SoC.
Especially if requested value is any way in 1 millisecond range you probably can and should use normal priority tasklet. (correct me if i'm
wrong)

> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c 
> b/drivers/net/wireless/ath/ath9k/hif_usb.c
> index 8e7153b..febea5e 100644
> --- a/drivers/net/wireless/ath/ath9k/hif_usb.c
> +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
> @@ -658,7 +658,6 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
>  	default:
>  		goto resubmit;
>  	}
> -
>  	if (likely(urb->actual_length != 0)) {
>  		skb_put(skb, urb->actual_length);
>  		ath9k_hif_usb_rx_stream(hif_dev, skb); @@ -667,12 +666,18 @@ static 
> void ath9k_hif_usb_rx_cb(struct urb *urb)
>  resubmit:
>  	skb_reset_tail_pointer(skb);
>  	skb_trim(skb, 0);
> -
> -	usb_anchor_urb(urb, &hif_dev->rx_submitted);
> -	ret = usb_submit_urb(urb, GFP_ATOMIC);
> -	if (ret) {
> -		usb_unanchor_urb(urb);
> -		goto free;
> +	if (atomic_read(&hif_dev->rx_urb_submit_delay) > 0) {
> +		usb_anchor_urb(urb, &hif_dev->rx_delayed_submitted);
> +		ret = tasklet_hrtimer_start(&hif_dev->rx_submit_timer,
> +					    ktime_set(0, atomic_read(&hif_dev->rx_urb_submit_delay)*1000),
> +					    HRTIMER_MODE_REL);
> +	} else {
> +		usb_anchor_urb(urb, &hif_dev->rx_submitted);
> +		ret = usb_submit_urb(urb, GFP_ATOMIC);
> +		if (ret) {
> +			usb_unanchor_urb(urb);
> +			goto free;
> +		}
>  	}
>  
>  	return;
> @@ -818,9 +823,37 @@ err:
>  	return -ENOMEM;
>  }
>  
> +static enum hrtimer_restart rx_urb_submit_timer_handler(struct 
> +hrtimer *me) {
> +	struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
> +	struct  hif_device_usb *hif_dev = container_of(thr, struct hif_device_usb, rx_submit_timer);
> +	struct urb *urb = NULL;
> +	struct sk_buff *skb = NULL;
> +	int ret;
> +
> +	while (true) {
> +		urb = usb_get_from_anchor(&hif_dev->rx_delayed_submitted);
> +		if (urb != NULL) {
> +			skb = (struct sk_buff *)urb->context;
> +			ret = usb_submit_urb(urb, GFP_ATOMIC);
> +			if (ret != -EBUSY) {
> +				usb_unanchor_urb(urb);
> +				dev_kfree_skb_any(skb);
> +				urb->context = NULL;
> +			}
> +		} else {
> +			break;
> +		}
> +	}
> +
> +	return HRTIMER_NORESTART;
> +}
> +
>  static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb 
> *hif_dev)  {
>  	usb_kill_anchored_urbs(&hif_dev->rx_submitted);
> +	usb_kill_anchored_urbs(&hif_dev->rx_delayed_submitted);
> +	tasklet_hrtimer_cancel(&hif_dev->rx_submit_timer);
>  }
>  
>  static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb 
> *hif_dev) @@ -830,6 +863,8 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
>  	int i, ret;
>  
>  	init_usb_anchor(&hif_dev->rx_submitted);
> +	init_usb_anchor(&hif_dev->rx_delayed_submitted);
> +
>  	spin_lock_init(&hif_dev->rx_lock);
>  
>  	for (i = 0; i < MAX_RX_URB_NUM; i++) { @@ -871,6 +906,10 @@ static 
> int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
>  		usb_free_urb(urb);
>  	}
>  
> +	/* add for flow control*/
> +	atomic_set(&hif_dev->rx_urb_submit_delay, 0);
> +	tasklet_hrtimer_init(&hif_dev->rx_submit_timer, 
> +rx_urb_submit_timer_handler, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +
>  	return 0;
>  
>  err_submit:
> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h 
> b/drivers/net/wireless/ath/ath9k/hif_usb.h
> index 51496e7..56d6be8 100644
> --- a/drivers/net/wireless/ath/ath9k/hif_usb.h
> +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
> @@ -98,9 +98,14 @@ struct hif_device_usb {
>  	struct hif_usb_tx tx;
>  	struct usb_anchor regout_submitted;
>  	struct usb_anchor rx_submitted;
> +	struct usb_anchor rx_delayed_submitted; /* delayed submit anchor */
>  	struct usb_anchor reg_in_submitted;
>  	struct usb_anchor mgmt_submitted;
>  	struct sk_buff *remain_skb;
> +
> +	struct tasklet_hrtimer  rx_submit_timer;/* delayed submit hrtimer */
> +	atomic_t  rx_urb_submit_delay; /*us*/
> +
>  	const char *fw_name;
>  	int rx_remain_len;
>  	int rx_pkt_len;
> diff --git a/drivers/net/wireless/ath/ath9k/htc.h 
> b/drivers/net/wireless/ath/ath9k/htc.h
> index 9dde265..453d0a8 100644
> --- a/drivers/net/wireless/ath/ath9k/htc.h
> +++ b/drivers/net/wireless/ath/ath9k/htc.h
> @@ -331,6 +331,10 @@ static inline struct ath9k_htc_tx_ctl 
> *HTC_SKB_CB(struct sk_buff *skb)
>  
>  #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
>  
> +#define TASKLETRX_STAT_INC(c) 
> +(hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c++)
> +#define TASKLETRX_STAT_ADD(c, a) 
> +(hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c += a) #define 
> +TASKLETRX_STAT_SET(c, a) 
> +(hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c = a)
> +
>  void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
>  			   struct ath_rx_status *rs);
>  
> @@ -352,11 +356,20 @@ struct ath_skbrx_stats {
>  	u32 skb_dropped;
>  };
>  
> +struct ath_taskletrx_stats {
> +	u32 taskletrx_looptimes;
> +	u32 taskletrx_highwater;
> +	u32 taskletrx_lowwater;
> +	u32 taskletrx_watermark_triggered;
> +	u32 taskletrx_urb_submit_delay;
> +};
> +
>  struct ath9k_debug {
>  	struct dentry *debugfs_phy;
>  	struct ath_tx_stats tx_stats;
>  	struct ath_rx_stats rx_stats;
>  	struct ath_skbrx_stats skbrx_stats;
> +	struct ath_taskletrx_stats taskletrx_stats;
>  };
>  
>  void ath9k_htc_get_et_strings(struct ieee80211_hw *hw, diff --git 
> a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c 
> b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> index 8cef1ed..7c8322e 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> @@ -286,6 +286,51 @@ static const struct file_operations fops_skb_rx = {
>  	.llseek = default_llseek,
>  };
>  
> +static ssize_t read_file_tasklet_rx(struct file *file, char __user *user_buf,
> +				    size_t count, loff_t *ppos)
> +{
> +	struct ath9k_htc_priv *priv = file->private_data;
> +	char *buf;
> +	unsigned int len = 0, size = 1500;
> +	ssize_t retval = 0;
> +
> +	buf = kzalloc(size, GFP_KERNEL);
> +	if (buf == NULL)
> +		return -ENOMEM;
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "Loop times",
> +			priv->debug.taskletrx_stats.taskletrx_looptimes);
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "High watermark",
> +			priv->debug.taskletrx_stats.taskletrx_highwater);
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "Low watermark",
> +			priv->debug.taskletrx_stats.taskletrx_lowwater);
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "WM triggered",
> +			priv->debug.taskletrx_stats.taskletrx_watermark_triggered);
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "URB delay",
> +			priv->debug.taskletrx_stats.taskletrx_urb_submit_delay);
> +	if (len > size)
> +		len = size;
> +
> +	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
> +	kfree(buf);
> +
> +	return retval;
> +}
> +
> +static const struct file_operations fops_tasklet_rx = {
> +	.read = read_file_tasklet_rx,
> +	.open = simple_open,
> +	.owner = THIS_MODULE,
> +	.llseek = default_llseek,
> +};
> +
>  static ssize_t read_file_slot(struct file *file, char __user *user_buf,
>  			      size_t count, loff_t *ppos)
>  {
> @@ -518,7 +563,11 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
>  	debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
>  			    priv, &fops_skb_rx);
>  
> +	debugfs_create_file("tasklet_rx", S_IRUSR, priv->debug.debugfs_phy,
> +			    priv, &fops_tasklet_rx);
> +
>  	ath9k_cmn_debug_recv(priv->debug.debugfs_phy, 
> &priv->debug.rx_stats);
> +
>  	ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, 
> &priv->debug.rx_stats);
>  
>  	debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, diff 
> --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c 
> b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> index a0f58e2..f5e6217 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> @@ -1061,7 +1061,28 @@ void ath9k_rx_tasklet(unsigned long data)
>  	unsigned long flags;
>  	struct ieee80211_hdr *hdr;
>  
> +	/* add for adaptive flow control*/
> +	int looptimes = 0;
> +	int highwatermark = ATH9K_HTC_RXBUF*3/4;
> +	int lowwatermark = ATH9K_HTC_RXBUF/4;
> +	unsigned int delay = 0;
> +
> +	struct htc_target *htc = priv->htc;
> +	struct hif_device_usb *hif_dev = htc->hif_dev;
> +
> +	TASKLETRX_STAT_SET(taskletrx_highwater, highwatermark);
> +	TASKLETRX_STAT_SET(taskletrx_lowwater, lowwatermark);
> +
>  	do {
> +		looptimes++;
> +		TASKLETRX_STAT_SET(taskletrx_looptimes, looptimes);
> +		if (looptimes > highwatermark) {
> +			delay = looptimes*10;
> +			atomic_set(&hif_dev->rx_urb_submit_delay, delay);
> +			TASKLETRX_STAT_INC(taskletrx_watermark_triggered);
> +			TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, delay);
> +		}
> +
>  		spin_lock_irqsave(&priv->rx.rxbuflock, flags);
>  		list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
>  			if (tmp_buf->in_process) {
> @@ -1072,6 +1093,11 @@ void ath9k_rx_tasklet(unsigned long data)
>  
>  		if (rxbuf == NULL) {
>  			spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
> +			if (looptimes < lowwatermark) {
> +				atomic_set(&hif_dev->rx_urb_submit_delay, 0);
> +				TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, 0);
> +			}
> +
>  			break;
>  		}
>  
> 


--
Regards,
Oleksij


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

* [ath9k-devel] 答复:  [PATCH] Repair soft lockup with monitor mode of ath9k_htc card
@ 2015-01-30 10:24     ` 郑玉伟
  0 siblings, 0 replies; 10+ messages in thread
From: 郑玉伟 @ 2015-01-30 10:24 UTC (permalink / raw)
  To: ath9k-devel

Sorry, the patch ruined by the mail editor, I will send the patch with another mail account witch support smtp. 

I use tasklet_hrtimer_start for delayed submit, and the hrtimer callback function is excuted in the lower priority than normal tasklet. (TASKLET_SOFTIRQ 5, HRTIMER_SOFTIRQ 7 )

The hrtimer mode has been tested several weeks.  So I select this way currently.


-----????-----
???: Oleksij Rempel [mailto:linux at rempel-privat.de] 
????: 2015?1?29? 18:52
???: ???; linux-kernel at vger.kernel.org; ath9k-devel at venema.h4ckr.net; linux-wireless at vger.kernel.org; kvalo at codeaurora.org; ath9k-devel at qca.qualcomm.com
??: netdev at vger.kernel.org
??: Re: [ath9k-devel] [PATCH] Repair soft lockup with monitor mode of ath9k_htc card

Am 29.01.2015 um 05:09 schrieb zhengyuwei at 360.cn:
> From: Yuwei Zheng <zhengyuwei@360.cn>
> 
> In the environment with heavy wifi traffic, set the ar9271 into 
> monitor mode, will trigger a deadloop panic.
> 
> The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and 
> ath9k_rx_tasklet excute on the soft irq context. In other words, the 
> ath9k_hif_usb_rx_cb have more chance to excute than ath9k_rx_tasklet.  
> So in the worst condition,  the rx.rxbuf receive list is always full, and the do {}while(true) loop will not be break. The kernel get a soft lockup panic.
>   
> [59011.007210] BUG: soft lockup - CPU#0 stuck for 23s! 
> [kworker/0:0:30609]
> [59011.030560] BUG: scheduling while atomic: 
> kworker/0:0/30609/0x40010100 [59013.804486] BUG: scheduling while 
> atomic: kworker/0:0/30609/0x40010100 [59013.858522] Kernel panic - not 
> syncing: softlockup: hung tasks
> 
> [59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
> [59014.046834] bc20:                                                       de57b950 60000113
> [59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 
> dc7bb440 df4bbcd0 00000000 [59014.072337] bc60: de57b950 60000113 
> df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff [59014.085233] 
> [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] 
> (_raw_spin_unlock_irqrestore+0xc/0x10)
> [59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) 
> from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) 
> [59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) 
> from [<c0036d23>] (tasklet_action+0x3b/0x98) [59014.134132] 
> [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] 
> (__do_softirq+0x99/0x16c) [59014.147784] [<c0036709>] 
> (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c) 
> [59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] 
> (handle_IRQ+0x37/0x78) [59014.173124] [<c000cfc3>] 
> (handle_IRQ+0x37/0x78) from [<c00085df>] 
> (omap3_intc_handle_irq+0x5f/0x68) [59014.187225] [<c00085df>] 
> (omap3_intc_handle_irq+0x5f/0x68) from 
> [<c04c28db>](__irq_svc+0x3b/0x5c)
> 
> This bug can be see with low performance board, such as uniprocessor beagle bone board.
> Signed-off-by: Yuwei Zheng <zhengyuwei@360.cn>
> 
> ---
>  drivers/net/wireless/ath/ath9k/hif_usb.c       | 53 ++++++++++++++++++++++----
>  drivers/net/wireless/ath/ath9k/hif_usb.h       |  5 +++
>  drivers/net/wireless/ath/ath9k/htc.h           | 13 +++++++
>  drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 49 
> ++++++++++++++++++++++++  
> drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 26 +++++++++++++
>  5 files changed, 139 insertions(+), 7 deletions(-)

First of all, thank you for you work! :D

Please run ./scripts/checkpatch.pl yourpatch_path i get:
total: 139 errors, 12 warnings, 2 checks, 231 lines checked

You use tasklet_hrtimer_start. So far i know, there is no this kind of hrtimer which is actually hidden behind this word on this SoC.
Especially if requested value is any way in 1 millisecond range you probably can and should use normal priority tasklet. (correct me if i'm
wrong)

> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c 
> b/drivers/net/wireless/ath/ath9k/hif_usb.c
> index 8e7153b..febea5e 100644
> --- a/drivers/net/wireless/ath/ath9k/hif_usb.c
> +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
> @@ -658,7 +658,6 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
>  	default:
>  		goto resubmit;
>  	}
> -
>  	if (likely(urb->actual_length != 0)) {
>  		skb_put(skb, urb->actual_length);
>  		ath9k_hif_usb_rx_stream(hif_dev, skb); @@ -667,12 +666,18 @@ static 
> void ath9k_hif_usb_rx_cb(struct urb *urb)
>  resubmit:
>  	skb_reset_tail_pointer(skb);
>  	skb_trim(skb, 0);
> -
> -	usb_anchor_urb(urb, &hif_dev->rx_submitted);
> -	ret = usb_submit_urb(urb, GFP_ATOMIC);
> -	if (ret) {
> -		usb_unanchor_urb(urb);
> -		goto free;
> +	if (atomic_read(&hif_dev->rx_urb_submit_delay) > 0) {
> +		usb_anchor_urb(urb, &hif_dev->rx_delayed_submitted);
> +		ret = tasklet_hrtimer_start(&hif_dev->rx_submit_timer,
> +					    ktime_set(0, atomic_read(&hif_dev->rx_urb_submit_delay)*1000),
> +					    HRTIMER_MODE_REL);
> +	} else {
> +		usb_anchor_urb(urb, &hif_dev->rx_submitted);
> +		ret = usb_submit_urb(urb, GFP_ATOMIC);
> +		if (ret) {
> +			usb_unanchor_urb(urb);
> +			goto free;
> +		}
>  	}
>  
>  	return;
> @@ -818,9 +823,37 @@ err:
>  	return -ENOMEM;
>  }
>  
> +static enum hrtimer_restart rx_urb_submit_timer_handler(struct 
> +hrtimer *me) {
> +	struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
> +	struct  hif_device_usb *hif_dev = container_of(thr, struct hif_device_usb, rx_submit_timer);
> +	struct urb *urb = NULL;
> +	struct sk_buff *skb = NULL;
> +	int ret;
> +
> +	while (true) {
> +		urb = usb_get_from_anchor(&hif_dev->rx_delayed_submitted);
> +		if (urb != NULL) {
> +			skb = (struct sk_buff *)urb->context;
> +			ret = usb_submit_urb(urb, GFP_ATOMIC);
> +			if (ret != -EBUSY) {
> +				usb_unanchor_urb(urb);
> +				dev_kfree_skb_any(skb);
> +				urb->context = NULL;
> +			}
> +		} else {
> +			break;
> +		}
> +	}
> +
> +	return HRTIMER_NORESTART;
> +}
> +
>  static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb 
> *hif_dev)  {
>  	usb_kill_anchored_urbs(&hif_dev->rx_submitted);
> +	usb_kill_anchored_urbs(&hif_dev->rx_delayed_submitted);
> +	tasklet_hrtimer_cancel(&hif_dev->rx_submit_timer);
>  }
>  
>  static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb 
> *hif_dev) @@ -830,6 +863,8 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
>  	int i, ret;
>  
>  	init_usb_anchor(&hif_dev->rx_submitted);
> +	init_usb_anchor(&hif_dev->rx_delayed_submitted);
> +
>  	spin_lock_init(&hif_dev->rx_lock);
>  
>  	for (i = 0; i < MAX_RX_URB_NUM; i++) { @@ -871,6 +906,10 @@ static 
> int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
>  		usb_free_urb(urb);
>  	}
>  
> +	/* add for flow control*/
> +	atomic_set(&hif_dev->rx_urb_submit_delay, 0);
> +	tasklet_hrtimer_init(&hif_dev->rx_submit_timer, 
> +rx_urb_submit_timer_handler, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +
>  	return 0;
>  
>  err_submit:
> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h 
> b/drivers/net/wireless/ath/ath9k/hif_usb.h
> index 51496e7..56d6be8 100644
> --- a/drivers/net/wireless/ath/ath9k/hif_usb.h
> +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
> @@ -98,9 +98,14 @@ struct hif_device_usb {
>  	struct hif_usb_tx tx;
>  	struct usb_anchor regout_submitted;
>  	struct usb_anchor rx_submitted;
> +	struct usb_anchor rx_delayed_submitted; /* delayed submit anchor */
>  	struct usb_anchor reg_in_submitted;
>  	struct usb_anchor mgmt_submitted;
>  	struct sk_buff *remain_skb;
> +
> +	struct tasklet_hrtimer  rx_submit_timer;/* delayed submit hrtimer */
> +	atomic_t  rx_urb_submit_delay; /*us*/
> +
>  	const char *fw_name;
>  	int rx_remain_len;
>  	int rx_pkt_len;
> diff --git a/drivers/net/wireless/ath/ath9k/htc.h 
> b/drivers/net/wireless/ath/ath9k/htc.h
> index 9dde265..453d0a8 100644
> --- a/drivers/net/wireless/ath/ath9k/htc.h
> +++ b/drivers/net/wireless/ath/ath9k/htc.h
> @@ -331,6 +331,10 @@ static inline struct ath9k_htc_tx_ctl 
> *HTC_SKB_CB(struct sk_buff *skb)
>  
>  #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
>  
> +#define TASKLETRX_STAT_INC(c) 
> +(hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c++)
> +#define TASKLETRX_STAT_ADD(c, a) 
> +(hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c += a) #define 
> +TASKLETRX_STAT_SET(c, a) 
> +(hif_dev->htc_handle->drv_priv->debug.taskletrx_stats.c = a)
> +
>  void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
>  			   struct ath_rx_status *rs);
>  
> @@ -352,11 +356,20 @@ struct ath_skbrx_stats {
>  	u32 skb_dropped;
>  };
>  
> +struct ath_taskletrx_stats {
> +	u32 taskletrx_looptimes;
> +	u32 taskletrx_highwater;
> +	u32 taskletrx_lowwater;
> +	u32 taskletrx_watermark_triggered;
> +	u32 taskletrx_urb_submit_delay;
> +};
> +
>  struct ath9k_debug {
>  	struct dentry *debugfs_phy;
>  	struct ath_tx_stats tx_stats;
>  	struct ath_rx_stats rx_stats;
>  	struct ath_skbrx_stats skbrx_stats;
> +	struct ath_taskletrx_stats taskletrx_stats;
>  };
>  
>  void ath9k_htc_get_et_strings(struct ieee80211_hw *hw, diff --git 
> a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c 
> b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> index 8cef1ed..7c8322e 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
> @@ -286,6 +286,51 @@ static const struct file_operations fops_skb_rx = {
>  	.llseek = default_llseek,
>  };
>  
> +static ssize_t read_file_tasklet_rx(struct file *file, char __user *user_buf,
> +				    size_t count, loff_t *ppos)
> +{
> +	struct ath9k_htc_priv *priv = file->private_data;
> +	char *buf;
> +	unsigned int len = 0, size = 1500;
> +	ssize_t retval = 0;
> +
> +	buf = kzalloc(size, GFP_KERNEL);
> +	if (buf == NULL)
> +		return -ENOMEM;
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "Loop times",
> +			priv->debug.taskletrx_stats.taskletrx_looptimes);
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "High watermark",
> +			priv->debug.taskletrx_stats.taskletrx_highwater);
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "Low watermark",
> +			priv->debug.taskletrx_stats.taskletrx_lowwater);
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "WM triggered",
> +			priv->debug.taskletrx_stats.taskletrx_watermark_triggered);
> +
> +	len += scnprintf(buf + len, size - len,
> +			"%20s : %10u\n", "URB delay",
> +			priv->debug.taskletrx_stats.taskletrx_urb_submit_delay);
> +	if (len > size)
> +		len = size;
> +
> +	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
> +	kfree(buf);
> +
> +	return retval;
> +}
> +
> +static const struct file_operations fops_tasklet_rx = {
> +	.read = read_file_tasklet_rx,
> +	.open = simple_open,
> +	.owner = THIS_MODULE,
> +	.llseek = default_llseek,
> +};
> +
>  static ssize_t read_file_slot(struct file *file, char __user *user_buf,
>  			      size_t count, loff_t *ppos)
>  {
> @@ -518,7 +563,11 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
>  	debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
>  			    priv, &fops_skb_rx);
>  
> +	debugfs_create_file("tasklet_rx", S_IRUSR, priv->debug.debugfs_phy,
> +			    priv, &fops_tasklet_rx);
> +
>  	ath9k_cmn_debug_recv(priv->debug.debugfs_phy, 
> &priv->debug.rx_stats);
> +
>  	ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, 
> &priv->debug.rx_stats);
>  
>  	debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, diff 
> --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c 
> b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> index a0f58e2..f5e6217 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> @@ -1061,7 +1061,28 @@ void ath9k_rx_tasklet(unsigned long data)
>  	unsigned long flags;
>  	struct ieee80211_hdr *hdr;
>  
> +	/* add for adaptive flow control*/
> +	int looptimes = 0;
> +	int highwatermark = ATH9K_HTC_RXBUF*3/4;
> +	int lowwatermark = ATH9K_HTC_RXBUF/4;
> +	unsigned int delay = 0;
> +
> +	struct htc_target *htc = priv->htc;
> +	struct hif_device_usb *hif_dev = htc->hif_dev;
> +
> +	TASKLETRX_STAT_SET(taskletrx_highwater, highwatermark);
> +	TASKLETRX_STAT_SET(taskletrx_lowwater, lowwatermark);
> +
>  	do {
> +		looptimes++;
> +		TASKLETRX_STAT_SET(taskletrx_looptimes, looptimes);
> +		if (looptimes > highwatermark) {
> +			delay = looptimes*10;
> +			atomic_set(&hif_dev->rx_urb_submit_delay, delay);
> +			TASKLETRX_STAT_INC(taskletrx_watermark_triggered);
> +			TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, delay);
> +		}
> +
>  		spin_lock_irqsave(&priv->rx.rxbuflock, flags);
>  		list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
>  			if (tmp_buf->in_process) {
> @@ -1072,6 +1093,11 @@ void ath9k_rx_tasklet(unsigned long data)
>  
>  		if (rxbuf == NULL) {
>  			spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
> +			if (looptimes < lowwatermark) {
> +				atomic_set(&hif_dev->rx_urb_submit_delay, 0);
> +				TASKLETRX_STAT_SET(taskletrx_urb_submit_delay, 0);
> +			}
> +
>  			break;
>  		}
>  
> 


--
Regards,
Oleksij

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

end of thread, other threads:[~2015-01-30 10:31 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-29  4:09 [PATCH] Repair soft lockup with monitor mode of ath9k_htc card zhengyuwei
2015-01-29  4:09 ` [ath9k-devel] " zhengyuwei at 360.cn
2015-01-29 10:52 ` Oleksij Rempel
2015-01-29 10:52   ` Oleksij Rempel
2015-01-29 11:01   ` Kalle Valo
2015-01-29 11:01     ` Kalle Valo
2015-01-30 10:24   ` 答复: " 郑玉伟
2015-01-30 10:24     ` [ath9k-devel] 答复: " 郑玉伟
2015-01-30 10:24     ` 答复: [ath9k-devel] " 郑玉伟
2015-01-30 10:24     ` 郑玉伟

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.