aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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