aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorYoshihiro Shimoda <shimoda.yoshihiro@renesas.com>2008-04-10 08:05:47 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-04-25 00:16:49 -0400
commit6d8791076c7742c65dd796ae0ac260ab22e85517 (patch)
tree402ec1f9c417e09db52c39081dc57fbe278eedfb /drivers
parent97af0a911bfb1e798c395c6ebabb4731f821736f (diff)
USB: r8a66597-hcd: fix interrupt transfer interval
This driver ignored the value of bInterval and revised the problem that performed interrupt transfer. ASIX USB Ethernet adapter comes to work with this host controller by applying this patch. Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/r8a66597-hcd.c77
-rw-r--r--drivers/usb/host/r8a66597.h3
2 files changed, 70 insertions, 10 deletions
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index b46ff9a80b66..dac2f7dd69b9 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
46MODULE_AUTHOR("Yoshihiro Shimoda"); 46MODULE_AUTHOR("Yoshihiro Shimoda");
47MODULE_ALIAS("platform:r8a66597_hcd"); 47MODULE_ALIAS("platform:r8a66597_hcd");
48 48
49#define DRIVER_VERSION "29 May 2007" 49#define DRIVER_VERSION "10 Apr 2008"
50 50
51static const char hcd_name[] = "r8a66597_hcd"; 51static const char hcd_name[] = "r8a66597_hcd";
52 52
@@ -577,13 +577,9 @@ static void pipe_buffer_setting(struct r8a66597 *r8a66597,
577 PIPEBUF); 577 PIPEBUF);
578 r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket, 578 r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket,
579 PIPEMAXP); 579 PIPEMAXP);
580 if (info->interval)
581 info->interval--;
582 r8a66597_write(r8a66597, info->interval, PIPEPERI); 580 r8a66597_write(r8a66597, info->interval, PIPEPERI);
583} 581}
584 582
585
586
587/* this function must be called with interrupt disabled */ 583/* this function must be called with interrupt disabled */
588static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td) 584static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td)
589{ 585{
@@ -825,6 +821,25 @@ static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597,
825 dev->dma_map = 0; 821 dev->dma_map = 0;
826} 822}
827 823
824static unsigned long get_timer_interval(struct urb *urb, __u8 interval)
825{
826 __u8 i;
827 unsigned long time = 1;
828
829 if (usb_pipeisoc(urb->pipe))
830 return 0;
831
832 if (get_r8a66597_usb_speed(urb->dev->speed) == HSMODE) {
833 for (i = 0; i < (interval - 1); i++)
834 time *= 2;
835 time = time * 125 / 1000; /* uSOF -> msec */
836 } else {
837 time = interval;
838 }
839
840 return time;
841}
842
828/* this function must be called with interrupt disabled */ 843/* this function must be called with interrupt disabled */
829static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, 844static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
830 struct usb_host_endpoint *hep, 845 struct usb_host_endpoint *hep,
@@ -840,7 +855,16 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
840 & USB_ENDPOINT_XFERTYPE_MASK); 855 & USB_ENDPOINT_XFERTYPE_MASK);
841 info.bufnum = get_bufnum(info.pipenum); 856 info.bufnum = get_bufnum(info.pipenum);
842 info.buf_bsize = get_buf_bsize(info.pipenum); 857 info.buf_bsize = get_buf_bsize(info.pipenum);
843 info.interval = ep->bInterval; 858 if (info.type == R8A66597_BULK) {
859 info.interval = 0;
860 info.timer_interval = 0;
861 } else {
862 if (ep->bInterval > IITV)
863 info.interval = IITV;
864 else
865 info.interval = ep->bInterval ? ep->bInterval - 1 : 0;
866 info.timer_interval = get_timer_interval(urb, ep->bInterval);
867 }
844 if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) 868 if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
845 info.dir_in = 1; 869 info.dir_in = 1;
846 else 870 else
@@ -1582,6 +1606,29 @@ static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port)
1582 } 1606 }
1583} 1607}
1584 1608
1609static void r8a66597_interval_timer(unsigned long _r8a66597)
1610{
1611 struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
1612 unsigned long flags;
1613 u16 pipenum;
1614 struct r8a66597_td *td;
1615
1616 spin_lock_irqsave(&r8a66597->lock, flags);
1617
1618 for (pipenum = 0; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
1619 if (!(r8a66597->interval_map & (1 << pipenum)))
1620 continue;
1621 if (timer_pending(&r8a66597->interval_timer[pipenum]))
1622 continue;
1623
1624 td = r8a66597_get_td(r8a66597, pipenum);
1625 if (td)
1626 start_transfer(r8a66597, td);
1627 }
1628
1629 spin_unlock_irqrestore(&r8a66597->lock, flags);
1630}
1631
1585static void r8a66597_td_timer(unsigned long _r8a66597) 1632static void r8a66597_td_timer(unsigned long _r8a66597)
1586{ 1633{
1587 struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; 1634 struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
@@ -1763,10 +1810,17 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
1763 urb->hcpriv = td; 1810 urb->hcpriv = td;
1764 1811
1765 if (request) { 1812 if (request) {
1766 ret = start_transfer(r8a66597, td); 1813 if (td->pipe->info.timer_interval) {
1767 if (ret < 0) { 1814 r8a66597->interval_map |= 1 << td->pipenum;
1768 list_del(&td->queue); 1815 mod_timer(&r8a66597->interval_timer[td->pipenum],
1769 kfree(td); 1816 jiffies + msecs_to_jiffies(
1817 td->pipe->info.timer_interval));
1818 } else {
1819 ret = start_transfer(r8a66597, td);
1820 if (ret < 0) {
1821 list_del(&td->queue);
1822 kfree(td);
1823 }
1770 } 1824 }
1771 } else 1825 } else
1772 set_td_timer(r8a66597, td); 1826 set_td_timer(r8a66597, td);
@@ -2192,6 +2246,9 @@ static int __init r8a66597_probe(struct platform_device *pdev)
2192 init_timer(&r8a66597->td_timer[i]); 2246 init_timer(&r8a66597->td_timer[i]);
2193 r8a66597->td_timer[i].function = r8a66597_td_timer; 2247 r8a66597->td_timer[i].function = r8a66597_td_timer;
2194 r8a66597->td_timer[i].data = (unsigned long)r8a66597; 2248 r8a66597->td_timer[i].data = (unsigned long)r8a66597;
2249 setup_timer(&r8a66597->interval_timer[i],
2250 r8a66597_interval_timer,
2251 (unsigned long)r8a66597);
2195 } 2252 }
2196 INIT_LIST_HEAD(&r8a66597->child_device); 2253 INIT_LIST_HEAD(&r8a66597->child_device);
2197 2254
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
index 57388252b693..a01461017ad6 100644
--- a/drivers/usb/host/r8a66597.h
+++ b/drivers/usb/host/r8a66597.h
@@ -404,6 +404,7 @@
404#define make_devsel(addr) (addr << 12) 404#define make_devsel(addr) (addr << 12)
405 405
406struct r8a66597_pipe_info { 406struct r8a66597_pipe_info {
407 unsigned long timer_interval;
407 u16 pipenum; 408 u16 pipenum;
408 u16 address; /* R8A66597 HCD usb address */ 409 u16 address; /* R8A66597 HCD usb address */
409 u16 epnum; 410 u16 epnum;
@@ -478,9 +479,11 @@ struct r8a66597 {
478 479
479 struct timer_list rh_timer; 480 struct timer_list rh_timer;
480 struct timer_list td_timer[R8A66597_MAX_NUM_PIPE]; 481 struct timer_list td_timer[R8A66597_MAX_NUM_PIPE];
482 struct timer_list interval_timer[R8A66597_MAX_NUM_PIPE];
481 483
482 unsigned short address_map; 484 unsigned short address_map;
483 unsigned short timeout_map; 485 unsigned short timeout_map;
486 unsigned short interval_map;
484 unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE]; 487 unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
485 unsigned char dma_map; 488 unsigned char dma_map;
486 489