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; |