diff options
author | Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 2011-05-30 03:15:47 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-05-31 14:47:26 -0400 |
commit | 59342f6a6bc35df623fb44784daa5e1077063b8f (patch) | |
tree | 612d3ec8c09d18fb0a97f841a535de8b25e46ada /drivers/net | |
parent | 66870b1ccd5c1460e437c18b0026e2dcaab1ece9 (diff) |
zd1211rw: fix to work on OHCI
zd1211 devices register 'EP 4 OUT' endpoint as Interrupt type on USB 2.0:
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x04 EP 4 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
However on USB 1.1 endpoint becomes Bulk:
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x04 EP 4 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Commit 37939810b937aba830dd751291fcdc51cae1a6cb assumed that endpoint is
always interrupt type and changed usb_bulk_msg() calls to usb_interrupt_msg().
Problem here is that usb_bulk_msg() on interrupt endpoint selfcorrects the
call and changes requested pipe to interrupt type (see usb_bulk_msg).
However with usb_interrupt_msg() on bulk endpoint does not correct the
pipe type to bulk, but instead URB is submitted with interrupt type pipe.
So pre-2.6.39 used usb_bulk_msg() and therefore worked with both endpoint
types, however in 2.6.39 usb_interrupt_msg() with bulk endpoint causes
ohci_hcd to fail submitted URB instantly with -ENOSPC and preventing zd1211rw
from working with OHCI.
Fix this by detecting endpoint type and using correct endpoint/pipe types
for URB. Also fix asynchronous zd_usb_iowrite16v_async() to use right
URB type on 'EP 4 OUT'.
Cc: stable@kernel.org
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_usb.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 0e819943b9e4..631194d49828 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -1533,6 +1533,31 @@ static void __exit usb_exit(void) | |||
1533 | module_init(usb_init); | 1533 | module_init(usb_init); |
1534 | module_exit(usb_exit); | 1534 | module_exit(usb_exit); |
1535 | 1535 | ||
1536 | static int zd_ep_regs_out_msg(struct usb_device *udev, void *data, int len, | ||
1537 | int *actual_length, int timeout) | ||
1538 | { | ||
1539 | /* In USB 2.0 mode EP_REGS_OUT endpoint is interrupt type. However in | ||
1540 | * USB 1.1 mode endpoint is bulk. Select correct type URB by endpoint | ||
1541 | * descriptor. | ||
1542 | */ | ||
1543 | struct usb_host_endpoint *ep; | ||
1544 | unsigned int pipe; | ||
1545 | |||
1546 | pipe = usb_sndintpipe(udev, EP_REGS_OUT); | ||
1547 | ep = usb_pipe_endpoint(udev, pipe); | ||
1548 | if (!ep) | ||
1549 | return -EINVAL; | ||
1550 | |||
1551 | if (usb_endpoint_xfer_int(&ep->desc)) { | ||
1552 | return usb_interrupt_msg(udev, pipe, data, len, | ||
1553 | actual_length, timeout); | ||
1554 | } else { | ||
1555 | pipe = usb_sndbulkpipe(udev, EP_REGS_OUT); | ||
1556 | return usb_bulk_msg(udev, pipe, data, len, actual_length, | ||
1557 | timeout); | ||
1558 | } | ||
1559 | } | ||
1560 | |||
1536 | static int usb_int_regs_length(unsigned int count) | 1561 | static int usb_int_regs_length(unsigned int count) |
1537 | { | 1562 | { |
1538 | return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data); | 1563 | return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data); |
@@ -1648,15 +1673,14 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, | |||
1648 | 1673 | ||
1649 | udev = zd_usb_to_usbdev(usb); | 1674 | udev = zd_usb_to_usbdev(usb); |
1650 | prepare_read_regs_int(usb); | 1675 | prepare_read_regs_int(usb); |
1651 | r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT), | 1676 | r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/); |
1652 | req, req_len, &actual_req_len, 50 /* ms */); | ||
1653 | if (r) { | 1677 | if (r) { |
1654 | dev_dbg_f(zd_usb_dev(usb), | 1678 | dev_dbg_f(zd_usb_dev(usb), |
1655 | "error in usb_interrupt_msg(). Error number %d\n", r); | 1679 | "error in zd_ep_regs_out_msg(). Error number %d\n", r); |
1656 | goto error; | 1680 | goto error; |
1657 | } | 1681 | } |
1658 | if (req_len != actual_req_len) { | 1682 | if (req_len != actual_req_len) { |
1659 | dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()\n" | 1683 | dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()\n" |
1660 | " req_len %d != actual_req_len %d\n", | 1684 | " req_len %d != actual_req_len %d\n", |
1661 | req_len, actual_req_len); | 1685 | req_len, actual_req_len); |
1662 | r = -EIO; | 1686 | r = -EIO; |
@@ -1818,9 +1842,17 @@ int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | |||
1818 | rw->value = cpu_to_le16(ioreqs[i].value); | 1842 | rw->value = cpu_to_le16(ioreqs[i].value); |
1819 | } | 1843 | } |
1820 | 1844 | ||
1821 | usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT), | 1845 | /* In USB 2.0 mode endpoint is interrupt type. However in USB 1.1 mode |
1822 | req, req_len, iowrite16v_urb_complete, usb, | 1846 | * endpoint is bulk. Select correct type URB by endpoint descriptor. |
1823 | ep->desc.bInterval); | 1847 | */ |
1848 | if (usb_endpoint_xfer_int(&ep->desc)) | ||
1849 | usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT), | ||
1850 | req, req_len, iowrite16v_urb_complete, usb, | ||
1851 | ep->desc.bInterval); | ||
1852 | else | ||
1853 | usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | ||
1854 | req, req_len, iowrite16v_urb_complete, usb); | ||
1855 | |||
1824 | urb->transfer_flags |= URB_FREE_BUFFER; | 1856 | urb->transfer_flags |= URB_FREE_BUFFER; |
1825 | 1857 | ||
1826 | /* Submit previous URB */ | 1858 | /* Submit previous URB */ |
@@ -1924,15 +1956,14 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) | |||
1924 | } | 1956 | } |
1925 | 1957 | ||
1926 | udev = zd_usb_to_usbdev(usb); | 1958 | udev = zd_usb_to_usbdev(usb); |
1927 | r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT), | 1959 | r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/); |
1928 | req, req_len, &actual_req_len, 50 /* ms */); | ||
1929 | if (r) { | 1960 | if (r) { |
1930 | dev_dbg_f(zd_usb_dev(usb), | 1961 | dev_dbg_f(zd_usb_dev(usb), |
1931 | "error in usb_interrupt_msg(). Error number %d\n", r); | 1962 | "error in zd_ep_regs_out_msg(). Error number %d\n", r); |
1932 | goto out; | 1963 | goto out; |
1933 | } | 1964 | } |
1934 | if (req_len != actual_req_len) { | 1965 | if (req_len != actual_req_len) { |
1935 | dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()" | 1966 | dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()" |
1936 | " req_len %d != actual_req_len %d\n", | 1967 | " req_len %d != actual_req_len %d\n", |
1937 | req_len, actual_req_len); | 1968 | req_len, actual_req_len); |
1938 | r = -EIO; | 1969 | r = -EIO; |