Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 93351
b: refs/heads/master
c: 6d87910
h: refs/heads/master
i:
  93349: 5b8044a
  93347: 962c69f
  93343: 77c75e7
v: v3
  • Loading branch information
Yoshihiro Shimoda authored and Greg Kroah-Hartman committed Apr 25, 2008
1 parent afd67e1 commit 6b5e35d
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 97af0a911bfb1e798c395c6ebabb4731f821736f
refs/heads/master: 6d8791076c7742c65dd796ae0ac260ab22e85517
77 changes: 67 additions & 10 deletions trunk/drivers/usb/host/r8a66597-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yoshihiro Shimoda");
MODULE_ALIAS("platform:r8a66597_hcd");

#define DRIVER_VERSION "29 May 2007"
#define DRIVER_VERSION "10 Apr 2008"

static const char hcd_name[] = "r8a66597_hcd";

Expand Down Expand Up @@ -577,13 +577,9 @@ static void pipe_buffer_setting(struct r8a66597 *r8a66597,
PIPEBUF);
r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket,
PIPEMAXP);
if (info->interval)
info->interval--;
r8a66597_write(r8a66597, info->interval, PIPEPERI);
}



/* this function must be called with interrupt disabled */
static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td)
{
Expand Down Expand Up @@ -825,6 +821,25 @@ static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597,
dev->dma_map = 0;
}

static unsigned long get_timer_interval(struct urb *urb, __u8 interval)
{
__u8 i;
unsigned long time = 1;

if (usb_pipeisoc(urb->pipe))
return 0;

if (get_r8a66597_usb_speed(urb->dev->speed) == HSMODE) {
for (i = 0; i < (interval - 1); i++)
time *= 2;
time = time * 125 / 1000; /* uSOF -> msec */
} else {
time = interval;
}

return time;
}

/* this function must be called with interrupt disabled */
static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
struct usb_host_endpoint *hep,
Expand All @@ -840,7 +855,16 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
& USB_ENDPOINT_XFERTYPE_MASK);
info.bufnum = get_bufnum(info.pipenum);
info.buf_bsize = get_buf_bsize(info.pipenum);
info.interval = ep->bInterval;
if (info.type == R8A66597_BULK) {
info.interval = 0;
info.timer_interval = 0;
} else {
if (ep->bInterval > IITV)
info.interval = IITV;
else
info.interval = ep->bInterval ? ep->bInterval - 1 : 0;
info.timer_interval = get_timer_interval(urb, ep->bInterval);
}
if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
info.dir_in = 1;
else
Expand Down Expand Up @@ -1582,6 +1606,29 @@ static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port)
}
}

static void r8a66597_interval_timer(unsigned long _r8a66597)
{
struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
unsigned long flags;
u16 pipenum;
struct r8a66597_td *td;

spin_lock_irqsave(&r8a66597->lock, flags);

for (pipenum = 0; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
if (!(r8a66597->interval_map & (1 << pipenum)))
continue;
if (timer_pending(&r8a66597->interval_timer[pipenum]))
continue;

td = r8a66597_get_td(r8a66597, pipenum);
if (td)
start_transfer(r8a66597, td);
}

spin_unlock_irqrestore(&r8a66597->lock, flags);
}

static void r8a66597_td_timer(unsigned long _r8a66597)
{
struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
Expand Down Expand Up @@ -1763,10 +1810,17 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
urb->hcpriv = td;

if (request) {
ret = start_transfer(r8a66597, td);
if (ret < 0) {
list_del(&td->queue);
kfree(td);
if (td->pipe->info.timer_interval) {
r8a66597->interval_map |= 1 << td->pipenum;
mod_timer(&r8a66597->interval_timer[td->pipenum],
jiffies + msecs_to_jiffies(
td->pipe->info.timer_interval));
} else {
ret = start_transfer(r8a66597, td);
if (ret < 0) {
list_del(&td->queue);
kfree(td);
}
}
} else
set_td_timer(r8a66597, td);
Expand Down Expand Up @@ -2192,6 +2246,9 @@ static int __init r8a66597_probe(struct platform_device *pdev)
init_timer(&r8a66597->td_timer[i]);
r8a66597->td_timer[i].function = r8a66597_td_timer;
r8a66597->td_timer[i].data = (unsigned long)r8a66597;
setup_timer(&r8a66597->interval_timer[i],
r8a66597_interval_timer,
(unsigned long)r8a66597);
}
INIT_LIST_HEAD(&r8a66597->child_device);

Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/usb/host/r8a66597.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@
#define make_devsel(addr) (addr << 12)

struct r8a66597_pipe_info {
unsigned long timer_interval;
u16 pipenum;
u16 address; /* R8A66597 HCD usb address */
u16 epnum;
Expand Down Expand Up @@ -478,9 +479,11 @@ struct r8a66597 {

struct timer_list rh_timer;
struct timer_list td_timer[R8A66597_MAX_NUM_PIPE];
struct timer_list interval_timer[R8A66597_MAX_NUM_PIPE];

unsigned short address_map;
unsigned short timeout_map;
unsigned short interval_map;
unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
unsigned char dma_map;

Expand Down

0 comments on commit 6b5e35d

Please sign in to comment.