X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fhost%2Fsl811-hcd.c;h=5fa5647ea0951a9b28958060848eb195e67b58b2;hb=refs%2Fheads%2Fvserver;hp=99d43f758ad0e85d524d00cedaf93bed8793ac15;hpb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;p=linux-2.6.git diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 99d43f758..5fa5647ea 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -31,14 +31,6 @@ #undef VERBOSE #undef PACKET_TRACE -#include - -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#else -# undef DEBUG -#endif - #include #include #include @@ -53,7 +45,8 @@ #include #include #include -#include +#include +#include #include #include @@ -435,7 +428,6 @@ static void finish_request( struct sl811 *sl811, struct sl811h_ep *ep, struct urb *urb, - struct pt_regs *regs, int status ) __releases(sl811->lock) __acquires(sl811->lock) { @@ -451,7 +443,7 @@ static void finish_request( spin_unlock(&urb->lock); spin_unlock(&sl811->lock); - usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb, regs); + usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb); spin_lock(&sl811->lock); /* leave active endpoints in the schedule */ @@ -491,7 +483,7 @@ static void finish_request( } static void -done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs) +done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank) { u8 status; struct urb *urb; @@ -604,7 +596,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs) /* error? retry, until "3 strikes" */ } else if (++ep->error_count >= 3) { if (status & SL11H_STATMASK_TMOUT) - urbstat = -ETIMEDOUT; + urbstat = -ETIME; else if (status & SL11H_STATMASK_OVF) urbstat = -EOVERFLOW; else @@ -615,7 +607,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs) } if (urb && (urbstat != -EINPROGRESS || urb->status != -EINPROGRESS)) - finish_request(sl811, ep, urb, regs, urbstat); + finish_request(sl811, ep, urb, urbstat); } static inline u8 checkdone(struct sl811 *sl811) @@ -648,7 +640,7 @@ static inline u8 checkdone(struct sl811 *sl811) return irqstat; } -static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs) +static irqreturn_t sl811h_irq(struct usb_hcd *hcd) { struct sl811 *sl811 = hcd_to_sl811(hcd); u8 irqstat; @@ -677,13 +669,13 @@ retry: * issued ... that's fine if they're different endpoints. */ if (irqstat & SL11H_INTMASK_DONE_A) { - done(sl811, sl811->active_a, SL811_EP_A(SL811_HOST_BUF), regs); + done(sl811, sl811->active_a, SL811_EP_A(SL811_HOST_BUF)); sl811->active_a = NULL; sl811->stat_a++; } #ifdef USE_B if (irqstat & SL11H_INTMASK_DONE_B) { - done(sl811, sl811->active_b, SL811_EP_B(SL811_HOST_BUF), regs); + done(sl811, sl811->active_b, SL811_EP_B(SL811_HOST_BUF)); sl811->active_b = NULL; sl811->stat_b++; } @@ -730,7 +722,7 @@ retry: container_of(sl811->active_a ->hep->urb_list.next, struct urb, urb_list), - NULL, -ESHUTDOWN); + -ESHUTDOWN); sl811->active_a = NULL; } #ifdef USE_B @@ -782,6 +774,9 @@ retry: /* usb 1.1 says max 90% of a frame is available for periodic transfers. * this driver doesn't promise that much since it's got to handle an * IRQ per packet; irq handling latencies also use up that time. + * + * NOTE: the periodic schedule is a sparse tree, with the load for + * each branch minimized. see fig 3.5 in the OHCI spec for example. */ #define MAX_PERIODIC_LOAD 500 /* out of 1000 usec */ @@ -815,7 +810,7 @@ static int sl811h_urb_enqueue( struct usb_hcd *hcd, struct usb_host_endpoint *hep, struct urb *urb, - int mem_flags + gfp_t mem_flags ) { struct sl811 *sl811 = hcd_to_sl811(hcd); struct usb_device *udev = urb->dev; @@ -835,7 +830,7 @@ static int sl811h_urb_enqueue( /* avoid all allocations within spinlocks */ if (!hep->hcpriv) - ep = kcalloc(1, sizeof *ep, mem_flags); + ep = kzalloc(sizeof *ep, mem_flags); spin_lock_irqsave(&sl811->lock, flags); @@ -843,6 +838,7 @@ static int sl811h_urb_enqueue( if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE)) || !HC_IS_RUNNING(hcd->state)) { retval = -ENODEV; + kfree(ep); goto fail; } @@ -855,7 +851,7 @@ static int sl811h_urb_enqueue( } else { INIT_LIST_HEAD(&ep->schedule); - ep->udev = usb_get_dev(udev); + ep->udev = udev; ep->epnum = epnum; ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); ep->defctrl = SL11H_HCTLMASK_ARM | SL11H_HCTLMASK_ENABLE; @@ -911,8 +907,16 @@ static int sl811h_urb_enqueue( case PIPE_ISOCHRONOUS: case PIPE_INTERRUPT: urb->interval = ep->period; - if (ep->branch < PERIODIC_SIZE) + if (ep->branch < PERIODIC_SIZE) { + /* NOTE: the phase is correct here, but the value + * needs offsetting by the transfer queue depth. + * All current drivers ignore start_frame, so this + * is unlikely to ever matter... + */ + urb->start_frame = (sl811->frame & (PERIODIC_SIZE - 1)) + + ep->branch; break; + } retval = balance(sl811, ep->period, ep->load); if (retval < 0) @@ -952,7 +956,7 @@ static int sl811h_urb_enqueue( spin_lock(&urb->lock); if (urb->status != -EINPROGRESS) { spin_unlock(&urb->lock); - finish_request(sl811, ep, urb, NULL, 0); + finish_request(sl811, ep, urb, 0); retval = 0; goto fail; } @@ -1021,7 +1025,7 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) } if (urb) - finish_request(sl811, ep, urb, NULL, 0); + finish_request(sl811, ep, urb, 0); else VDBG("dequeue, urb %p active %s; wait4irq\n", urb, (sl811->active_a == ep) ? "A" : "B"); @@ -1046,7 +1050,6 @@ sl811h_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) if (!list_empty(&hep->urb_list)) WARN("ep %p not empty?\n", ep); - usb_put_dev(ep->udev); kfree(ep); hep->hcpriv = NULL; } @@ -1079,7 +1082,7 @@ sl811h_hub_status_data(struct usb_hcd *hcd, char *buf) */ local_irq_save(flags); if (!timer_pending(&sl811->timer)) { - if (sl811h_irq( /* ~0, */ hcd, NULL) != IRQ_NONE) + if (sl811h_irq( /* ~0, */ hcd) != IRQ_NONE) sl811->stat_lost++; } local_irq_restore(flags); @@ -1122,7 +1125,7 @@ sl811h_hub_descriptor ( desc->wHubCharacteristics = (__force __u16)cpu_to_le16(temp); /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ - desc->bitmap[0] = 1 << 1; + desc->bitmap[0] = 0 << 1; desc->bitmap[1] = ~0; } @@ -1351,7 +1354,7 @@ error: #ifdef CONFIG_PM static int -sl811h_hub_suspend(struct usb_hcd *hcd) +sl811h_bus_suspend(struct usb_hcd *hcd) { // SOFs off DBG("%s\n", __FUNCTION__); @@ -1359,7 +1362,7 @@ sl811h_hub_suspend(struct usb_hcd *hcd) } static int -sl811h_hub_resume(struct usb_hcd *hcd) +sl811h_bus_resume(struct usb_hcd *hcd) { // SOFs on DBG("%s\n", __FUNCTION__); @@ -1368,8 +1371,8 @@ sl811h_hub_resume(struct usb_hcd *hcd) #else -#define sl811h_hub_suspend NULL -#define sl811h_hub_resume NULL +#define sl811h_bus_suspend NULL +#define sl811h_bus_resume NULL #endif @@ -1513,7 +1516,7 @@ static int proc_sl811h_open(struct inode *inode, struct file *file) return single_open(file, proc_sl811h_show, PDE(inode)->data); } -static struct file_operations proc_ops = { +static const struct file_operations proc_ops = { .open = proc_sl811h_open, .read = seq_read, .llseek = seq_lseek, @@ -1563,29 +1566,17 @@ static int sl811h_start(struct usb_hcd *hcd) { struct sl811 *sl811 = hcd_to_sl811(hcd); - struct usb_device *udev; /* chip has been reset, VBUS power is off */ - - udev = usb_alloc_dev(NULL, &hcd->self, 0); - if (!udev) - return -ENOMEM; - - udev->speed = USB_SPEED_FULL; hcd->state = HC_STATE_RUNNING; - if (sl811->board) - hcd->can_wakeup = sl811->board->can_wakeup; - - if (usb_hcd_register_root_hub(udev, hcd) != 0) { - usb_put_dev(udev); - sl811h_stop(hcd); - return -ENODEV; + if (sl811->board) { + if (!device_can_wakeup(hcd->self.controller)) + device_init_wakeup(hcd->self.controller, + sl811->board->can_wakeup); + hcd->power_budget = sl811->board->power * 2; } - if (sl811->board && sl811->board->power) - hub_set_power_budget(udev, sl811->board->power * 2); - /* enable power and interupts */ port_power(sl811, 1); @@ -1625,31 +1616,28 @@ static struct hc_driver sl811h_hc_driver = { */ .hub_status_data = sl811h_hub_status_data, .hub_control = sl811h_hub_control, - .hub_suspend = sl811h_hub_suspend, - .hub_resume = sl811h_hub_resume, + .bus_suspend = sl811h_bus_suspend, + .bus_resume = sl811h_bus_resume, }; /*-------------------------------------------------------------------------*/ static int __devexit -sl811h_remove(struct device *dev) +sl811h_remove(struct platform_device *dev) { - struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(dev); struct sl811 *sl811 = hcd_to_sl811(hcd); - struct platform_device *pdev; struct resource *res; - pdev = container_of(dev, struct platform_device, dev); - remove_debug_file(sl811); usb_remove_hcd(hcd); /* some platforms may use IORESOURCE_IO */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + res = platform_get_resource(dev, IORESOURCE_MEM, 1); if (res) iounmap(sl811->data_reg); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (res) iounmap(sl811->addr_reg); @@ -1658,11 +1646,10 @@ sl811h_remove(struct device *dev) } static int __devinit -sl811h_probe(struct device *dev) +sl811h_probe(struct platform_device *dev) { struct usb_hcd *hcd; struct sl811 *sl811; - struct platform_device *pdev; struct resource *addr, *data; int irq; void __iomem *addr_reg; @@ -1675,30 +1662,33 @@ sl811h_probe(struct device *dev) * specific platform_data. we don't probe for IRQs, and do only * minimal sanity checking. */ - pdev = container_of(dev, struct platform_device, dev); - irq = platform_get_irq(pdev, 0); - if (pdev->num_resources < 3 || irq < 0) + irq = platform_get_irq(dev, 0); + if (dev->num_resources < 3 || irq < 0) return -ENODEV; /* refuse to confuse usbcore */ - if (dev->dma_mask) { + if (dev->dev.dma_mask) { DBG("no we won't dma\n"); return -EINVAL; } /* the chip may be wired for either kind of addressing */ - addr = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data = platform_get_resource(pdev, IORESOURCE_MEM, 1); + addr = platform_get_resource(dev, IORESOURCE_MEM, 0); + data = platform_get_resource(dev, IORESOURCE_MEM, 1); retval = -EBUSY; if (!addr || !data) { - addr = platform_get_resource(pdev, IORESOURCE_IO, 0); - data = platform_get_resource(pdev, IORESOURCE_IO, 1); + addr = platform_get_resource(dev, IORESOURCE_IO, 0); + data = platform_get_resource(dev, IORESOURCE_IO, 1); if (!addr || !data) return -ENODEV; ioaddr = 1; - - addr_reg = (void __iomem *) addr->start; - data_reg = (void __iomem *) data->start; + /* + * NOTE: 64-bit resource->start is getting truncated + * to avoid compiler warning, assuming that ->start + * is always 32-bit for this case + */ + addr_reg = (void __iomem *) (unsigned long) addr->start; + data_reg = (void __iomem *) (unsigned long) data->start; } else { addr_reg = ioremap(addr->start, 1); if (addr_reg == NULL) { @@ -1714,7 +1704,7 @@ sl811h_probe(struct device *dev) } /* allocate and initialize hcd */ - hcd = usb_create_hcd(&sl811h_hc_driver, dev, dev->bus_id); + hcd = usb_create_hcd(&sl811h_hc_driver, &dev->dev, dev->dev.bus_id); if (!hcd) { retval = -ENOMEM; goto err5; @@ -1724,7 +1714,7 @@ sl811h_probe(struct device *dev) spin_lock_init(&sl811->lock); INIT_LIST_HEAD(&sl811->async); - sl811->board = dev->platform_data; + sl811->board = dev->dev.platform_data; init_timer(&sl811->timer); sl811->timer.function = sl811h_timer; sl811->timer.data = (unsigned long) sl811; @@ -1758,7 +1748,7 @@ sl811h_probe(struct device *dev) * was on a system with single edge triggering, so most sorts of * triggering arrangement should work. */ - retval = usb_add_hcd(hcd, irq, SA_INTERRUPT | SA_SHIRQ); + retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err6; @@ -1786,45 +1776,45 @@ sl811h_probe(struct device *dev) */ static int -sl811h_suspend(struct device *dev, pm_message_t state, u32 phase) +sl811h_suspend(struct platform_device *dev, pm_message_t state) { - struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(dev); struct sl811 *sl811 = hcd_to_sl811(hcd); int retval = 0; - if (phase != SUSPEND_POWER_DOWN) - return retval; - - if (state <= PM_SUSPEND_MEM) - retval = sl811h_hub_suspend(hcd); - else + switch (state.event) { + case PM_EVENT_FREEZE: + retval = sl811h_bus_suspend(hcd); + break; + case PM_EVENT_SUSPEND: + case PM_EVENT_PRETHAW: /* explicitly discard hw state */ port_power(sl811, 0); + break; + } if (retval == 0) - dev->power.power_state = state; + dev->dev.power.power_state = state; return retval; } static int -sl811h_resume(struct device *dev, u32 phase) +sl811h_resume(struct platform_device *dev) { - struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(dev); struct sl811 *sl811 = hcd_to_sl811(hcd); - if (phase != RESUME_POWER_ON) - return 0; - /* with no "check to see if VBUS is still powered" board hook, * let's assume it'd only be powered to enable remote wakeup. */ - if (dev->power.power_state > PM_SUSPEND_MEM - || !hcd->can_wakeup) { + if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND + || !device_can_wakeup(&hcd->self.root_hub->dev)) { sl811->port1 = 0; port_power(sl811, 1); + usb_root_hub_lost_power(hcd->self.root_hub); return 0; } - dev->power.power_state = PMSG_ON; - return sl811h_hub_resume(hcd); + dev->dev.power.power_state = PMSG_ON; + return sl811h_bus_resume(hcd); } #else @@ -1836,15 +1826,16 @@ sl811h_resume(struct device *dev, u32 phase) /* this driver is exported so sl811_cs can depend on it */ -struct device_driver sl811h_driver = { - .name = (char *) hcd_name, - .bus = &platform_bus_type, - +struct platform_driver sl811h_driver = { .probe = sl811h_probe, .remove = __devexit_p(sl811h_remove), .suspend = sl811h_suspend, .resume = sl811h_resume, + .driver = { + .name = (char *) hcd_name, + .owner = THIS_MODULE, + }, }; EXPORT_SYMBOL(sl811h_driver); @@ -1856,12 +1847,12 @@ static int __init sl811h_init(void) return -ENODEV; INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION); - return driver_register(&sl811h_driver); + return platform_driver_register(&sl811h_driver); } module_init(sl811h_init); static void __exit sl811h_cleanup(void) { - driver_unregister(&sl811h_driver); + platform_driver_unregister(&sl811h_driver); } module_exit(sl811h_cleanup);