From d2066eb659e6ee915383510c136da38eff86ef15 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Fri, 13 Jul 2007 21:26:59 +0200 Subject: USB: use mutex instead of semaphore in the ELAN U132 adapter driver The ELAN U132 adapter driver uses the semaphore u132_module_lock as mutex. Use the mutex API instead of the (binary) semaphore. Signed-off-by: Matthias Kaehlcke Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/u132-hcd.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index e98df2ee9901..7f765ec038cd 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -83,7 +84,7 @@ static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait); * u132_module_lock exists to protect access to global variables * */ -static struct semaphore u132_module_lock; +static struct mutex u132_module_lock; static int u132_exiting = 0; static int u132_instances = 0; static struct list_head u132_static_list; @@ -258,10 +259,10 @@ static void u132_hcd_delete(struct kref *kref) struct platform_device *pdev = u132->platform_dev; struct usb_hcd *hcd = u132_to_hcd(u132); u132->going += 1; - down(&u132_module_lock); + mutex_lock(&u132_module_lock); list_del_init(&u132->u132_list); u132_instances -= 1; - up(&u132_module_lock); + mutex_unlock(&u132_module_lock); dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13" "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev); usb_put_hcd(hcd); @@ -3111,10 +3112,10 @@ static int __devinit u132_probe(struct platform_device *pdev) int retval = 0; struct u132 *u132 = hcd_to_u132(hcd); hcd->rsrc_start = 0; - down(&u132_module_lock); + mutex_lock(&u132_module_lock); list_add_tail(&u132->u132_list, &u132_static_list); u132->sequence_num = ++u132_instances; - up(&u132_module_lock); + mutex_unlock(&u132_module_lock); u132_u132_init_kref(u132); u132_initialise(u132, pdev); hcd->product_desc = "ELAN U132 Host Controller"; @@ -3216,7 +3217,7 @@ static int __init u132_hcd_init(void) INIT_LIST_HEAD(&u132_static_list); u132_instances = 0; u132_exiting = 0; - init_MUTEX(&u132_module_lock); + mutex_init(&u132_module_lock); if (usb_disabled()) return -ENODEV; printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__, @@ -3232,9 +3233,9 @@ static void __exit u132_hcd_exit(void) { struct u132 *u132; struct u132 *temp; - down(&u132_module_lock); + mutex_lock(&u132_module_lock); u132_exiting += 1; - up(&u132_module_lock); + mutex_unlock(&u132_module_lock); list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) { platform_device_unregister(u132->platform_dev); } platform_driver_unregister(&u132_platform_driver); -- cgit v1.2.3 From 1b4cd43bd3f9aa7a794e29b80b0d984a8e144df4 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Jul 2007 17:03:01 -0400 Subject: isp116x-hcd: prepare for urb->status This patch (as931b), adapted from a patch by Olav Kongas, makes a small set of conservative changes to the isp116x-hcd driver in preparation for the removal of urb->status. finish_request() is moved up in the source and is called as soon as the URB is known to have completed, rather than after all the active endpoints have been scanned. The status of a completed URB is kept in a local variable and copied to urb->status only when the URB is about to be given back. -EREMOTEIO error status for control transfers is set after the status stage rather than when the short packet arrives. Some unnecessary uses of urb->lock are removed. Signed-off-by: Alan Stern Cc: Olav Kongas Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp116x-hcd.c | 187 +++++++++++++++++++---------------------- 1 file changed, 86 insertions(+), 101 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 46873f2534b5..5c851a36de72 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -228,7 +228,6 @@ static void preproc_atl_queue(struct isp116x *isp116x) struct urb, urb_list); ptd = &ep->ptd; len = ep->length; - spin_lock(&urb->lock); ep->data = (unsigned char *)urb->transfer_buffer + urb->actual_length; @@ -264,7 +263,6 @@ static void preproc_atl_queue(struct isp116x *isp116x) | PTD_EP(ep->epnum); ptd->len = PTD_LEN(len) | PTD_DIR(dir); ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe)); - spin_unlock(&urb->lock); if (!ep->active) { ptd->mps |= PTD_LAST_MSK; isp116x->atl_last_dir = dir; @@ -274,6 +272,61 @@ static void preproc_atl_queue(struct isp116x *isp116x) } } +/* + Take done or failed requests out of schedule. Give back + processed urbs. +*/ +static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep, + struct urb *urb) +__releases(isp116x->lock) __acquires(isp116x->lock) +{ + unsigned i; + + urb->hcpriv = NULL; + ep->error_count = 0; + + if (usb_pipecontrol(urb->pipe)) + ep->nextpid = USB_PID_SETUP; + + urb_dbg(urb, "Finish"); + + spin_unlock(&isp116x->lock); + usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb); + spin_lock(&isp116x->lock); + + /* take idle endpoints out of the schedule */ + if (!list_empty(&ep->hep->urb_list)) + return; + + /* async deschedule */ + if (!list_empty(&ep->schedule)) { + list_del_init(&ep->schedule); + return; + } + + /* periodic deschedule */ + DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); + for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { + struct isp116x_ep *temp; + struct isp116x_ep **prev = &isp116x->periodic[i]; + + while (*prev && ((temp = *prev) != ep)) + prev = &temp->next; + if (*prev) + *prev = ep->next; + isp116x->load[i] -= ep->load; + } + ep->branch = PERIODIC_SIZE; + isp116x_to_hcd(isp116x)->self.bandwidth_allocated -= + ep->load / ep->period; + + /* switch irq type? */ + if (!--isp116x->periodic_count) { + isp116x->irqenb &= ~HCuPINT_SOF; + isp116x->irqenb |= HCuPINT_ATL; + } +} + /* Analyze transfer results, handle partial transfers and errors */ @@ -284,6 +337,7 @@ static void postproc_atl_queue(struct isp116x *isp116x) struct usb_device *udev; struct ptd *ptd; int short_not_ok; + int status; u8 cc; for (ep = isp116x->atl_active; ep; ep = ep->active) { @@ -294,7 +348,7 @@ static void postproc_atl_queue(struct isp116x *isp116x) ptd = &ep->ptd; cc = PTD_GET_CC(ptd); short_not_ok = 1; - spin_lock(&urb->lock); + status = -EINPROGRESS; /* Data underrun is special. For allowed underrun we clear the error and continue as normal. For @@ -302,47 +356,36 @@ static void postproc_atl_queue(struct isp116x *isp116x) immediately while for control transfer, we do a STATUS stage. */ if (cc == TD_DATAUNDERRUN) { - if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) { - DBG("Allowed data underrun\n"); + if (!(urb->transfer_flags & URB_SHORT_NOT_OK) || + usb_pipecontrol(urb->pipe)) { + DBG("Allowed or control data underrun\n"); cc = TD_CC_NOERROR; short_not_ok = 0; } else { ep->error_count = 1; - if (usb_pipecontrol(urb->pipe)) - ep->nextpid = USB_PID_ACK; - else - usb_settoggle(udev, ep->epnum, - ep->nextpid == - USB_PID_OUT, - PTD_GET_TOGGLE(ptd)); + usb_settoggle(udev, ep->epnum, + ep->nextpid == USB_PID_OUT, + PTD_GET_TOGGLE(ptd)); urb->actual_length += PTD_GET_COUNT(ptd); - urb->status = cc_to_error[TD_DATAUNDERRUN]; - spin_unlock(&urb->lock); - continue; + status = cc_to_error[TD_DATAUNDERRUN]; + goto done; } } - /* Keep underrun error through the STATUS stage */ - if (urb->status == cc_to_error[TD_DATAUNDERRUN]) - cc = TD_DATAUNDERRUN; if (cc != TD_CC_NOERROR && cc != TD_NOTACCESSED && (++ep->error_count >= 3 || cc == TD_CC_STALL || cc == TD_DATAOVERRUN)) { - if (urb->status == -EINPROGRESS) - urb->status = cc_to_error[cc]; + status = cc_to_error[cc]; if (ep->nextpid == USB_PID_ACK) ep->nextpid = 0; - spin_unlock(&urb->lock); - continue; + goto done; } /* According to usb spec, zero-length Int transfer signals finishing of the urb. Hey, does this apply only for IN endpoints? */ if (usb_pipeint(urb->pipe) && !PTD_GET_LEN(ptd)) { - if (urb->status == -EINPROGRESS) - urb->status = 0; - spin_unlock(&urb->lock); - continue; + status = 0; + goto done; } /* Relax after previously failed, but later succeeded @@ -381,8 +424,8 @@ static void postproc_atl_queue(struct isp116x *isp116x) /* All data for this URB is transferred, let's finish */ if (usb_pipecontrol(urb->pipe)) ep->nextpid = USB_PID_ACK; - else if (urb->status == -EINPROGRESS) - urb->status = 0; + else + status = 0; break; case USB_PID_SETUP: if (PTD_GET_ACTIVE(ptd) @@ -402,69 +445,27 @@ static void postproc_atl_queue(struct isp116x *isp116x) if (PTD_GET_ACTIVE(ptd) || (cc != TD_CC_NOERROR && cc < 0x0E)) break; - if (urb->status == -EINPROGRESS) - urb->status = 0; + if ((urb->transfer_flags & URB_SHORT_NOT_OK) && + urb->actual_length < + urb->transfer_buffer_length) + status = -EREMOTEIO; + else + status = 0; ep->nextpid = 0; break; default: BUG(); } - spin_unlock(&urb->lock); - } -} - -/* - Take done or failed requests out of schedule. Give back - processed urbs. -*/ -static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep, - struct urb *urb) -__releases(isp116x->lock) __acquires(isp116x->lock) -{ - unsigned i; - - urb->hcpriv = NULL; - ep->error_count = 0; - - if (usb_pipecontrol(urb->pipe)) - ep->nextpid = USB_PID_SETUP; - - urb_dbg(urb, "Finish"); - - spin_unlock(&isp116x->lock); - usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb); - spin_lock(&isp116x->lock); - - /* take idle endpoints out of the schedule */ - if (!list_empty(&ep->hep->urb_list)) - return; - - /* async deschedule */ - if (!list_empty(&ep->schedule)) { - list_del_init(&ep->schedule); - return; - } - /* periodic deschedule */ - DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); - for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { - struct isp116x_ep *temp; - struct isp116x_ep **prev = &isp116x->periodic[i]; - - while (*prev && ((temp = *prev) != ep)) - prev = &temp->next; - if (*prev) - *prev = ep->next; - isp116x->load[i] -= ep->load; - } - ep->branch = PERIODIC_SIZE; - isp116x_to_hcd(isp116x)->self.bandwidth_allocated -= - ep->load / ep->period; - - /* switch irq type? */ - if (!--isp116x->periodic_count) { - isp116x->irqenb &= ~HCuPINT_SOF; - isp116x->irqenb |= HCuPINT_ATL; + done: + if (status != -EINPROGRESS) { + spin_lock(&urb->lock); + if (urb->status == -EINPROGRESS) + urb->status = status; + spin_unlock(&urb->lock); + } + if (urb->status != -EINPROGRESS) + finish_request(isp116x, ep, urb); } } @@ -570,9 +571,6 @@ static void start_atl_transfers(struct isp116x *isp116x) */ static void finish_atl_transfers(struct isp116x *isp116x) { - struct isp116x_ep *ep; - struct urb *urb; - if (!isp116x->atl_active) return; /* Fifo not ready? */ @@ -582,16 +580,6 @@ static void finish_atl_transfers(struct isp116x *isp116x) atomic_inc(&isp116x->atl_finishing); unpack_fifo(isp116x); postproc_atl_queue(isp116x); - for (ep = isp116x->atl_active; ep; ep = ep->active) { - urb = - container_of(ep->hep->urb_list.next, struct urb, urb_list); - /* USB_PID_ACK check here avoids finishing of - control transfers, for which TD_DATAUNDERRUN - occured, while URB_SHORT_NOT_OK was set */ - if (urb && urb->status != -EINPROGRESS - && ep->nextpid != USB_PID_ACK) - finish_request(isp116x, ep, urb); - } atomic_dec(&isp116x->atl_finishing); } @@ -821,15 +809,12 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, } /* in case of unlink-during-submit */ - spin_lock(&urb->lock); if (urb->status != -EINPROGRESS) { - spin_unlock(&urb->lock); finish_request(isp116x, ep, urb); ret = 0; goto fail; } urb->hcpriv = hep; - spin_unlock(&urb->lock); start_atl_transfers(isp116x); fail: -- cgit v1.2.3 From e7e7c360fb07020b24652843aec442325baad0ce Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 13 Jul 2007 15:46:29 -0400 Subject: UHCI: short control URBs get a status stage It has recently been pointed out that short control transfers should have a status stage, even if they generate an error because URB_SHORT_NOT_OK was set. This patch (as935) changes uhci-hcd to enable the status stage when this happens. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-q.c | 59 ++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 21 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 4aed305982ec..3bb908ca38e9 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -827,8 +827,10 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, * If direction is "send", change the packet ID from SETUP (0x2D) * to OUT (0xE1). Else change it from SETUP to IN (0x69) and * set Short Packet Detect (SPD) for all data packets. + * + * 0-length transfers always get treated as "send". */ - if (usb_pipeout(urb->pipe)) + if (usb_pipeout(urb->pipe) || len == 0) destination ^= (USB_PID_SETUP ^ USB_PID_OUT); else { destination ^= (USB_PID_SETUP ^ USB_PID_IN); @@ -839,7 +841,12 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, * Build the DATA TDs */ while (len > 0) { - int pktsze = min(len, maxsze); + int pktsze = maxsze; + + if (len <= pktsze) { /* The last data packet */ + pktsze = len; + status &= ~TD_CTRL_SPD; + } td = uhci_alloc_td(uhci); if (!td) @@ -866,20 +873,10 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, goto nomem; *plink = LINK_TO_TD(td); - /* - * It's IN if the pipe is an output pipe or we're not expecting - * data back. - */ - destination &= ~TD_TOKEN_PID_MASK; - if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length) - destination |= USB_PID_IN; - else - destination |= USB_PID_OUT; - + /* Change direction for the status transaction */ + destination ^= (USB_PID_IN ^ USB_PID_OUT); destination |= TD_TOKEN_TOGGLE; /* End in Data1 */ - status &= ~TD_CTRL_SPD; - uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status | TD_CTRL_IOC, destination | uhci_explen(0), 0); @@ -1185,10 +1182,18 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) } } + /* Did we receive a short packet? */ } else if (len < uhci_expected_length(td_token(td))) { - /* We received a short packet */ - if (urb->transfer_flags & URB_SHORT_NOT_OK) + /* For control transfers, go to the status TD if + * this isn't already the last data TD */ + if (qh->type == USB_ENDPOINT_XFER_CONTROL) { + if (td->list.next != urbp->td_list.prev) + ret = 1; + } + + /* For bulk and interrupt, this may be an error */ + else if (urb->transfer_flags & URB_SHORT_NOT_OK) ret = -EREMOTEIO; /* Fixup needed only if this isn't the URB's last TD */ @@ -1208,10 +1213,6 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) err: if (ret < 0) { - /* In case a control transfer gets an error - * during the setup stage */ - urb->actual_length = max(urb->actual_length, 0); - /* Note that the queue has stopped and save * the next toggle value */ qh->element = UHCI_PTR_TERM; @@ -1489,9 +1490,25 @@ __acquires(uhci->lock) { struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; + if (qh->type == USB_ENDPOINT_XFER_CONTROL) { + + /* urb->actual_length < 0 means the setup transaction didn't + * complete successfully. Either it failed or the URB was + * unlinked first. Regardless, don't confuse people with a + * negative length. */ + urb->actual_length = max(urb->actual_length, 0); + + /* Report erroneous short transfers */ + if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && + urb->actual_length < + urb->transfer_buffer_length && + urb->status == 0)) + urb->status = -EREMOTEIO; + } + /* When giving back the first URB in an Isochronous queue, * reinitialize the QH's iso-related members for the next URB. */ - if (qh->type == USB_ENDPOINT_XFER_ISOC && + else if (qh->type == USB_ENDPOINT_XFER_ISOC && urbp->node.prev == &qh->queue && urbp->node.next != &qh->queue) { struct urb *nurb = list_entry(urbp->node.next, -- cgit v1.2.3 From e294531dc9f2c1f5291373dcdd5013c0cdcbdee2 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 18 Jul 2007 23:10:34 +0900 Subject: USB: r8a66597-hcd: fixes some problem This patch incorporates some updates. Updates include: - Fix the problem that control transfer might fail - Change from GFP_KERNEL to GFP_ATOMIC - Clean up some coding style issue Signed-off-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597-hcd.c | 110 ++++++++++++++++++++-------------------- drivers/usb/host/r8a66597.h | 87 +++++++++++++++---------------- 2 files changed, 96 insertions(+), 101 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index a7a7070c6e2a..d60f1985320c 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -35,10 +35,8 @@ #include #include #include - -#include -#include -#include +#include +#include #include "../core/hcd.h" #include "r8a66597.h" @@ -54,16 +52,21 @@ static const char hcd_name[] = "r8a66597_hcd"; /* module parameters */ static unsigned short clock = XTAL12; module_param(clock, ushort, 0644); -MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=0)"); +MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 " + "(default=0)"); + static unsigned short vif = LDRV; module_param(vif, ushort, 0644); MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)"); -static unsigned short endian = 0; + +static unsigned short endian; module_param(endian, ushort, 0644); -MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)"); +MODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)"); + static unsigned short irq_sense = INTL; module_param(irq_sense, ushort, 0644); -MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0(default=32)"); +MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0 " + "(default=32)"); static void packet_write(struct r8a66597 *r8a66597, u16 pipenum); static int r8a66597_get_frame(struct usb_hcd *hcd); @@ -308,7 +311,7 @@ static int make_r8a66597_device(struct r8a66597 *r8a66597, struct r8a66597_device *dev; int usb_address = urb->setup_packet[2]; /* urb->pipe is address 0 */ - dev = kzalloc(sizeof(struct r8a66597_device), GFP_KERNEL); + dev = kzalloc(sizeof(struct r8a66597_device), GFP_ATOMIC); if (dev == NULL) return -ENOMEM; @@ -611,33 +614,33 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min; memset(array, 0, sizeof(array)); - switch(ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_BULK: + switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_BULK: if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) array[i++] = 4; else { array[i++] = 3; array[i++] = 5; } - break; - case USB_ENDPOINT_XFER_INT: + break; + case USB_ENDPOINT_XFER_INT: if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { array[i++] = 6; array[i++] = 7; array[i++] = 8; } else array[i++] = 9; - break; - case USB_ENDPOINT_XFER_ISOC: + break; + case USB_ENDPOINT_XFER_ISOC: if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) array[i++] = 2; else array[i++] = 1; - break; - default: - err("Illegal type"); - return 0; - } + break; + default: + err("Illegal type"); + return 0; + } i = 1; min = array[0]; @@ -654,7 +657,7 @@ static u16 get_r8a66597_type(__u8 type) { u16 r8a66597_type; - switch(type) { + switch (type) { case USB_ENDPOINT_XFER_BULK: r8a66597_type = R8A66597_BULK; break; @@ -874,7 +877,7 @@ static void r8a66597_usb_preconnect(struct r8a66597 *r8a66597, int port) { r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION) | (1 << USB_PORT_FEAT_C_CONNECTION); - r8a66597_write(r8a66597, (u16)~DTCH, get_intsts_reg(port)); + r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); } @@ -917,7 +920,7 @@ static void prepare_setup_packet(struct r8a66597 *r8a66597, r8a66597_write(r8a66597, make_devsel(td->address) | td->maxpacket, DCPMAXP); - r8a66597_write(r8a66597, (u16)~(SIGN | SACK), INTSTS1); + r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1); for (i = 0; i < 4; i++) { r8a66597_write(r8a66597, p[i], setup_addr); @@ -948,19 +951,18 @@ static void prepare_packet_read(struct r8a66597 *r8a66597, pipe_irq_disable(r8a66597, td->pipenum); pipe_setting(r8a66597, td); pipe_stop(r8a66597, td->pipe); - r8a66597_write(r8a66597, (u16)~(1 << td->pipenum), - BRDYSTS); + r8a66597_write(r8a66597, ~(1 << td->pipenum), BRDYSTS); if (td->pipe->pipetre) { r8a66597_write(r8a66597, TRCLR, - td->pipe->pipetre); + td->pipe->pipetre); r8a66597_write(r8a66597, - (urb->transfer_buffer_length - + td->maxpacket - 1) - / td->maxpacket, - td->pipe->pipetrn); + (urb->transfer_buffer_length + + td->maxpacket - 1) + / td->maxpacket, + td->pipe->pipetrn); r8a66597_bset(r8a66597, TRENB, - td->pipe->pipetre); + td->pipe->pipetre); } pipe_start(r8a66597, td->pipe); @@ -991,7 +993,7 @@ static void prepare_packet_write(struct r8a66597 *r8a66597, if (td->pipe->pipetre) r8a66597_bclr(r8a66597, TRENB, td->pipe->pipetre); } - r8a66597_write(r8a66597, (u16)~(1 << td->pipenum), BRDYSTS); + r8a66597_write(r8a66597, ~(1 << td->pipenum), BRDYSTS); fifo_change_from_pipe(r8a66597, td->pipe); tmp = r8a66597_read(r8a66597, td->pipe->fifoctr); @@ -1009,21 +1011,21 @@ static void prepare_status_packet(struct r8a66597 *r8a66597, struct urb *urb = td->urb; r8a66597_pipe_toggle(r8a66597, td->pipe, 1); + pipe_stop(r8a66597, td->pipe); if (urb->setup_packet[0] & USB_ENDPOINT_DIR_MASK) { r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG); r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL); r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); - r8a66597_write(r8a66597, BVAL | BCLR, CFIFOCTR); - r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS); + r8a66597_write(r8a66597, ~BEMP0, BEMPSTS); + r8a66597_write(r8a66597, BCLR, CFIFOCTR); + r8a66597_write(r8a66597, BVAL, CFIFOCTR); enable_irq_empty(r8a66597, 0); } else { r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL); r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); r8a66597_write(r8a66597, BCLR, CFIFOCTR); - r8a66597_write(r8a66597, (u16)~BRDY0, BRDYSTS); - r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS); enable_irq_ready(r8a66597, 0); } enable_irq_nrdy(r8a66597, 0); @@ -1269,7 +1271,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) /* write fifo */ if (pipenum > 0) - r8a66597_write(r8a66597, (u16)~(1 << pipenum), BEMPSTS); + r8a66597_write(r8a66597, ~(1 << pipenum), BEMPSTS); if (urb->transfer_buffer) { r8a66597_write_fifo(r8a66597, td->pipe->fifoaddr, buf, size); if (!usb_pipebulk(urb->pipe) || td->maxpacket != size) @@ -1362,7 +1364,7 @@ static void irq_pipe_ready(struct r8a66597 *r8a66597) mask = r8a66597_read(r8a66597, BRDYSTS) & r8a66597_read(r8a66597, BRDYENB); - r8a66597_write(r8a66597, (u16)~mask, BRDYSTS); + r8a66597_write(r8a66597, ~mask, BRDYSTS); if (mask & BRDY0) { td = r8a66597_get_td(r8a66597, 0); if (td && td->type == USB_PID_IN) @@ -1397,7 +1399,7 @@ static void irq_pipe_empty(struct r8a66597 *r8a66597) mask = r8a66597_read(r8a66597, BEMPSTS) & r8a66597_read(r8a66597, BEMPENB); - r8a66597_write(r8a66597, (u16)~mask, BEMPSTS); + r8a66597_write(r8a66597, ~mask, BEMPSTS); if (mask & BEMP0) { cfifo_change(r8a66597, 0); td = r8a66597_get_td(r8a66597, 0); @@ -1434,7 +1436,7 @@ static void irq_pipe_nrdy(struct r8a66597 *r8a66597) mask = r8a66597_read(r8a66597, NRDYSTS) & r8a66597_read(r8a66597, NRDYENB); - r8a66597_write(r8a66597, (u16)~mask, NRDYSTS); + r8a66597_write(r8a66597, ~mask, NRDYSTS); if (mask & NRDY0) { cfifo_change(r8a66597, 0); set_urb_error(r8a66597, 0); @@ -1488,14 +1490,14 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) mask0 = intsts0 & intenb0 & (BEMP | NRDY | BRDY); if (mask2) { if (mask2 & ATTCH) { - r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS2); + r8a66597_write(r8a66597, ~ATTCH, INTSTS2); r8a66597_bclr(r8a66597, ATTCHE, INTENB2); /* start usb bus sampling */ start_root_hub_sampling(r8a66597, 1); } if (mask2 & DTCH) { - r8a66597_write(r8a66597, (u16)~DTCH, INTSTS2); + r8a66597_write(r8a66597, ~DTCH, INTSTS2); r8a66597_bclr(r8a66597, DTCHE, INTENB2); r8a66597_usb_disconnect(r8a66597, 1); } @@ -1503,24 +1505,24 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) if (mask1) { if (mask1 & ATTCH) { - r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS1); + r8a66597_write(r8a66597, ~ATTCH, INTSTS1); r8a66597_bclr(r8a66597, ATTCHE, INTENB1); /* start usb bus sampling */ start_root_hub_sampling(r8a66597, 0); } if (mask1 & DTCH) { - r8a66597_write(r8a66597, (u16)~DTCH, INTSTS1); + r8a66597_write(r8a66597, ~DTCH, INTSTS1); r8a66597_bclr(r8a66597, DTCHE, INTENB1); r8a66597_usb_disconnect(r8a66597, 0); } if (mask1 & SIGN) { - r8a66597_write(r8a66597, (u16)~SIGN, INTSTS1); + r8a66597_write(r8a66597, ~SIGN, INTSTS1); set_urb_error(r8a66597, 0); check_next_phase(r8a66597); } if (mask1 & SACK) { - r8a66597_write(r8a66597, (u16)~SACK, INTSTS1); + r8a66597_write(r8a66597, ~SACK, INTSTS1); check_next_phase(r8a66597); } } @@ -1663,13 +1665,9 @@ static int check_pipe_config(struct r8a66597 *r8a66597, struct urb *urb) static int r8a66597_start(struct usb_hcd *hcd) { struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); - int ret; hcd->state = HC_STATE_RUNNING; - if ((ret = enable_controller(r8a66597)) < 0) - return ret; - - return 0; + return enable_controller(r8a66597); } static void r8a66597_stop(struct usb_hcd *hcd) @@ -1696,13 +1694,12 @@ static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb) static struct r8a66597_td *r8a66597_make_td(struct r8a66597 *r8a66597, struct urb *urb, - struct usb_host_endpoint *hep, - gfp_t mem_flags) + struct usb_host_endpoint *hep) { struct r8a66597_td *td; u16 pipenum; - td = kzalloc(sizeof(struct r8a66597_td), mem_flags); + td = kzalloc(sizeof(struct r8a66597_td), GFP_ATOMIC); if (td == NULL) return NULL; @@ -1741,7 +1738,8 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd, } if (!hep->hcpriv) { - hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), mem_flags); + hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), + GFP_ATOMIC); if (!hep->hcpriv) { ret = -ENOMEM; goto error; @@ -1755,7 +1753,7 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd, init_pipe_config(r8a66597, urb); set_address_zero(r8a66597, urb); - td = r8a66597_make_td(r8a66597, urb, hep, mem_flags); + td = r8a66597_make_td(r8a66597, urb, hep); if (td == NULL) { ret = -ENOMEM; goto error; diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index 97c2a71ac7a1..fe9ceb077d9b 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h @@ -203,14 +203,14 @@ #define DTLN 0x0FFF /* b11-0: FIFO received data length */ /* Interrupt Enable Register 0 */ -#define VBSE 0x8000 /* b15: VBUS interrupt */ -#define RSME 0x4000 /* b14: Resume interrupt */ -#define SOFE 0x2000 /* b13: Frame update interrupt */ -#define DVSE 0x1000 /* b12: Device state transition interrupt */ -#define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */ -#define BEMPE 0x0400 /* b10: Buffer empty interrupt */ -#define NRDYE 0x0200 /* b9: Buffer not ready interrupt */ -#define BRDYE 0x0100 /* b8: Buffer ready interrupt */ +#define VBSE 0x8000 /* b15: VBUS interrupt */ +#define RSME 0x4000 /* b14: Resume interrupt */ +#define SOFE 0x2000 /* b13: Frame update interrupt */ +#define DVSE 0x1000 /* b12: Device state transition interrupt */ +#define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */ +#define BEMPE 0x0400 /* b10: Buffer empty interrupt */ +#define NRDYE 0x0200 /* b9: Buffer not ready interrupt */ +#define BRDYE 0x0100 /* b8: Buffer ready interrupt */ /* Interrupt Enable Register 1 */ #define OVRCRE 0x8000 /* b15: Over-current interrupt */ @@ -268,16 +268,16 @@ #define SOF_DISABLE 0x0000 /* SOF OUT Disable */ /* Interrupt Status Register 0 */ -#define VBINT 0x8000 /* b15: VBUS interrupt */ -#define RESM 0x4000 /* b14: Resume interrupt */ -#define SOFR 0x2000 /* b13: SOF frame update interrupt */ -#define DVST 0x1000 /* b12: Device state transition interrupt */ -#define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */ -#define BEMP 0x0400 /* b10: Buffer empty interrupt */ -#define NRDY 0x0200 /* b9: Buffer not ready interrupt */ -#define BRDY 0x0100 /* b8: Buffer ready interrupt */ -#define VBSTS 0x0080 /* b7: VBUS input port */ -#define DVSQ 0x0070 /* b6-4: Device state */ +#define VBINT 0x8000 /* b15: VBUS interrupt */ +#define RESM 0x4000 /* b14: Resume interrupt */ +#define SOFR 0x2000 /* b13: SOF frame update interrupt */ +#define DVST 0x1000 /* b12: Device state transition interrupt */ +#define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */ +#define BEMP 0x0400 /* b10: Buffer empty interrupt */ +#define NRDY 0x0200 /* b9: Buffer not ready interrupt */ +#define BRDY 0x0100 /* b8: Buffer ready interrupt */ +#define VBSTS 0x0080 /* b7: VBUS input port */ +#define DVSQ 0x0070 /* b6-4: Device state */ #define DS_SPD_CNFG 0x0070 /* Suspend Configured */ #define DS_SPD_ADDR 0x0060 /* Suspend Address */ #define DS_SPD_DFLT 0x0050 /* Suspend Default */ @@ -315,13 +315,10 @@ /* Micro Frame Number Register */ #define UFRNM 0x0007 /* b2-0: Micro frame number */ -/* USB Address / Low Power Status Recovery Register */ -//#define USBADDR 0x007F /* b6-0: USB address */ - /* Default Control Pipe Maxpacket Size Register */ /* Pipe Maxpacket Size Register */ -#define DEVSEL 0xF000 /* b15-14: Device address select */ -#define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */ +#define DEVSEL 0xF000 /* b15-14: Device address select */ +#define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */ /* Default Control Pipe Control Register */ #define BSTS 0x8000 /* b15: Buffer status */ @@ -366,21 +363,21 @@ #define MXPS 0x07FF /* b10-0: Maxpacket size */ /* Pipe Cycle Configuration Register */ -#define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */ -#define IITV 0x0007 /* b2-0: Isochronous interval */ +#define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */ +#define IITV 0x0007 /* b2-0: Isochronous interval */ /* Pipex Control Register */ -#define BSTS 0x8000 /* b15: Buffer status */ -#define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */ -#define CSCLR 0x2000 /* b13: complete-split status clear */ -#define CSSTS 0x1000 /* b12: complete-split status */ -#define ATREPM 0x0400 /* b10: Auto repeat mode */ -#define ACLRM 0x0200 /* b9: Out buffer auto clear mode */ -#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ -#define SQSET 0x0080 /* b7: Sequence toggle bit set */ -#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ -#define PBUSY 0x0020 /* b5: pipe busy */ -#define PID 0x0003 /* b1-0: Response PID */ +#define BSTS 0x8000 /* b15: Buffer status */ +#define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */ +#define CSCLR 0x2000 /* b13: complete-split status clear */ +#define CSSTS 0x1000 /* b12: complete-split status */ +#define ATREPM 0x0400 /* b10: Auto repeat mode */ +#define ACLRM 0x0200 /* b9: Out buffer auto clear mode */ +#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ +#define SQSET 0x0080 /* b7: Sequence toggle bit set */ +#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ +#define PBUSY 0x0020 /* b5: pipe busy */ +#define PID 0x0003 /* b1-0: Response PID */ /* PIPExTRE */ #define TRENB 0x0200 /* b9: Transaction counter enable */ @@ -407,15 +404,15 @@ #define make_devsel(addr) (addr << 12) struct r8a66597_pipe_info { - u16 pipenum; - u16 address; /* R8A66597 HCD usb addres */ - u16 epnum; - u16 maxpacket; - u16 type; - u16 bufnum; - u16 buf_bsize; - u16 interval; - u16 dir_in; + u16 pipenum; + u16 address; /* R8A66597 HCD usb addres */ + u16 epnum; + u16 maxpacket; + u16 type; + u16 bufnum; + u16 buf_bsize; + u16 interval; + u16 dir_in; }; struct r8a66597_pipe { -- cgit v1.2.3