aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/zd1211rw/zd_usb.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2011-02-12 13:43:32 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-14 15:51:21 -0500
commiteefdbec1ea8b7093d2c09d1825f68438701723cf (patch)
tree6dc40b6d25f8dede0522927f48c4a716ff9c88c9 /drivers/net/wireless/zd1211rw/zd_usb.c
parent37939810b937aba830dd751291fcdc51cae1a6cb (diff)
zd1211rw: use async urb for write command
Writing beacon to device happen through multiple write command calls. zd_usb_iowrite16v uses synchronous urb call and with multiple write commands in row causes high CPU usage. This patch makes zd_usb_iowrite16v use asynchronous urb submit within zd_usb.c. zd_usb_iowrite16v_async_start is used to initiate writing multiple commands to device using zd_usb_iowrite16v_async. Each URB is delayed and submitted to device by next zd_usb_iowrite16v_async call or by call to zd_usb_iowrite16v_async_end. URBs submitted by zd_usb_iowrite16v_async have URB_NO_INTERRUPT set and last URB send by zd_usb_iowrite16v_async_end does not. This lower CPU usage when doing writes that require multiple URBs. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/zd1211rw/zd_usb.c')
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c162
1 files changed, 138 insertions, 24 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 7346512158e8..c98f6e7eed3d 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);
@@ -1663,13 +1664,104 @@ error:
1663 return r; 1664 return r;
1664} 1665}
1665 1666
1666int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, 1667static 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
1675static int zd_submit_waiting_urb(struct zd_usb *usb, bool last)
1676{
1677 int r;
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 */
1698error:
1699 usb_free_urb(urb);
1700 return r;
1701}
1702
1703static 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
1716static 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;
1747error:
1748 usb->in_async = 0;
1749 return r;
1750}
1751
1752static int zd_usb_iowrite16v_async(struct zd_usb *usb,
1753 const struct zd_ioreq16 *ioreqs,
1754 unsigned int count)
1668{ 1755{
1669 int r; 1756 int r;
1670 struct usb_device *udev; 1757 struct usb_device *udev;
1671 struct usb_req_write_regs *req = NULL; 1758 struct usb_req_write_regs *req = NULL;
1672 int i, req_len, actual_req_len; 1759 int i, req_len;
1760 struct urb *urb;
1761 struct usb_host_endpoint *ep;
1762
1763 ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
1764 ZD_ASSERT(usb->in_async);
1673 1765
1674 if (count == 0) 1766 if (count == 0)
1675 return 0; 1767 return 0;
@@ -1685,17 +1777,23 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
1685 return -EWOULDBLOCK; 1777 return -EWOULDBLOCK;
1686 } 1778 }
1687 1779
1688 ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex)); 1780 udev = zd_usb_to_usbdev(usb);
1689 BUILD_BUG_ON(sizeof(struct usb_req_write_regs) + 1781
1690 USB_MAX_IOWRITE16_COUNT * sizeof(struct reg_data) > 1782 ep = usb_pipe_endpoint(udev, usb_sndintpipe(udev, EP_REGS_OUT));
1691 sizeof(usb->req_buf)); 1783 if (!ep)
1692 BUG_ON(sizeof(struct usb_req_write_regs) + 1784 return -ENOENT;
1693 count * sizeof(struct reg_data) > 1785
1694 sizeof(usb->req_buf)); 1786 urb = usb_alloc_urb(0, GFP_KERNEL);
1787 if (!urb)
1788 return -ENOMEM;
1695 1789
1696 req_len = sizeof(struct usb_req_write_regs) + 1790 req_len = sizeof(struct usb_req_write_regs) +
1697 count * sizeof(struct reg_data); 1791 count * sizeof(struct reg_data);
1698 req = (void *)usb->req_buf; 1792 req = kmalloc(req_len, GFP_KERNEL);
1793 if (!req) {
1794 r = -ENOMEM;
1795 goto error;
1796 }
1699 1797
1700 req->id = cpu_to_le16(USB_REQ_WRITE_REGS); 1798 req->id = cpu_to_le16(USB_REQ_WRITE_REGS);
1701 for (i = 0; i < count; i++) { 1799 for (i = 0; i < count; i++) {
@@ -1704,28 +1802,44 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
1704 rw->value = cpu_to_le16(ioreqs[i].value); 1802 rw->value = cpu_to_le16(ioreqs[i].value);
1705 } 1803 }
1706 1804
1707 udev = zd_usb_to_usbdev(usb); 1805 usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT),
1708 r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT), 1806 req, req_len, iowrite16v_urb_complete, usb,
1709 req, req_len, &actual_req_len, 50 /* ms */); 1807 ep->desc.bInterval);
1808 urb->transfer_flags |= URB_FREE_BUFFER | URB_SHORT_NOT_OK;
1809
1810 /* Submit previous URB */
1811 r = zd_submit_waiting_urb(usb, false);
1710 if (r) { 1812 if (r) {
1711 dev_dbg_f(zd_usb_dev(usb), 1813 dev_dbg_f(zd_usb_dev(usb),
1712 "error in usb_interrupt_msg(). Error number %d\n", r); 1814 "error in zd_submit_waiting_usb(). "
1713 goto error; 1815 "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_interrupt_msg()"
1718 " req_len %d != actual_req_len %d\n",
1719 req_len, actual_req_len);
1720 r = -EIO;
1721 goto error; 1816 goto error;
1722 } 1817 }
1723 1818
1724 /* FALL-THROUGH with r == 0 */ 1819 /* Delay submit so that URB_NO_INTERRUPT flag can be set for all URBs
1820 * of currect batch except for very last.
1821 */
1822 usb->urb_async_waiting = urb;
1823 return 0;
1725error: 1824error:
1825 usb_free_urb(urb);
1726 return r; 1826 return r;
1727} 1827}
1728 1828
1829int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
1830 unsigned int count)
1831{
1832 int r;
1833
1834 zd_usb_iowrite16v_async_start(usb);
1835 r = zd_usb_iowrite16v_async(usb, ioreqs, count);
1836 if (r) {
1837 zd_usb_iowrite16v_async_end(usb, 0);
1838 return r;
1839 }
1840 return zd_usb_iowrite16v_async_end(usb, 50 /* ms */);
1841}
1842
1729int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) 1843int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
1730{ 1844{
1731 int r; 1845 int r;