diff options
Diffstat (limited to 'drivers/net/wireless/zd1211rw/zd_usb.c')
| -rw-r--r-- | drivers/net/wireless/zd1211rw/zd_usb.c | 177 |
1 files changed, 145 insertions, 32 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index f6df3665fdb6..81e80489a052 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
| @@ -1156,6 +1156,7 @@ void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw, | |||
| 1156 | memset(usb, 0, sizeof(*usb)); | 1156 | memset(usb, 0, sizeof(*usb)); |
| 1157 | usb->intf = usb_get_intf(intf); | 1157 | usb->intf = usb_get_intf(intf); |
| 1158 | usb_set_intfdata(usb->intf, hw); | 1158 | usb_set_intfdata(usb->intf, hw); |
| 1159 | init_usb_anchor(&usb->submitted_cmds); | ||
| 1159 | init_usb_interrupt(usb); | 1160 | init_usb_interrupt(usb); |
| 1160 | init_usb_tx(usb); | 1161 | init_usb_tx(usb); |
| 1161 | init_usb_rx(usb); | 1162 | init_usb_rx(usb); |
| @@ -1634,15 +1635,15 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, | |||
| 1634 | 1635 | ||
| 1635 | udev = zd_usb_to_usbdev(usb); | 1636 | udev = zd_usb_to_usbdev(usb); |
| 1636 | prepare_read_regs_int(usb); | 1637 | prepare_read_regs_int(usb); |
| 1637 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | 1638 | r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT), |
| 1638 | req, req_len, &actual_req_len, 50 /* ms */); | 1639 | req, req_len, &actual_req_len, 50 /* ms */); |
| 1639 | if (r) { | 1640 | if (r) { |
| 1640 | dev_dbg_f(zd_usb_dev(usb), | 1641 | dev_dbg_f(zd_usb_dev(usb), |
| 1641 | "error in usb_bulk_msg(). Error number %d\n", r); | 1642 | "error in usb_interrupt_msg(). Error number %d\n", r); |
| 1642 | goto error; | 1643 | goto error; |
| 1643 | } | 1644 | } |
| 1644 | if (req_len != actual_req_len) { | 1645 | if (req_len != actual_req_len) { |
| 1645 | dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()\n" | 1646 | dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()\n" |
| 1646 | " req_len %d != actual_req_len %d\n", | 1647 | " req_len %d != actual_req_len %d\n", |
| 1647 | req_len, actual_req_len); | 1648 | req_len, actual_req_len); |
| 1648 | r = -EIO; | 1649 | r = -EIO; |
| @@ -1663,13 +1664,103 @@ error: | |||
| 1663 | return r; | 1664 | return r; |
| 1664 | } | 1665 | } |
| 1665 | 1666 | ||
| 1666 | int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | 1667 | static void iowrite16v_urb_complete(struct urb *urb) |
| 1667 | unsigned int count) | 1668 | { |
| 1669 | struct zd_usb *usb = urb->context; | ||
| 1670 | |||
| 1671 | if (urb->status && !usb->cmd_error) | ||
| 1672 | usb->cmd_error = urb->status; | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | static int zd_submit_waiting_urb(struct zd_usb *usb, bool last) | ||
| 1676 | { | ||
| 1677 | int r = 0; | ||
| 1678 | struct urb *urb = usb->urb_async_waiting; | ||
| 1679 | |||
| 1680 | if (!urb) | ||
| 1681 | return 0; | ||
| 1682 | |||
| 1683 | usb->urb_async_waiting = NULL; | ||
| 1684 | |||
| 1685 | if (!last) | ||
| 1686 | urb->transfer_flags |= URB_NO_INTERRUPT; | ||
| 1687 | |||
| 1688 | usb_anchor_urb(urb, &usb->submitted_cmds); | ||
| 1689 | r = usb_submit_urb(urb, GFP_KERNEL); | ||
| 1690 | if (r) { | ||
| 1691 | usb_unanchor_urb(urb); | ||
| 1692 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1693 | "error in usb_submit_urb(). Error number %d\n", r); | ||
| 1694 | goto error; | ||
| 1695 | } | ||
| 1696 | |||
| 1697 | /* fall-through with r == 0 */ | ||
| 1698 | error: | ||
| 1699 | usb_free_urb(urb); | ||
| 1700 | return r; | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | void zd_usb_iowrite16v_async_start(struct zd_usb *usb) | ||
| 1704 | { | ||
| 1705 | ZD_ASSERT(usb_anchor_empty(&usb->submitted_cmds)); | ||
| 1706 | ZD_ASSERT(usb->urb_async_waiting == NULL); | ||
| 1707 | ZD_ASSERT(!usb->in_async); | ||
| 1708 | |||
| 1709 | ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex)); | ||
| 1710 | |||
| 1711 | usb->in_async = 1; | ||
| 1712 | usb->cmd_error = 0; | ||
| 1713 | usb->urb_async_waiting = NULL; | ||
| 1714 | } | ||
| 1715 | |||
| 1716 | int zd_usb_iowrite16v_async_end(struct zd_usb *usb, unsigned int timeout) | ||
| 1717 | { | ||
| 1718 | int r; | ||
| 1719 | |||
| 1720 | ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex)); | ||
| 1721 | ZD_ASSERT(usb->in_async); | ||
| 1722 | |||
| 1723 | /* Submit last iowrite16v URB */ | ||
| 1724 | r = zd_submit_waiting_urb(usb, true); | ||
| 1725 | if (r) { | ||
| 1726 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1727 | "error in zd_submit_waiting_usb(). " | ||
| 1728 | "Error number %d\n", r); | ||
| 1729 | |||
| 1730 | usb_kill_anchored_urbs(&usb->submitted_cmds); | ||
| 1731 | goto error; | ||
| 1732 | } | ||
| 1733 | |||
| 1734 | if (timeout) | ||
| 1735 | timeout = usb_wait_anchor_empty_timeout(&usb->submitted_cmds, | ||
| 1736 | timeout); | ||
| 1737 | if (!timeout) { | ||
| 1738 | usb_kill_anchored_urbs(&usb->submitted_cmds); | ||
| 1739 | if (usb->cmd_error == -ENOENT) { | ||
| 1740 | dev_dbg_f(zd_usb_dev(usb), "timed out"); | ||
| 1741 | r = -ETIMEDOUT; | ||
| 1742 | goto error; | ||
| 1743 | } | ||
| 1744 | } | ||
| 1745 | |||
| 1746 | r = usb->cmd_error; | ||
| 1747 | error: | ||
| 1748 | usb->in_async = 0; | ||
| 1749 | return r; | ||
| 1750 | } | ||
| 1751 | |||
| 1752 | int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | ||
| 1753 | unsigned int count) | ||
| 1668 | { | 1754 | { |
| 1669 | int r; | 1755 | int r; |
| 1670 | struct usb_device *udev; | 1756 | struct usb_device *udev; |
| 1671 | struct usb_req_write_regs *req = NULL; | 1757 | struct usb_req_write_regs *req = NULL; |
| 1672 | int i, req_len, actual_req_len; | 1758 | int i, req_len; |
| 1759 | struct urb *urb; | ||
| 1760 | struct usb_host_endpoint *ep; | ||
| 1761 | |||
| 1762 | ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex)); | ||
| 1763 | ZD_ASSERT(usb->in_async); | ||
| 1673 | 1764 | ||
| 1674 | if (count == 0) | 1765 | if (count == 0) |
| 1675 | return 0; | 1766 | return 0; |
| @@ -1685,17 +1776,23 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | |||
| 1685 | return -EWOULDBLOCK; | 1776 | return -EWOULDBLOCK; |
| 1686 | } | 1777 | } |
| 1687 | 1778 | ||
| 1688 | ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex)); | 1779 | udev = zd_usb_to_usbdev(usb); |
| 1689 | BUILD_BUG_ON(sizeof(struct usb_req_write_regs) + | 1780 | |
| 1690 | USB_MAX_IOWRITE16_COUNT * sizeof(struct reg_data) > | 1781 | ep = usb_pipe_endpoint(udev, usb_sndintpipe(udev, EP_REGS_OUT)); |
| 1691 | sizeof(usb->req_buf)); | 1782 | if (!ep) |
| 1692 | BUG_ON(sizeof(struct usb_req_write_regs) + | 1783 | return -ENOENT; |
| 1693 | count * sizeof(struct reg_data) > | 1784 | |
| 1694 | sizeof(usb->req_buf)); | 1785 | urb = usb_alloc_urb(0, GFP_KERNEL); |
| 1786 | if (!urb) | ||
| 1787 | return -ENOMEM; | ||
| 1695 | 1788 | ||
| 1696 | req_len = sizeof(struct usb_req_write_regs) + | 1789 | req_len = sizeof(struct usb_req_write_regs) + |
| 1697 | count * sizeof(struct reg_data); | 1790 | count * sizeof(struct reg_data); |
| 1698 | req = (void *)usb->req_buf; | 1791 | req = kmalloc(req_len, GFP_KERNEL); |
| 1792 | if (!req) { | ||
| 1793 | r = -ENOMEM; | ||
| 1794 | goto error; | ||
| 1795 | } | ||
| 1699 | 1796 | ||
| 1700 | req->id = cpu_to_le16(USB_REQ_WRITE_REGS); | 1797 | req->id = cpu_to_le16(USB_REQ_WRITE_REGS); |
| 1701 | for (i = 0; i < count; i++) { | 1798 | for (i = 0; i < count; i++) { |
| @@ -1704,28 +1801,44 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | |||
| 1704 | rw->value = cpu_to_le16(ioreqs[i].value); | 1801 | rw->value = cpu_to_le16(ioreqs[i].value); |
| 1705 | } | 1802 | } |
| 1706 | 1803 | ||
| 1707 | udev = zd_usb_to_usbdev(usb); | 1804 | usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT), |
| 1708 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | 1805 | req, req_len, iowrite16v_urb_complete, usb, |
| 1709 | req, req_len, &actual_req_len, 50 /* ms */); | 1806 | ep->desc.bInterval); |
| 1807 | urb->transfer_flags |= URB_FREE_BUFFER | URB_SHORT_NOT_OK; | ||
| 1808 | |||
| 1809 | /* Submit previous URB */ | ||
| 1810 | r = zd_submit_waiting_urb(usb, false); | ||
| 1710 | if (r) { | 1811 | if (r) { |
| 1711 | dev_dbg_f(zd_usb_dev(usb), | 1812 | dev_dbg_f(zd_usb_dev(usb), |
| 1712 | "error in usb_bulk_msg(). Error number %d\n", r); | 1813 | "error in zd_submit_waiting_usb(). " |
| 1713 | goto error; | 1814 | "Error number %d\n", r); |
| 1714 | } | ||
| 1715 | if (req_len != actual_req_len) { | ||
| 1716 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1717 | "error in usb_bulk_msg()" | ||
| 1718 | " req_len %d != actual_req_len %d\n", | ||
| 1719 | req_len, actual_req_len); | ||
| 1720 | r = -EIO; | ||
| 1721 | goto error; | 1815 | goto error; |
| 1722 | } | 1816 | } |
| 1723 | 1817 | ||
| 1724 | /* FALL-THROUGH with r == 0 */ | 1818 | /* Delay submit so that URB_NO_INTERRUPT flag can be set for all URBs |
| 1819 | * of currect batch except for very last. | ||
| 1820 | */ | ||
| 1821 | usb->urb_async_waiting = urb; | ||
| 1822 | return 0; | ||
| 1725 | error: | 1823 | error: |
| 1824 | usb_free_urb(urb); | ||
| 1726 | return r; | 1825 | return r; |
| 1727 | } | 1826 | } |
| 1728 | 1827 | ||
| 1828 | int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | ||
| 1829 | unsigned int count) | ||
| 1830 | { | ||
| 1831 | int r; | ||
| 1832 | |||
| 1833 | zd_usb_iowrite16v_async_start(usb); | ||
| 1834 | r = zd_usb_iowrite16v_async(usb, ioreqs, count); | ||
| 1835 | if (r) { | ||
| 1836 | zd_usb_iowrite16v_async_end(usb, 0); | ||
| 1837 | return r; | ||
| 1838 | } | ||
| 1839 | return zd_usb_iowrite16v_async_end(usb, 50 /* ms */); | ||
| 1840 | } | ||
| 1841 | |||
| 1729 | int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) | 1842 | int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) |
| 1730 | { | 1843 | { |
| 1731 | int r; | 1844 | int r; |
| @@ -1794,15 +1907,15 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) | |||
| 1794 | } | 1907 | } |
| 1795 | 1908 | ||
| 1796 | udev = zd_usb_to_usbdev(usb); | 1909 | udev = zd_usb_to_usbdev(usb); |
| 1797 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | 1910 | r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT), |
| 1798 | req, req_len, &actual_req_len, 50 /* ms */); | 1911 | req, req_len, &actual_req_len, 50 /* ms */); |
| 1799 | if (r) { | 1912 | if (r) { |
| 1800 | dev_dbg_f(zd_usb_dev(usb), | 1913 | dev_dbg_f(zd_usb_dev(usb), |
| 1801 | "error in usb_bulk_msg(). Error number %d\n", r); | 1914 | "error in usb_interrupt_msg(). Error number %d\n", r); |
| 1802 | goto out; | 1915 | goto out; |
| 1803 | } | 1916 | } |
| 1804 | if (req_len != actual_req_len) { | 1917 | if (req_len != actual_req_len) { |
| 1805 | dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()" | 1918 | dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()" |
| 1806 | " req_len %d != actual_req_len %d\n", | 1919 | " req_len %d != actual_req_len %d\n", |
| 1807 | req_len, actual_req_len); | 1920 | req_len, actual_req_len); |
| 1808 | r = -EIO; | 1921 | r = -EIO; |
