aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2011-01-31 13:49:52 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-04 16:29:51 -0500
commita0fd751f0924e0eefa36592f1d358c4ab18b44c5 (patch)
tree35505bb17a07f66dc18b0c456bd5086efe01918c
parent212e1a5b9df0a51d54d7841467f3f01baa1b82f1 (diff)
zd1211rw: add TX watchdog and device resetting
When doing transfers at high speed for long time, tx queue can freeze. So add tx watchdog. TX-watchdog checks for locked tx-urbs and reset hardware when such is detected. Merely unlinking urb was not enough, device have to be reseted. Hw settings are restored so that any open link will stay on after reset. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c8
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.h2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c161
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.h12
5 files changed, 181 insertions, 4 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 907e6562cb59..54f68f134ea7 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1448,6 +1448,7 @@ int zd_chip_enable_rxtx(struct zd_chip *chip)
1448 mutex_lock(&chip->mutex); 1448 mutex_lock(&chip->mutex);
1449 zd_usb_enable_tx(&chip->usb); 1449 zd_usb_enable_tx(&chip->usb);
1450 r = zd_usb_enable_rx(&chip->usb); 1450 r = zd_usb_enable_rx(&chip->usb);
1451 zd_tx_watchdog_enable(&chip->usb);
1451 mutex_unlock(&chip->mutex); 1452 mutex_unlock(&chip->mutex);
1452 return r; 1453 return r;
1453} 1454}
@@ -1455,6 +1456,7 @@ int zd_chip_enable_rxtx(struct zd_chip *chip)
1455void zd_chip_disable_rxtx(struct zd_chip *chip) 1456void zd_chip_disable_rxtx(struct zd_chip *chip)
1456{ 1457{
1457 mutex_lock(&chip->mutex); 1458 mutex_lock(&chip->mutex);
1459 zd_tx_watchdog_disable(&chip->usb);
1458 zd_usb_disable_rx(&chip->usb); 1460 zd_usb_disable_rx(&chip->usb);
1459 zd_usb_disable_tx(&chip->usb); 1461 zd_usb_disable_tx(&chip->usb);
1460 mutex_unlock(&chip->mutex); 1462 mutex_unlock(&chip->mutex);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index e82f0075ed93..a590a94cb6fa 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -264,7 +264,7 @@ static int set_mc_hash(struct zd_mac *mac)
264 return zd_chip_set_multicast_hash(&mac->chip, &hash); 264 return zd_chip_set_multicast_hash(&mac->chip, &hash);
265} 265}
266 266
267static int zd_op_start(struct ieee80211_hw *hw) 267int zd_op_start(struct ieee80211_hw *hw)
268{ 268{
269 struct zd_mac *mac = zd_hw_mac(hw); 269 struct zd_mac *mac = zd_hw_mac(hw);
270 struct zd_chip *chip = &mac->chip; 270 struct zd_chip *chip = &mac->chip;
@@ -314,7 +314,7 @@ out:
314 return r; 314 return r;
315} 315}
316 316
317static void zd_op_stop(struct ieee80211_hw *hw) 317void zd_op_stop(struct ieee80211_hw *hw)
318{ 318{
319 struct zd_mac *mac = zd_hw_mac(hw); 319 struct zd_mac *mac = zd_hw_mac(hw);
320 struct zd_chip *chip = &mac->chip; 320 struct zd_chip *chip = &mac->chip;
@@ -1409,6 +1409,9 @@ static void link_led_handler(struct work_struct *work)
1409 int is_associated; 1409 int is_associated;
1410 int r; 1410 int r;
1411 1411
1412 if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
1413 goto requeue;
1414
1412 spin_lock_irq(&mac->lock); 1415 spin_lock_irq(&mac->lock);
1413 is_associated = mac->associated; 1416 is_associated = mac->associated;
1414 spin_unlock_irq(&mac->lock); 1417 spin_unlock_irq(&mac->lock);
@@ -1418,6 +1421,7 @@ static void link_led_handler(struct work_struct *work)
1418 if (r) 1421 if (r)
1419 dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r); 1422 dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
1420 1423
1424requeue:
1421 queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work, 1425 queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
1422 LINK_LED_WORK_DELAY); 1426 LINK_LED_WORK_DELAY);
1423} 1427}
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index c0f239e40bcd..f8c93c3fe755 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -314,6 +314,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length);
314void zd_mac_tx_failed(struct urb *urb); 314void zd_mac_tx_failed(struct urb *urb);
315void zd_mac_tx_to_dev(struct sk_buff *skb, int error); 315void zd_mac_tx_to_dev(struct sk_buff *skb, int error);
316 316
317int zd_op_start(struct ieee80211_hw *hw);
318void zd_op_stop(struct ieee80211_hw *hw);
317int zd_restore_settings(struct zd_mac *mac); 319int zd_restore_settings(struct zd_mac *mac);
318 320
319#ifdef DEBUG 321#ifdef DEBUG
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 861dad192871..178d794be3fd 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -798,6 +798,7 @@ void zd_usb_disable_tx(struct zd_usb *usb)
798 usb_kill_anchored_urbs(&tx->submitted); 798 usb_kill_anchored_urbs(&tx->submitted);
799 799
800 spin_lock_irqsave(&tx->lock, flags); 800 spin_lock_irqsave(&tx->lock, flags);
801 WARN_ON(!skb_queue_empty(&tx->submitted_skbs));
801 WARN_ON(tx->submitted_urbs != 0); 802 WARN_ON(tx->submitted_urbs != 0);
802 tx->submitted_urbs = 0; 803 tx->submitted_urbs = 0;
803 spin_unlock_irqrestore(&tx->lock, flags); 804 spin_unlock_irqrestore(&tx->lock, flags);
@@ -895,6 +896,7 @@ static void tx_urb_complete(struct urb *urb)
895 goto resubmit; 896 goto resubmit;
896 } 897 }
897free_urb: 898free_urb:
899 skb_unlink(skb, &usb->tx.submitted_skbs);
898 zd_mac_tx_to_dev(skb, urb->status); 900 zd_mac_tx_to_dev(skb, urb->status);
899 usb_free_urb(urb); 901 usb_free_urb(urb);
900 tx_dec_submitted_urbs(usb); 902 tx_dec_submitted_urbs(usb);
@@ -924,6 +926,7 @@ resubmit:
924int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb) 926int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb)
925{ 927{
926 int r; 928 int r;
929 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
927 struct usb_device *udev = zd_usb_to_usbdev(usb); 930 struct usb_device *udev = zd_usb_to_usbdev(usb);
928 struct urb *urb; 931 struct urb *urb;
929 struct zd_usb_tx *tx = &usb->tx; 932 struct zd_usb_tx *tx = &usb->tx;
@@ -942,10 +945,14 @@ int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb)
942 usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT), 945 usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
943 skb->data, skb->len, tx_urb_complete, skb); 946 skb->data, skb->len, tx_urb_complete, skb);
944 947
948 info->rate_driver_data[1] = (void *)jiffies;
949 skb_queue_tail(&tx->submitted_skbs, skb);
945 usb_anchor_urb(urb, &tx->submitted); 950 usb_anchor_urb(urb, &tx->submitted);
951
946 r = usb_submit_urb(urb, GFP_ATOMIC); 952 r = usb_submit_urb(urb, GFP_ATOMIC);
947 if (r) { 953 if (r) {
948 usb_unanchor_urb(urb); 954 usb_unanchor_urb(urb);
955 skb_unlink(skb, &tx->submitted_skbs);
949 goto error; 956 goto error;
950 } 957 }
951 tx_inc_submitted_urbs(usb); 958 tx_inc_submitted_urbs(usb);
@@ -956,6 +963,76 @@ out:
956 return r; 963 return r;
957} 964}
958 965
966static bool zd_tx_timeout(struct zd_usb *usb)
967{
968 struct zd_usb_tx *tx = &usb->tx;
969 struct sk_buff_head *q = &tx->submitted_skbs;
970 struct sk_buff *skb, *skbnext;
971 struct ieee80211_tx_info *info;
972 unsigned long flags, trans_start;
973 bool have_timedout = false;
974
975 spin_lock_irqsave(&q->lock, flags);
976 skb_queue_walk_safe(q, skb, skbnext) {
977 info = IEEE80211_SKB_CB(skb);
978 trans_start = (unsigned long)info->rate_driver_data[1];
979
980 if (time_is_before_jiffies(trans_start + ZD_TX_TIMEOUT)) {
981 have_timedout = true;
982 break;
983 }
984 }
985 spin_unlock_irqrestore(&q->lock, flags);
986
987 return have_timedout;
988}
989
990static void zd_tx_watchdog_handler(struct work_struct *work)
991{
992 struct zd_usb *usb =
993 container_of(work, struct zd_usb, tx.watchdog_work.work);
994 struct zd_usb_tx *tx = &usb->tx;
995
996 if (!atomic_read(&tx->enabled) || !tx->watchdog_enabled)
997 goto out;
998 if (!zd_tx_timeout(usb))
999 goto out;
1000
1001 /* TX halted, try reset */
1002 dev_warn(zd_usb_dev(usb), "TX-stall detected, reseting device...");
1003
1004 usb_queue_reset_device(usb->intf);
1005
1006 /* reset will stop this worker, don't rearm */
1007 return;
1008out:
1009 queue_delayed_work(zd_workqueue, &tx->watchdog_work,
1010 ZD_TX_WATCHDOG_INTERVAL);
1011}
1012
1013void zd_tx_watchdog_enable(struct zd_usb *usb)
1014{
1015 struct zd_usb_tx *tx = &usb->tx;
1016
1017 if (!tx->watchdog_enabled) {
1018 dev_dbg_f(zd_usb_dev(usb), "\n");
1019 queue_delayed_work(zd_workqueue, &tx->watchdog_work,
1020 ZD_TX_WATCHDOG_INTERVAL);
1021 tx->watchdog_enabled = 1;
1022 }
1023}
1024
1025void zd_tx_watchdog_disable(struct zd_usb *usb)
1026{
1027 struct zd_usb_tx *tx = &usb->tx;
1028
1029 if (tx->watchdog_enabled) {
1030 dev_dbg_f(zd_usb_dev(usb), "\n");
1031 tx->watchdog_enabled = 0;
1032 cancel_delayed_work_sync(&tx->watchdog_work);
1033 }
1034}
1035
959static inline void init_usb_interrupt(struct zd_usb *usb) 1036static inline void init_usb_interrupt(struct zd_usb *usb)
960{ 1037{
961 struct zd_usb_interrupt *intr = &usb->intr; 1038 struct zd_usb_interrupt *intr = &usb->intr;
@@ -984,8 +1061,11 @@ static inline void init_usb_tx(struct zd_usb *usb)
984 spin_lock_init(&tx->lock); 1061 spin_lock_init(&tx->lock);
985 atomic_set(&tx->enabled, 0); 1062 atomic_set(&tx->enabled, 0);
986 tx->stopped = 0; 1063 tx->stopped = 0;
1064 skb_queue_head_init(&tx->submitted_skbs);
987 init_usb_anchor(&tx->submitted); 1065 init_usb_anchor(&tx->submitted);
988 tx->submitted_urbs = 0; 1066 tx->submitted_urbs = 0;
1067 tx->watchdog_enabled = 0;
1068 INIT_DELAYED_WORK(&tx->watchdog_work, zd_tx_watchdog_handler);
989} 1069}
990 1070
991void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw, 1071void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw,
@@ -1233,11 +1313,92 @@ static void disconnect(struct usb_interface *intf)
1233 dev_dbg(&intf->dev, "disconnected\n"); 1313 dev_dbg(&intf->dev, "disconnected\n");
1234} 1314}
1235 1315
1316static void zd_usb_resume(struct zd_usb *usb)
1317{
1318 struct zd_mac *mac = zd_usb_to_mac(usb);
1319 int r;
1320
1321 dev_dbg_f(zd_usb_dev(usb), "\n");
1322
1323 r = zd_op_start(zd_usb_to_hw(usb));
1324 if (r < 0) {
1325 dev_warn(zd_usb_dev(usb), "Device resume failed "
1326 "with error code %d. Retrying...\n", r);
1327 if (usb->was_running)
1328 set_bit(ZD_DEVICE_RUNNING, &mac->flags);
1329 usb_queue_reset_device(usb->intf);
1330 return;
1331 }
1332
1333 if (mac->type != NL80211_IFTYPE_UNSPECIFIED) {
1334 r = zd_restore_settings(mac);
1335 if (r < 0) {
1336 dev_dbg(zd_usb_dev(usb),
1337 "failed to restore settings, %d\n", r);
1338 return;
1339 }
1340 }
1341}
1342
1343static void zd_usb_stop(struct zd_usb *usb)
1344{
1345 dev_dbg_f(zd_usb_dev(usb), "\n");
1346
1347 zd_op_stop(zd_usb_to_hw(usb));
1348
1349 zd_usb_disable_tx(usb);
1350 zd_usb_disable_rx(usb);
1351 zd_usb_disable_int(usb);
1352
1353 usb->initialized = 0;
1354}
1355
1356static int pre_reset(struct usb_interface *intf)
1357{
1358 struct ieee80211_hw *hw = usb_get_intfdata(intf);
1359 struct zd_mac *mac;
1360 struct zd_usb *usb;
1361
1362 if (!hw || intf->condition != USB_INTERFACE_BOUND)
1363 return 0;
1364
1365 mac = zd_hw_mac(hw);
1366 usb = &mac->chip.usb;
1367
1368 usb->was_running = test_bit(ZD_DEVICE_RUNNING, &mac->flags);
1369
1370 zd_usb_stop(usb);
1371
1372 mutex_lock(&mac->chip.mutex);
1373 return 0;
1374}
1375
1376static int post_reset(struct usb_interface *intf)
1377{
1378 struct ieee80211_hw *hw = usb_get_intfdata(intf);
1379 struct zd_mac *mac;
1380 struct zd_usb *usb;
1381
1382 if (!hw || intf->condition != USB_INTERFACE_BOUND)
1383 return 0;
1384
1385 mac = zd_hw_mac(hw);
1386 usb = &mac->chip.usb;
1387
1388 mutex_unlock(&mac->chip.mutex);
1389
1390 if (usb->was_running)
1391 zd_usb_resume(usb);
1392 return 0;
1393}
1394
1236static struct usb_driver driver = { 1395static struct usb_driver driver = {
1237 .name = KBUILD_MODNAME, 1396 .name = KBUILD_MODNAME,
1238 .id_table = usb_ids, 1397 .id_table = usb_ids,
1239 .probe = probe, 1398 .probe = probe,
1240 .disconnect = disconnect, 1399 .disconnect = disconnect,
1400 .pre_reset = pre_reset,
1401 .post_reset = post_reset,
1241}; 1402};
1242 1403
1243struct workqueue_struct *zd_workqueue; 1404struct workqueue_struct *zd_workqueue;
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index 24db0dd68421..98f09c2dde7e 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -32,6 +32,9 @@
32#define ZD_USB_TX_HIGH 5 32#define ZD_USB_TX_HIGH 5
33#define ZD_USB_TX_LOW 2 33#define ZD_USB_TX_LOW 2
34 34
35#define ZD_TX_TIMEOUT (HZ * 5)
36#define ZD_TX_WATCHDOG_INTERVAL round_jiffies_relative(HZ)
37
35enum devicetype { 38enum devicetype {
36 DEVICE_ZD1211 = 0, 39 DEVICE_ZD1211 = 0,
37 DEVICE_ZD1211B = 1, 40 DEVICE_ZD1211B = 1,
@@ -196,9 +199,11 @@ struct zd_usb_rx {
196struct zd_usb_tx { 199struct zd_usb_tx {
197 atomic_t enabled; 200 atomic_t enabled;
198 spinlock_t lock; 201 spinlock_t lock;
202 struct delayed_work watchdog_work;
203 struct sk_buff_head submitted_skbs;
199 struct usb_anchor submitted; 204 struct usb_anchor submitted;
200 int submitted_urbs; 205 int submitted_urbs;
201 int stopped; 206 u8 stopped:1, watchdog_enabled:1;
202}; 207};
203 208
204/* Contains the usb parts. The structure doesn't require a lock because intf 209/* Contains the usb parts. The structure doesn't require a lock because intf
@@ -210,7 +215,7 @@ struct zd_usb {
210 struct zd_usb_tx tx; 215 struct zd_usb_tx tx;
211 struct usb_interface *intf; 216 struct usb_interface *intf;
212 u8 req_buf[64]; /* zd_usb_iowrite16v needs 62 bytes */ 217 u8 req_buf[64]; /* zd_usb_iowrite16v needs 62 bytes */
213 u8 is_zd1211b:1, initialized:1; 218 u8 is_zd1211b:1, initialized:1, was_running:1;
214}; 219};
215 220
216#define zd_usb_dev(usb) (&usb->intf->dev) 221#define zd_usb_dev(usb) (&usb->intf->dev)
@@ -237,6 +242,9 @@ void zd_usb_clear(struct zd_usb *usb);
237 242
238int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size); 243int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size);
239 244
245void zd_tx_watchdog_enable(struct zd_usb *usb);
246void zd_tx_watchdog_disable(struct zd_usb *usb);
247
240int zd_usb_enable_int(struct zd_usb *usb); 248int zd_usb_enable_int(struct zd_usb *usb);
241void zd_usb_disable_int(struct zd_usb *usb); 249void zd_usb_disable_int(struct zd_usb *usb);
242 250