diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-03 08:48:58 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-03 08:48:58 -0800 |
commit | 7f5b09c15ab989ed5ce4adda0be42c1302df70b7 (patch) | |
tree | 9695b00983d1bd077ff91c463abcb136330cf344 /drivers/usb/host | |
parent | 94468080220162f74dc6ce5c3e95e5fec8022902 (diff) | |
parent | cedf8a78421943441b9011ce7bcdab55f07d2ea6 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (220 commits)
USB: backlight, appledisplay: fix incomplete registration failure handling
USB: pl2303: remove unnecessary reset of usb_device in urbs
USB: ftdi_sio: remove obsolete check in unthrottle
USB: ftdi_sio: remove unused tx_bytes counter
USB: qcaux: driver for auxiliary serial ports on Qualcomm devices
USB: pl2303: initial TIOCGSERIAL support
USB: option: add Longcheer/Longsung vendor ID
USB: fix I2C API usage in ohci-pnx4008.
USB: usbmon: mask seconds properly in text API
USB: sisusbvga: no unnecessary GFP_ATOMIC
USB: storage: onetouch: unnecessary GFP_ATOMIC
USB: serial: ftdi: add CONTEC vendor and product id
USB: remove references to port->port.count from the serial drivers
USB: tty: Prune uses of tty_request_room in the USB layer
USB: tty: Add a function to insert a string of characters with the same flag
USB: don't read past config->interface[] if usb_control_msg() fails in usb_reset_configuration()
USB: tty: kill request_room for USB ACM class
USB: tty: sort out the request_room handling for whiteheat
USB: storage: fix misplaced parenthesis
USB: vstusb.c: removal of driver for Vernier Software & Technology, Inc., devices and spectrometers
...
Diffstat (limited to 'drivers/usb/host')
36 files changed, 3723 insertions, 145 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2678a1624fc..8d3df0397de 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -399,3 +399,14 @@ config USB_HWA_HCD To compile this driver a module, choose M here: the module will be called "hwa-hc". + +config USB_IMX21_HCD + tristate "iMX21 HCD support" + depends on USB && ARM && MACH_MX21 + help + This driver enables support for the on-chip USB host in the + iMX21 processor. + + To compile this driver as a module, choose M here: the + module will be called "imx21-hcd". + diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index f58b2494c44..4e0c67f1f51 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -32,3 +32,5 @@ obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o +obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o + diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 87c1b7c34c0..51bd0edf544 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -149,7 +149,7 @@ static int __init ehci_atmel_drv_probe(struct platform_device *pdev) goto fail_request_resource; } hcd->rsrc_start = res->start; - hcd->rsrc_len = res->end - res->start + 1; + hcd->rsrc_len = resource_size(res); if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, driver->description)) { diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index dbfb482a94e..e3a74e75e82 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -121,6 +121,7 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct ehci_hcd *ehci; + struct resource *res; int ret; if (usb_disabled()) @@ -144,8 +145,9 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) if (!hcd) return -ENOMEM; - hcd->rsrc_start = pdev->resource[0].start; - hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { pr_debug("request_mem_region failed"); diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 991174937db..0e26aa13f15 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2005 MontaVista Software + * Copyright 2005-2009 MontaVista Software, Inc. + * Copyright 2008 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,17 +18,20 @@ * * Ported to 834x by Randy Vinson <rvinson@mvista.com> using code provided * by Hunter Wu. + * Power Management support by Dave Liu <daveliu@freescale.com>, + * Jerry Huang <Chang-Ming.Huang@freescale.com> and + * Anton Vorontsov <avorontsov@ru.mvista.com>. */ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/delay.h> +#include <linux/pm.h> #include <linux/platform_device.h> #include <linux/fsl_devices.h> #include "ehci-fsl.h" -/* FIXME: Power Management is un-ported so temporarily disable it */ -#undef CONFIG_PM - - /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ @@ -40,8 +44,8 @@ * Allocates basic resources for this USB host controller. * */ -int usb_hcd_fsl_probe(const struct hc_driver *driver, - struct platform_device *pdev) +static int usb_hcd_fsl_probe(const struct hc_driver *driver, + struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata; struct usb_hcd *hcd; @@ -147,7 +151,8 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver, * Reverses the effect of usb_hcd_fsl_probe(). * */ -void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct platform_device *pdev) +static void usb_hcd_fsl_remove(struct usb_hcd *hcd, + struct platform_device *pdev) { usb_remove_hcd(hcd); iounmap(hcd->regs); @@ -284,10 +289,81 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) return retval; } +struct ehci_fsl { + struct ehci_hcd ehci; + +#ifdef CONFIG_PM + /* Saved USB PHY settings, need to restore after deep sleep. */ + u32 usb_ctrl; +#endif +}; + +#ifdef CONFIG_PM + +static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + return container_of(ehci, struct ehci_fsl, ehci); +} + +static int ehci_fsl_drv_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); + void __iomem *non_ehci = hcd->regs; + + if (!fsl_deep_sleep()) + return 0; + + ehci_fsl->usb_ctrl = in_be32(non_ehci + FSL_SOC_USB_CTRL); + return 0; +} + +static int ehci_fsl_drv_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + void __iomem *non_ehci = hcd->regs; + + if (!fsl_deep_sleep()) + return 0; + + usb_root_hub_lost_power(hcd->self.root_hub); + + /* Restore USB PHY settings and enable the controller. */ + out_be32(non_ehci + FSL_SOC_USB_CTRL, ehci_fsl->usb_ctrl); + + ehci_reset(ehci); + ehci_fsl_reinit(ehci); + + return 0; +} + +static int ehci_fsl_drv_restore(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + + usb_root_hub_lost_power(hcd->self.root_hub); + return 0; +} + +static struct dev_pm_ops ehci_fsl_pm_ops = { + .suspend = ehci_fsl_drv_suspend, + .resume = ehci_fsl_drv_resume, + .restore = ehci_fsl_drv_restore, +}; + +#define EHCI_FSL_PM_OPS (&ehci_fsl_pm_ops) +#else +#define EHCI_FSL_PM_OPS NULL +#endif /* CONFIG_PM */ + static const struct hc_driver ehci_fsl_hc_driver = { .description = hcd_name, .product_desc = "Freescale On-Chip EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), + .hcd_priv_size = sizeof(struct ehci_fsl), /* * generic hardware linkage @@ -354,6 +430,7 @@ static struct platform_driver ehci_fsl_driver = { .remove = ehci_fsl_drv_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { - .name = "fsl-ehci", + .name = "fsl-ehci", + .pm = EHCI_FSL_PM_OPS, }, }; diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 35c56f40bdb..23cd917088b 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -162,6 +162,17 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) goto err_ioremap; } + /* call platform specific init function */ + if (pdata->init) { + ret = pdata->init(pdev); + if (ret) { + dev_err(dev, "platform init failed\n"); + goto err_init; + } + /* platforms need some time to settle changed IO settings */ + mdelay(10); + } + /* enable clocks */ priv->usbclk = clk_get(dev, "usb"); if (IS_ERR(priv->usbclk)) { @@ -192,18 +203,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) if (ret < 0) goto err_init; - /* call platform specific init function */ - if (pdata->init) { - ret = pdata->init(pdev); - if (ret) { - dev_err(dev, "platform init failed\n"); - goto err_init; - } - } - - /* most platforms need some time to settle changed IO settings */ - mdelay(10); - /* Initialize the transceiver */ if (pdata->otg) { pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET; diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 74d07f4e8b7..f0282d6bb7a 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -26,10 +26,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * TODO (last updated Feb 23rd, 2009): + * TODO (last updated Feb 12, 2010): * - add kernel-doc * - enable AUTOIDLE - * - move DPLL5 programming to clock fw * - add suspend/resume * - move workarounds to board-files */ @@ -37,6 +36,7 @@ #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/gpio.h> +#include <linux/regulator/consumer.h> #include <plat/usb.h> /* @@ -178,6 +178,11 @@ struct ehci_hcd_omap { void __iomem *uhh_base; void __iomem *tll_base; void __iomem *ehci_base; + + /* Regulators for USB PHYs. + * Each PHY can have a seperate regulator. + */ + struct regulator *regulator[OMAP3_HS_USB_PORTS]; }; /*-------------------------------------------------------------------------*/ @@ -546,6 +551,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) int irq = platform_get_irq(pdev, 0); int ret = -ENODEV; + int i; + char supply[7]; if (!pdata) { dev_dbg(&pdev->dev, "missing platform_data\n"); @@ -613,6 +620,21 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) goto err_tll_ioremap; } + /* get ehci regulator and enable */ + for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { + if (omap->port_mode[i] != EHCI_HCD_OMAP_MODE_PHY) { + omap->regulator[i] = NULL; + continue; + } + snprintf(supply, sizeof(supply), "hsusb%d", i); + omap->regulator[i] = regulator_get(omap->dev, supply); + if (IS_ERR(omap->regulator[i])) + dev_dbg(&pdev->dev, + "failed to get ehci port%d regulator\n", i); + else + regulator_enable(omap->regulator[i]); + } + ret = omap_start_ehc(omap, hcd); if (ret) { dev_dbg(&pdev->dev, "failed to start ehci\n"); @@ -622,13 +644,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) omap->ehci->regs = hcd->regs + HC_LENGTH(readl(&omap->ehci->caps->hc_capbase)); + dbg_hcs_params(omap->ehci, "reset"); + dbg_hcc_params(omap->ehci, "reset"); + /* cache this readonly data; minimize chip reads */ omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params); - /* SET 1 micro-frame Interrupt interval */ - writel(readl(&omap->ehci->regs->command) | (1 << 16), - &omap->ehci->regs->command); - ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (ret) { dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); @@ -641,6 +662,12 @@ err_add_hcd: omap_stop_ehc(omap, hcd); err_start: + for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { + if (omap->regulator[i]) { + regulator_disable(omap->regulator[i]); + regulator_put(omap->regulator[i]); + } + } iounmap(omap->tll_base); err_tll_ioremap: @@ -674,13 +701,21 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) { struct ehci_hcd_omap *omap = platform_get_drvdata(pdev); struct usb_hcd *hcd = ehci_to_hcd(omap->ehci); + int i; usb_remove_hcd(hcd); omap_stop_ehc(omap, hcd); iounmap(hcd->regs); + for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { + if (omap->regulator[i]) { + regulator_disable(omap->regulator[i]); + regulator_put(omap->regulator[i]); + } + } iounmap(omap->tll_base); iounmap(omap->uhh_base); usb_put_hcd(hcd); + kfree(omap); return 0; } diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 1d283e1b2b8..0f87dc72820 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -222,14 +222,14 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) goto err1; } - if (!request_mem_region(res->start, res->end - res->start + 1, + if (!request_mem_region(res->start, resource_size(res), ehci_orion_hc_driver.description)) { dev_dbg(&pdev->dev, "controller already in use\n"); err = -EBUSY; goto err1; } - regs = ioremap(res->start, res->end - res->start + 1); + regs = ioremap(res->start, resource_size(res)); if (regs == NULL) { dev_dbg(&pdev->dev, "error mapping memory\n"); err = -EFAULT; @@ -244,7 +244,7 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) } hcd->rsrc_start = res->start; - hcd->rsrc_len = res->end - res->start + 1; + hcd->rsrc_len = resource_size(res); hcd->regs = regs; ehci = hcd_to_ehci(hcd); @@ -287,7 +287,7 @@ err4: err3: iounmap(regs); err2: - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); err1: dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), err); diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 36f96da129f..8df33b8a634 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -134,21 +134,21 @@ ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) hcd->rsrc_len = res.end - res.start + 1; if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - printk(KERN_ERR __FILE__ ": request_mem_region failed\n"); + printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__); rv = -EBUSY; goto err_rmr; } irq = irq_of_parse_and_map(dn, 0); if (irq == NO_IRQ) { - printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n"); + printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__); rv = -EBUSY; goto err_irq; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { - printk(KERN_ERR __FILE__ ": ioremap failed\n"); + printk(KERN_ERR "%s: ioremap failed\n", __FILE__); rv = -ENOMEM; goto err_ioremap; } @@ -161,9 +161,9 @@ ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) ehci->ohci_hcctrl_reg = ioremap(res.start + OHCI_HCCTRL_OFFSET, OHCI_HCCTRL_LEN); else - pr_debug(__FILE__ ": no ohci offset in fdt\n"); + pr_debug("%s: no ohci offset in fdt\n", __FILE__); if (!ehci->ohci_hcctrl_reg) { - pr_debug(__FILE__ ": ioremap for ohci hcctrl failed\n"); + pr_debug("%s: ioremap for ohci hcctrl failed\n", __FILE__); } else { ehci->has_amcc_usb23 = 1; } @@ -241,7 +241,7 @@ static int ehci_hcd_ppc_of_remove(struct of_device *op) else release_mem_region(res.start, 0x4); else - pr_debug(__FILE__ ": no ohci offset in fdt\n"); + pr_debug("%s: no ohci offset in fdt\n", __FILE__); of_node_put(np); } @@ -264,7 +264,7 @@ static int ehci_hcd_ppc_of_shutdown(struct of_device *op) } -static struct of_device_id ehci_hcd_ppc_of_match[] = { +static const struct of_device_id ehci_hcd_ppc_of_match[] = { { .compatible = "usb-ehci", }, diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 1e391e624c8..39340ae00ac 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -510,6 +510,8 @@ static int disable_periodic (struct ehci_hcd *ehci) ehci_writel(ehci, cmd, &ehci->regs->command); /* posted write ... */ + free_cached_itd_list(ehci); + ehci->next_uframe = -1; return 0; } @@ -2322,9 +2324,13 @@ restart: * No need to check for activity unless the * frame is current. */ - if (frame == clock_frame && live && - (q.sitd->hw_results & - SITD_ACTIVE(ehci))) { + if (((frame == clock_frame) || + (((frame + 1) % ehci->periodic_size) + == clock_frame)) + && live + && (q.sitd->hw_results & + SITD_ACTIVE(ehci))) { + incomplete = true; q_p = &q.sitd->sitd_next; hw_p = &q.sitd->hw_next; diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index a5861531ad3..f603bb2c0a8 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -177,21 +177,21 @@ ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match) hcd->rsrc_len = res.end - res.start + 1; if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - printk(KERN_ERR __FILE__ ": request_mem_region failed\n"); + printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__); rv = -EBUSY; goto err_rmr; } irq = irq_of_parse_and_map(dn, 0); if (irq == NO_IRQ) { - printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n"); + printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__); rv = -EBUSY; goto err_irq; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { - printk(KERN_ERR __FILE__ ": ioremap failed\n"); + printk(KERN_ERR "%s: ioremap failed\n", __FILE__); rv = -ENOMEM; goto err_ioremap; } @@ -281,7 +281,7 @@ static int ehci_hcd_xilinx_of_shutdown(struct of_device *op) } -static struct of_device_id ehci_hcd_xilinx_of_match[] = { +static const struct of_device_id ehci_hcd_xilinx_of_match[] = { {.compatible = "xlnx,xps-usb-host-1.00.a",}, {}, }; diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 78e7c3cfcb7..5dcfb3de994 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -433,7 +433,7 @@ static int fhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, return -ENOMEM; /* allocate the private part of the URB */ - urb_priv->tds = kzalloc(size * sizeof(struct td), mem_flags); + urb_priv->tds = kcalloc(size, sizeof(*urb_priv->tds), mem_flags); if (!urb_priv->tds) { kfree(urb_priv); return -ENOMEM; @@ -805,7 +805,7 @@ static int __devexit of_fhci_remove(struct of_device *ofdev) return fhci_remove(&ofdev->dev); } -static struct of_device_id of_fhci_match[] = { +static const struct of_device_id of_fhci_match[] = { { .compatible = "fsl,mpc8323-qe-usb", }, {}, }; diff --git a/drivers/usb/host/imx21-dbg.c b/drivers/usb/host/imx21-dbg.c new file mode 100644 index 00000000000..512f647448c --- /dev/null +++ b/drivers/usb/host/imx21-dbg.c @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2009 by Martin Fuzzey + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* this file is part of imx21-hcd.c */ + +#ifndef DEBUG + +static inline void create_debug_files(struct imx21 *imx21) { } +static inline void remove_debug_files(struct imx21 *imx21) { } +static inline void debug_urb_submitted(struct imx21 *imx21, struct urb *urb) {} +static inline void debug_urb_completed(struct imx21 *imx21, struct urb *urb, + int status) {} +static inline void debug_urb_unlinked(struct imx21 *imx21, struct urb *urb) {} +static inline void debug_urb_queued_for_etd(struct imx21 *imx21, + struct urb *urb) {} +static inline void debug_urb_queued_for_dmem(struct imx21 *imx21, + struct urb *urb) {} +static inline void debug_etd_allocated(struct imx21 *imx21) {} +static inline void debug_etd_freed(struct imx21 *imx21) {} +static inline void debug_dmem_allocated(struct imx21 *imx21, int size) {} +static inline void debug_dmem_freed(struct imx21 *imx21, int size) {} +static inline void debug_isoc_submitted(struct imx21 *imx21, + int frame, struct td *td) {} +static inline void debug_isoc_completed(struct imx21 *imx21, + int frame, struct td *td, int cc, int len) {} + +#else + +#include <linux/debugfs.h> +#include <linux/seq_file.h> + +static const char *dir_labels[] = { + "TD 0", + "OUT", + "IN", + "TD 1" +}; + +static const char *speed_labels[] = { + "Full", + "Low" +}; + +static const char *format_labels[] = { + "Control", + "ISO", + "Bulk", + "Interrupt" +}; + +static inline struct debug_stats *stats_for_urb(struct imx21 *imx21, + struct urb *urb) +{ + return usb_pipeisoc(urb->pipe) ? + &imx21->isoc_stats : &imx21->nonisoc_stats; +} + +static void debug_urb_submitted(struct imx21 *imx21, struct urb *urb) +{ + stats_for_urb(imx21, urb)->submitted++; +} + +static void debug_urb_completed(struct imx21 *imx21, struct urb *urb, int st) +{ + if (st) + stats_for_urb(imx21, urb)->completed_failed++; + else + stats_for_urb(imx21, urb)->completed_ok++; +} + +static void debug_urb_unlinked(struct imx21 *imx21, struct urb *urb) +{ + stats_for_urb(imx21, urb)->unlinked++; +} + +static void debug_urb_queued_for_etd(struct imx21 *imx21, struct urb *urb) +{ + stats_for_urb(imx21, urb)->queue_etd++; +} + +static void debug_urb_queued_for_dmem(struct imx21 *imx21, struct urb *urb) +{ + stats_for_urb(imx21, urb)->queue_dmem++; +} + +static inline void debug_etd_allocated(struct imx21 *imx21) +{ + imx21->etd_usage.maximum = max( + ++(imx21->etd_usage.value), + imx21->etd_usage.maximum); +} + +static inline void debug_etd_freed(struct imx21 *imx21) +{ + imx21->etd_usage.value--; +} + +static inline void debug_dmem_allocated(struct imx21 *imx21, int size) +{ + imx21->dmem_usage.value += size; + imx21->dmem_usage.maximum = max( + imx21->dmem_usage.value, + imx21->dmem_usage.maximum); +} + +static inline void debug_dmem_freed(struct imx21 *imx21, int size) +{ + imx21->dmem_usage.value -= size; +} + + +static void debug_isoc_submitted(struct imx21 *imx21, + int frame, struct td *td) +{ + struct debug_isoc_trace *trace = &imx21->isoc_trace[ + imx21->isoc_trace_index++]; + + imx21->isoc_trace_index %= ARRAY_SIZE(imx21->isoc_trace); + trace->schedule_frame = td->frame; + trace->submit_frame = frame; + trace->request_len = td->len; + trace->td = td; +} + +static inline void debug_isoc_completed(struct imx21 *imx21, + int frame, struct td *td, int cc, int len) +{ + struct debug_isoc_trace *trace, *trace_failed; + int i; + int found = 0; + + trace = imx21->isoc_trace; + for (i = 0; i < ARRAY_SIZE(imx21->isoc_trace); i++, trace++) { + if (trace->td == td) { + trace->done_frame = frame; + trace->done_len = len; + trace->cc = cc; + trace->td = NULL; + found = 1; + break; + } + } + + if (found && cc) { + trace_failed = &imx21->isoc_trace_failed[ + imx21->isoc_trace_index_failed++]; + + imx21->isoc_trace_index_failed %= ARRAY_SIZE( + imx21->isoc_trace_failed); + *trace_failed = *trace; + } +} + + +static char *format_ep(struct usb_host_endpoint *ep, char *buf, int bufsize) +{ + if (ep) + snprintf(buf, bufsize, "ep_%02x (type:%02X kaddr:%p)", + ep->desc.bEndpointAddress, + usb_endpoint_type(&ep->desc), + ep); + else + snprintf(buf, bufsize, "none"); + return buf; +} + +static char *format_etd_dword0(u32 value, char *buf, int bufsize) |