aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2011-06-20 07:42:44 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-06-22 16:09:46 -0400
commitc900eff30a14ecf209ee7a17a7c3c54890694ce6 (patch)
treea408e64682e04326bcb334409e0f1130f8222cde /drivers/net/wireless
parentf762d8c3f8b502b93d20bd755fc30ce99d3d0abd (diff)
zd1211rw: handle lost read-reg interrupts
Device losses read-reg interrupts. By looking at usbmon it appears that USB_INT_ID_RETRY_FAILED can override USB_INT_ID_REGS. This causes read command to timeout, usually under heavy TX. Fix by retrying read registers again if USB_INT_ID_RETRY_FAILED is received while waiting for USB_INT_ID_REGS. However USB_INT_ID_REGS is not always lost but is received after USB_INT_ID_RETRY_FAILED and is usually received by the retried read command. USB_INT_ID_REGS of the retry is then left unhandled and might be received by next read command. Handle this by ignoring previous USB_INT_ID_REGS that doesn't match current read command request. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c125
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.h5
2 files changed, 109 insertions, 21 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 621c2cc9fc8..cf0d69dd7be 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -111,6 +111,9 @@ MODULE_DEVICE_TABLE(usb, usb_ids);
111#define FW_ZD1211_PREFIX "zd1211/zd1211_" 111#define FW_ZD1211_PREFIX "zd1211/zd1211_"
112#define FW_ZD1211B_PREFIX "zd1211/zd1211b_" 112#define FW_ZD1211B_PREFIX "zd1211/zd1211b_"
113 113
114static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
115 unsigned int count);
116
114/* USB device initialization */ 117/* USB device initialization */
115static void int_urb_complete(struct urb *urb); 118static void int_urb_complete(struct urb *urb);
116 119
@@ -365,6 +368,20 @@ exit:
365 368
366#define urb_dev(urb) (&(urb)->dev->dev) 369#define urb_dev(urb) (&(urb)->dev->dev)
367 370
371static inline void handle_regs_int_override(struct urb *urb)
372{
373 struct zd_usb *usb = urb->context;
374 struct zd_usb_interrupt *intr = &usb->intr;
375
376 spin_lock(&intr->lock);
377 if (atomic_read(&intr->read_regs_enabled)) {
378 atomic_set(&intr->read_regs_enabled, 0);
379 intr->read_regs_int_overridden = 1;
380 complete(&intr->read_regs.completion);
381 }
382 spin_unlock(&intr->lock);
383}
384
368static inline void handle_regs_int(struct urb *urb) 385static inline void handle_regs_int(struct urb *urb)
369{ 386{
370 struct zd_usb *usb = urb->context; 387 struct zd_usb *usb = urb->context;
@@ -383,25 +400,45 @@ static inline void handle_regs_int(struct urb *urb)
383 USB_MAX_EP_INT_BUFFER); 400 USB_MAX_EP_INT_BUFFER);
384 spin_unlock(&mac->lock); 401 spin_unlock(&mac->lock);
385 schedule_work(&mac->process_intr); 402 schedule_work(&mac->process_intr);
386 } else if (intr->read_regs_enabled) { 403 } else if (atomic_read(&intr->read_regs_enabled)) {
387 intr->read_regs.length = len = urb->actual_length; 404 len = urb->actual_length;
388 405 intr->read_regs.length = urb->actual_length;
389 if (len > sizeof(intr->read_regs.buffer)) 406 if (len > sizeof(intr->read_regs.buffer))
390 len = sizeof(intr->read_regs.buffer); 407 len = sizeof(intr->read_regs.buffer);
408
391 memcpy(intr->read_regs.buffer, urb->transfer_buffer, len); 409 memcpy(intr->read_regs.buffer, urb->transfer_buffer, len);
392 intr->read_regs_enabled = 0; 410
411 /* Sometimes USB_INT_ID_REGS is not overridden, but comes after
412 * USB_INT_ID_RETRY_FAILED. Read-reg retry then gets this
413 * delayed USB_INT_ID_REGS, but leaves USB_INT_ID_REGS of
414 * retry unhandled. Next read-reg command then might catch
415 * this wrong USB_INT_ID_REGS. Fix by ignoring wrong reads.
416 */
417 if (!check_read_regs(usb, intr->read_regs.req,
418 intr->read_regs.req_count))
419 goto out;
420
421 atomic_set(&intr->read_regs_enabled, 0);
422 intr->read_regs_int_overridden = 0;
393 complete(&intr->read_regs.completion); 423 complete(&intr->read_regs.completion);
424
394 goto out; 425 goto out;
395 } 426 }
396 427
397out: 428out:
398 spin_unlock(&intr->lock); 429 spin_unlock(&intr->lock);
430
431 /* CR_INTERRUPT might override read_reg too. */
432 if (int_num == CR_INTERRUPT && atomic_read(&intr->read_regs_enabled))
433 handle_regs_int_override(urb);
399} 434}
400 435
401static void int_urb_complete(struct urb *urb) 436static void int_urb_complete(struct urb *urb)
402{ 437{
403 int r; 438 int r;
404 struct usb_int_header *hdr; 439 struct usb_int_header *hdr;
440 struct zd_usb *usb;
441 struct zd_usb_interrupt *intr;
405 442
406 switch (urb->status) { 443 switch (urb->status) {
407 case 0: 444 case 0:
@@ -430,6 +467,14 @@ static void int_urb_complete(struct urb *urb)
430 goto resubmit; 467 goto resubmit;
431 } 468 }
432 469
470 /* USB_INT_ID_RETRY_FAILED triggered by tx-urb submit can override
471 * pending USB_INT_ID_REGS causing read command timeout.
472 */
473 usb = urb->context;
474 intr = &usb->intr;
475 if (hdr->id != USB_INT_ID_REGS && atomic_read(&intr->read_regs_enabled))
476 handle_regs_int_override(urb);
477
433 switch (hdr->id) { 478 switch (hdr->id) {
434 case USB_INT_ID_REGS: 479 case USB_INT_ID_REGS:
435 handle_regs_int(urb); 480 handle_regs_int(urb);
@@ -1129,6 +1174,7 @@ static inline void init_usb_interrupt(struct zd_usb *usb)
1129 spin_lock_init(&intr->lock); 1174 spin_lock_init(&intr->lock);
1130 intr->interval = int_urb_interval(zd_usb_to_usbdev(usb)); 1175 intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));
1131 init_completion(&intr->read_regs.completion); 1176 init_completion(&intr->read_regs.completion);
1177 atomic_set(&intr->read_regs_enabled, 0);
1132 intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT); 1178 intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT);
1133} 1179}
1134 1180
@@ -1563,12 +1609,16 @@ static int usb_int_regs_length(unsigned int count)
1563 return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data); 1609 return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);
1564} 1610}
1565 1611
1566static void prepare_read_regs_int(struct zd_usb *usb) 1612static void prepare_read_regs_int(struct zd_usb *usb,
1613 struct usb_req_read_regs *req,
1614 unsigned int count)
1567{ 1615{
1568 struct zd_usb_interrupt *intr = &usb->intr; 1616 struct zd_usb_interrupt *intr = &usb->intr;
1569 1617
1570 spin_lock_irq(&intr->lock); 1618 spin_lock_irq(&intr->lock);
1571 intr->read_regs_enabled = 1; 1619 atomic_set(&intr->read_regs_enabled, 1);
1620 intr->read_regs.req = req;
1621 intr->read_regs.req_count = count;
1572 INIT_COMPLETION(intr->read_regs.completion); 1622 INIT_COMPLETION(intr->read_regs.completion);
1573 spin_unlock_irq(&intr->lock); 1623 spin_unlock_irq(&intr->lock);
1574} 1624}
@@ -1578,22 +1628,18 @@ static void disable_read_regs_int(struct zd_usb *usb)
1578 struct zd_usb_interrupt *intr = &usb->intr; 1628 struct zd_usb_interrupt *intr = &usb->intr;
1579 1629
1580 spin_lock_irq(&intr->lock); 1630 spin_lock_irq(&intr->lock);
1581 intr->read_regs_enabled = 0; 1631 atomic_set(&intr->read_regs_enabled, 0);
1582 spin_unlock_irq(&intr->lock); 1632 spin_unlock_irq(&intr->lock);
1583} 1633}
1584 1634
1585static int get_results(struct zd_usb *usb, u16 *values, 1635static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
1586 struct usb_req_read_regs *req, unsigned int count) 1636 unsigned int count)
1587{ 1637{
1588 int r;
1589 int i; 1638 int i;
1590 struct zd_usb_interrupt *intr = &usb->intr; 1639 struct zd_usb_interrupt *intr = &usb->intr;
1591 struct read_regs_int *rr = &intr->read_regs; 1640 struct read_regs_int *rr = &intr->read_regs;
1592 struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer; 1641 struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
1593 1642
1594 spin_lock_irq(&intr->lock);
1595
1596 r = -EIO;
1597 /* The created block size seems to be larger than expected. 1643 /* The created block size seems to be larger than expected.
1598 * However results appear to be correct. 1644 * However results appear to be correct.
1599 */ 1645 */
@@ -1601,13 +1647,14 @@ static int get_results(struct zd_usb *usb, u16 *values,
1601 dev_dbg_f(zd_usb_dev(usb), 1647 dev_dbg_f(zd_usb_dev(usb),
1602 "error: actual length %d less than expected %d\n", 1648 "error: actual length %d less than expected %d\n",
1603 rr->length, usb_int_regs_length(count)); 1649 rr->length, usb_int_regs_length(count));
1604 goto error_unlock; 1650 return false;
1605 } 1651 }
1652
1606 if (rr->length > sizeof(rr->buffer)) { 1653 if (rr->length > sizeof(rr->buffer)) {
1607 dev_dbg_f(zd_usb_dev(usb), 1654 dev_dbg_f(zd_usb_dev(usb),
1608 "error: actual length %d exceeds buffer size %zu\n", 1655 "error: actual length %d exceeds buffer size %zu\n",
1609 rr->length, sizeof(rr->buffer)); 1656 rr->length, sizeof(rr->buffer));
1610 goto error_unlock; 1657 return false;
1611 } 1658 }
1612 1659
1613 for (i = 0; i < count; i++) { 1660 for (i = 0; i < count; i++) {
@@ -1617,8 +1664,39 @@ static int get_results(struct zd_usb *usb, u16 *values,
1617 "rd[%d] addr %#06hx expected %#06hx\n", i, 1664 "rd[%d] addr %#06hx expected %#06hx\n", i,
1618 le16_to_cpu(rd->addr), 1665 le16_to_cpu(rd->addr),
1619 le16_to_cpu(req->addr[i])); 1666 le16_to_cpu(req->addr[i]));
1620 goto error_unlock; 1667 return false;
1621 } 1668 }
1669 }
1670
1671 return true;
1672}
1673
1674static int get_results(struct zd_usb *usb, u16 *values,
1675 struct usb_req_read_regs *req, unsigned int count,
1676 bool *retry)
1677{
1678 int r;
1679 int i;
1680 struct zd_usb_interrupt *intr = &usb->intr;
1681 struct read_regs_int *rr = &intr->read_regs;
1682 struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
1683
1684 spin_lock_irq(&intr->lock);
1685
1686 r = -EIO;
1687
1688 /* Read failed because firmware bug? */
1689 *retry = !!intr->read_regs_int_overridden;
1690 if (*retry)
1691 goto error_unlock;
1692
1693 if (!check_read_regs(usb, req, count)) {
1694 dev_dbg_f(zd_usb_dev(usb), "error: invalid read regs\n");
1695 goto error_unlock;
1696 }
1697
1698 for (i = 0; i < count; i++) {
1699 struct reg_data *rd = &regs->regs[i];
1622 values[i] = le16_to_cpu(rd->value); 1700 values[i] = le16_to_cpu(rd->value);
1623 } 1701 }
1624 1702
@@ -1631,11 +1709,11 @@ error_unlock:
1631int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, 1709int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
1632 const zd_addr_t *addresses, unsigned int count) 1710 const zd_addr_t *addresses, unsigned int count)
1633{ 1711{
1634 int r; 1712 int r, i, req_len, actual_req_len, try_count = 0;
1635 int i, req_len, actual_req_len;
1636 struct usb_device *udev; 1713 struct usb_device *udev;
1637 struct usb_req_read_regs *req = NULL; 1714 struct usb_req_read_regs *req = NULL;
1638 unsigned long timeout; 1715 unsigned long timeout;
1716 bool retry = false;
1639 1717
1640 if (count < 1) { 1718 if (count < 1) {
1641 dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n"); 1719 dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n");
@@ -1671,8 +1749,10 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
1671 for (i = 0; i < count; i++) 1749 for (i = 0; i < count; i++)
1672 req->addr[i] = cpu_to_le16((u16)addresses[i]); 1750 req->addr[i] = cpu_to_le16((u16)addresses[i]);
1673 1751
1752retry_read:
1753 try_count++;
1674 udev = zd_usb_to_usbdev(usb); 1754 udev = zd_usb_to_usbdev(usb);
1675 prepare_read_regs_int(usb); 1755 prepare_read_regs_int(usb, req, count);
1676 r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/); 1756 r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
1677 if (r) { 1757 if (r) {
1678 dev_dbg_f(zd_usb_dev(usb), 1758 dev_dbg_f(zd_usb_dev(usb),
@@ -1696,7 +1776,12 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
1696 goto error; 1776 goto error;
1697 } 1777 }
1698 1778
1699 r = get_results(usb, values, req, count); 1779 r = get_results(usb, values, req, count, &retry);
1780 if (retry && try_count < 20) {
1781 dev_dbg_f(zd_usb_dev(usb), "read retry, tries so far: %d\n",
1782 try_count);
1783 goto retry_read;
1784 }
1700error: 1785error:
1701 return r; 1786 return r;
1702} 1787}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index bf942843b73..99193b456a7 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -144,6 +144,8 @@ struct usb_int_retry_fail {
144 144
145struct read_regs_int { 145struct read_regs_int {
146 struct completion completion; 146 struct completion completion;
147 struct usb_req_read_regs *req;
148 unsigned int req_count;
147 /* Stores the USB int structure and contains the USB address of the 149 /* Stores the USB int structure and contains the USB address of the
148 * first requested register before request. 150 * first requested register before request.
149 */ 151 */
@@ -169,7 +171,8 @@ struct zd_usb_interrupt {
169 void *buffer; 171 void *buffer;
170 dma_addr_t buffer_dma; 172 dma_addr_t buffer_dma;
171 int interval; 173 int interval;
172 u8 read_regs_enabled:1; 174 atomic_t read_regs_enabled;
175 u8 read_regs_int_overridden:1;
173}; 176};
174 177
175static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr) 178static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)