diff options
Diffstat (limited to 'drivers/usb/host')
29 files changed, 848 insertions, 892 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0b80cee30da4..6361fc739306 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -479,9 +479,10 @@ config USB_OHCI_HCD_OMAP3 OMAP3 and later chips. config USB_OHCI_HCD_DAVINCI - bool "OHCI support for TI DaVinci DA8xx" + tristate "OHCI support for TI DaVinci DA8xx" depends on ARCH_DAVINCI_DA8XX - depends on USB_OHCI_HCD=y + depends on USB_OHCI_HCD + select PHY_DA8XX_USB default y help Enables support for the DaVinci DA8xx integrated OHCI diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 6ef785b0ea8f..2644537b7bcf 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_USB_OHCI_HCD_AT91) += ohci-at91.o obj-$(CONFIG_USB_OHCI_HCD_S3C2410) += ohci-s3c2410.o obj-$(CONFIG_USB_OHCI_HCD_LPC32XX) += ohci-nxp.o obj-$(CONFIG_USB_OHCI_HCD_PXA27X) += ohci-pxa27x.o +obj-$(CONFIG_USB_OHCI_HCD_DAVINCI) += ohci-da8xx.o obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 9f5ffb629973..91701cc68082 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -286,6 +286,9 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) if (pdata->has_fsl_erratum_a005275 == 1) ehci->has_fsl_hs_errata = 1; + if (pdata->has_fsl_erratum_a005697 == 1) + ehci->has_fsl_susp_errata = 1; + if ((pdata->operating_mode == FSL_USB2_DR_HOST) || (pdata->operating_mode == FSL_USB2_DR_OTG)) if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0)) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 74f62d68f013..df169c8e7225 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -310,6 +310,14 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) } spin_unlock_irq(&ehci->lock); + if (changed && ehci_has_fsl_susp_errata(ehci)) + /* + * Wait for at least 10 millisecondes to ensure the controller + * enter the suspend status before initiating a port resume + * using the Force Port Resume bit (Not-EHCI compatible). + */ + usleep_range(10000, 20000); + if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) { /* * Wait for HCD to enter low-power mode or for the bus @@ -1200,6 +1208,12 @@ int ehci_hub_control( wIndex, (temp1 & HOSTPC_PHCD) ? "succeeded" : "failed"); } + if (ehci_has_fsl_susp_errata(ehci)) { + /* 10ms for HCD enter suspend */ + spin_unlock_irqrestore(&ehci->lock, flags); + usleep_range(10000, 20000); + spin_lock_irqsave(&ehci->lock, flags); + } set_bit(wIndex, &ehci->suspended_ports); break; case USB_PORT_FEAT_POWER: diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 3b3649d88c5f..93326974ff4b 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -258,9 +258,8 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* These workarounds need to be applied after ehci_setup() */ switch (pdev->vendor) { case PCI_VENDOR_ID_NEC: - ehci->need_io_watchdog = 0; - break; case PCI_VENDOR_ID_INTEL: + case PCI_VENDOR_ID_AMD: ehci->need_io_watchdog = 0; break; case PCI_VENDOR_ID_NVIDIA: diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index eca3710d8fc4..8f3f055c05fa 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -550,11 +550,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) /*-------------------------------------------------------------------------*/ -// high bandwidth multiplier, as encoded in highspeed endpoint descriptors -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) -// ... and packet size, for any kind of endpoint descriptor -#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) - /* * reverse of qh_urb_transaction: free a list of TDs. * used for cleanup after errors, before HC sees an URB's TDs. @@ -651,7 +646,7 @@ qh_urb_transaction ( token |= (1 /* "in" */ << 8); /* else it's already initted to "out" pid (0 << 8) */ - maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); + maxpacket = usb_maxpacket(urb->dev, urb->pipe, !is_input); /* * buffer gets wrapped in one or more qtds; @@ -770,9 +765,11 @@ qh_make ( gfp_t flags ) { struct ehci_qh *qh = ehci_qh_alloc (ehci, flags); + struct usb_host_endpoint *ep; u32 info1 = 0, info2 = 0; int is_input, type; int maxp = 0; + int mult; struct usb_tt *tt = urb->dev->tt; struct ehci_qh_hw *hw; @@ -787,13 +784,15 @@ qh_make ( is_input = usb_pipein (urb->pipe); type = usb_pipetype (urb->pipe); - maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input); + ep = usb_pipe_endpoint (urb->dev, urb->pipe); + maxp = usb_endpoint_maxp (&ep->desc); + mult = usb_endpoint_maxp_mult (&ep->desc); /* 1024 byte maxpacket is a hardware ceiling. High bandwidth * acts like up to 3KB, but is built from smaller packets. */ - if (max_packet(maxp) > 1024) { - ehci_dbg(ehci, "bogus qh maxpacket %d\n", max_packet(maxp)); + if (maxp > 1024) { + ehci_dbg(ehci, "bogus qh maxpacket %d\n", maxp); goto done; } @@ -809,8 +808,7 @@ qh_make ( unsigned tmp; qh->ps.usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, - is_input, 0, - hb_mult(maxp) * max_packet(maxp))); + is_input, 0, mult * maxp)); qh->ps.phase = NO_FRAME; if (urb->dev->speed == USB_SPEED_HIGH) { @@ -854,7 +852,7 @@ qh_make ( think_time = tt ? tt->think_time : 0; qh->ps.tt_usecs = NS_TO_US(think_time + usb_calc_bus_time (urb->dev->speed, - is_input, 0, max_packet (maxp))); + is_input, 0, maxp)); if (urb->interval > ehci->periodic_size) urb->interval = ehci->periodic_size; qh->ps.period = urb->interval; @@ -925,11 +923,11 @@ qh_make ( * to help them do so. So now people expect to use * such nonconformant devices with Linux too; sigh. */ - info1 |= max_packet(maxp) << 16; + info1 |= maxp << 16; info2 |= (EHCI_TUNE_MULT_HS << 30); } else { /* PIPE_INTERRUPT */ - info1 |= max_packet (maxp) << 16; - info2 |= hb_mult (maxp) << 30; + info1 |= maxp << 16; + info2 |= mult << 30; } break; default: @@ -1221,7 +1219,7 @@ static int submit_single_step_set_feature( token |= (1 /* "in" */ << 8); /*This is IN stage*/ - maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, 0)); + maxpacket = usb_maxpacket(urb->dev, urb->pipe, 0); qtd_fill(ehci, qtd, buf, len, token, maxpacket); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 1dfe54f14737..980a6b3b2da2 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1064,11 +1064,10 @@ iso_stream_init( /* knows about ITD vs SITD */ if (dev->speed == USB_SPEED_HIGH) { - unsigned multi = hb_mult(maxp); + unsigned multi = usb_endpoint_maxp_mult(&urb->ep->desc); stream->highspeed = 1; - maxp = max_packet(maxp); buf1 |= maxp; maxp *= multi; diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c index e42a29e8e229..63b9d0c67963 100644 --- a/drivers/usb/host/ehci-w90x900.c +++ b/drivers/usb/host/ehci-w90x900.c @@ -33,8 +33,7 @@ static const char hcd_name[] = "ehci-w90x900 "; static struct hc_driver __read_mostly ehci_w90x900_hc_driver; -static int usb_w90x900_probe(const struct hc_driver *driver, - struct platform_device *pdev) +static int ehci_w90x900_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct ehci_hcd *ehci; @@ -42,7 +41,8 @@ static int usb_w90x900_probe(const struct hc_driver *driver, int retval = 0, irq; unsigned long val; - hcd = usb_create_hcd(driver, &pdev->dev, "w90x900 EHCI"); + hcd = usb_create_hcd(&ehci_w90x900_hc_driver, + &pdev->dev, "w90x900 EHCI"); if (!hcd) { retval = -ENOMEM; goto err1; @@ -63,9 +63,9 @@ static int usb_w90x900_probe(const struct hc_driver *driver, HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); /* enable PHY 0,1,the regs only apply to w90p910 - * 0xA4,0xA8 were offsets of PHY0 and PHY1 controller of - * w90p910 IC relative to ehci->regs. - */ + * 0xA4,0xA8 were offsets of PHY0 and PHY1 controller of + * w90p910 IC relative to ehci->regs. + */ val = __raw_readl(ehci->regs+PHY0_CTR); val |= ENPHY; __raw_writel(val, ehci->regs+PHY0_CTR); @@ -92,26 +92,12 @@ err1: return retval; } -static void usb_w90x900_remove(struct usb_hcd *hcd, - struct platform_device *pdev) -{ - usb_remove_hcd(hcd); - usb_put_hcd(hcd); -} - -static int ehci_w90x900_probe(struct platform_device *pdev) -{ - if (usb_disabled()) - return -ENODEV; - - return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev); -} - static int ehci_w90x900_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); - usb_w90x900_remove(hcd, pdev); + usb_remove_hcd(hcd); + usb_put_hcd(hcd); return 0; } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 3f3b74aeca97..a8e36170d8b8 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -219,6 +219,7 @@ struct ehci_hcd { /* one per controller */ unsigned no_selective_suspend:1; unsigned has_fsl_port_bug:1; /* FreeScale */ unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */ + unsigned has_fsl_susp_errata:1; /* NXP SUSP quirk */ unsigned big_endian_mmio:1; unsigned big_endian_desc:1; unsigned big_endian_capbase:1; @@ -710,6 +711,13 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) #endif /* + * Some Freescale/NXP processors have an erratum (USB A-005697) + * in which we need to wait for 10ms for bus to enter suspend mode + * after setting SUSP bit. + */ +#define ehci_has_fsl_susp_errata(e) ((e)->has_fsl_susp_errata) + +/* * While most USB host controllers implement their registers in * little-endian format, a minority (celleb companion chip) implement * them in big endian format. diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index f07ccb25bc24..e90ddb530765 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -226,6 +226,8 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) of_property_read_bool(np, "fsl,usb-erratum-a007792"); pdata->has_fsl_erratum_a005275 = of_property_read_bool(np, "fsl,usb-erratum-a005275"); + pdata->has_fsl_erratum_a005697 = + of_property_read_bool(np, "fsl,usb_erratum-a005697"); /* * Determine whether phy_clk_valid needs to be checked diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 6cf82ee460a6..0f2b4b358e1a 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -147,7 +147,7 @@ static inline struct isp1362_ep_queue *get_ptd_queue(struct isp1362_hcd *isp1362 if (epq) DBG(1, "%s: PTD $%04x is on %s queue\n", __func__, offset, epq->name); else - pr_warning("%s: invalid PTD $%04x\n", __func__, offset); + pr_warn("%s: invalid PTD $%04x\n", __func__, offset); return epq; } @@ -157,8 +157,9 @@ static inline int get_ptd_offset(struct isp1362_ep_queue *epq, u8 index) int offset; if (index * epq->blk_size > epq->buf_size) { - pr_warning("%s: Bad %s index %d(%d)\n", __func__, epq->name, index, - epq->buf_size / epq->blk_size); + pr_warn("%s: Bad %s index %d(%d)\n", + __func__, epq->name, index, + epq->buf_size / epq->blk_size); return -EINVAL; } offset = epq->buf_start + index * epq->blk_size; @@ -902,8 +903,8 @@ static void start_iso_transfers(struct isp1362_hcd *isp1362_hcd) ptd_offset = next_ptd(epq, ep); if (ptd_offset < 0) { - pr_warning("%s: req %d No more %s PTD buffers available\n", __func__, - ep->num_req, epq->name); + pr_warn("%s: req %d No more %s PTD buffers available\n", + __func__, ep->num_req, epq->name); break; } } @@ -973,8 +974,8 @@ static void finish_transfers(struct isp1362_hcd *isp1362_hcd, unsigned long done break; } if (done_map) - pr_warning("%s: done_map not clear: %08lx:%08lx\n", __func__, done_map, - epq->skip_map); + pr_warn("%s: done_map not clear: %08lx:%08lx\n", + __func__, done_map, epq->skip_map); atomic_dec(&epq->finishing); } @@ -1433,7 +1434,7 @@ static int isp1362_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) } else DBG(1, "%s: urb %p active; wait4irq\n", __func__, urb); } else { - pr_warning("%s: No EP in URB %p\n", __func__, urb); + pr_warn("%s: No EP in URB %p\n", __func__, urb); retval = -EINVAL; } done: @@ -1748,10 +1749,10 @@ static int isp1362_bus_suspend(struct usb_hcd *hcd) /* FALL THROUGH */ case OHCI_USB_RESET: status = -EBUSY; - pr_warning("%s: needs reinit!\n", __func__); + pr_warn("%s: needs reinit!\n", __func__); goto done; case OHCI_USB_SUSPEND: - pr_warning("%s: already suspended?\n", __func__); + pr_warn("%s: already suspended?\n", __func__); goto done; } DBG(0, "%s: suspend root hub\n", __func__); @@ -1839,7 +1840,7 @@ static int isp1362_bus_resume(struct usb_hcd *hcd) isp1362_hcd->hc_control = isp1362_read_reg32(isp1362_hcd, HCCONTROL); pr_info("%s: HCCONTROL: %08x\n", __func__, isp1362_hcd->hc_control); if (hcd->state == HC_STATE_RESUMING) { - pr_warning("%s: duplicate resume\n", __func__); + pr_warn("%s: duplicate resume\n", __func__); status = 0; } else switch (isp1362_hcd->hc_control & OHCI_CTRL_HCFS) { @@ -2474,8 +2475,8 @@ static int isp1362_chip_test(struct isp1362_hcd *isp1362_hcd) __func__, offset); break; } - pr_warning("%s: memory check with offset %02x ok after second read\n", - __func__, offset); + pr_warn("%s: memory check with offset %02x ok after second read\n", + __func__, offset); } } kfree(ref); diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index b38a228134df..be9e63836881 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -14,8 +14,8 @@ #include <linux/clk.h> #include <linux/dma-mapping.h> +#include <linux/gpio/consumer.h> #include <linux/of_platform.h> -#include <linux/of_gpio.h> #include <linux/platform_device.h> #include <linux/platform_data/atmel.h> #include <linux/io.h> @@ -39,8 +39,8 @@ #define AT91_MAX_USBH_PORTS 3 struct at91_usbh_data { - int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */ - int overcurrent_pin[AT91_MAX_USBH_PORTS]; + struct gpio_desc *vbus_pin[AT91_MAX_USBH_PORTS]; + struct gpio_desc *overcurrent_pin[AT91_MAX_USBH_PORTS]; u8 ports; /* number of ports on root hub */ u8 overcurrent_supported; u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS]; @@ -68,8 +68,6 @@ static const struct ohci_driver_overrides ohci_at91_drv_overrides __initconst = .extra_priv_size = sizeof(struct ohci_at91_priv), }; -extern int usb_disabled(void); - /*-------------------------------------------------------------------------*/ static void at91_start_clock(struct ohci_at91_priv *ohci_at91) @@ -268,11 +266,8 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int if (!valid_port(port)) return; - if (!gpio_is_valid(pdata->vbus_pin[port])) - return; - - gpio_set_value(pdata->vbus_pin[port], - pdata->vbus_pin_active_low[port] ^ enable); + gpiod_set_value(pdata->vbus_pin[port], + pdata->vbus_pin_active_low[port] ^ enable); } static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) @@ -280,11 +275,8 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) if (!valid_port(port)) return -EINVAL; - if (!gpio_is_valid(pdata->vbus_pin[port])) - return -EINVAL; - - return gpio_get_value(pdata->vbus_pin[port]) ^ - pdata->vbus_pin_active_low[port]; + return gpiod_get_value(pdata->vbus_pin[port]) ^ + pdata->vbus_pin_active_low[port]; } /* @@ -474,16 +466,13 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) { struct platform_device *pdev = data; struct at91_usbh_data *pdata = dev_get_platdata(&pdev->dev); - int val, gpio, port; + int val, port; /* From the GPIO notifying the over-current situation, find * out the corresponding port */ at91_for_each_port(port) { - if (gpio_is_valid(pdata->overcurrent_pin[port]) && - gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { - gpio = pdata->overcurrent_pin[port]; + if (gpiod_to_irq(pdata->overcurrent_pin[port]) == irq) break; - } } if (port == AT91_MAX_USBH_PORTS) { @@ -491,7 +480,7 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) return IRQ_HANDLED; } - val = gpio_get_value(gpio); + val = gpiod_get_value(pdata->overcurrent_pin[port]); /* When notified of an over-current situation, disable power on the corresponding port, and mark this port in @@ -522,9 +511,8 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct at91_usbh_data *pdata; int i; - int gpio; int ret; - enum of_gpio_flags flags; + int err; u32 ports; /* Right now device-tree probed devices don't get dma_mask set. @@ -545,38 +533,16 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) pdata->ports = ports; at91_for_each_port(i) { - /* - * do not configure PIO if not in relation with - * real USB port on board - */ - if (i >= pdata->ports) { - pdata->vbus_pin[i] = -EINVAL; - pdata->overcurrent_pin[i] = -EINVAL; + pdata->vbus_pin[i] = devm_gpiod_get_optional(&pdev->dev, + "atmel,vbus-gpio", + GPIOD_IN); + if (IS_ERR(pdata->vbus_pin[i])) { + err = PTR_ERR(pdata->vbus_pin[i]); + dev_err(&pdev->dev, "unable to claim gpio \"vbus\": %d\n", err); continue; } - gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, - &flags); - pdata->vbus_pin[i] = gpio; - if (!gpio_is_valid(gpio)) - continue; - pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW; - - ret = gpio_request(gpio, "ohci_vbus"); - if (ret) { - dev_err(&pdev->dev, - "can't request vbus gpio %d\n", gpio); - continue; - } - ret = gpio_direction_output(gpio, - !pdata->vbus_pin_active_low[i]); - if (ret) { - dev_err(&pdev->dev, - "can't put vbus gpio %d as output %d\n", - gpio, !pdata->vbus_pin_active_low[i]); - gpio_free(gpio); - continue; - } + pdata->vbus_pin_active_low[i] = gpiod_get_value(pdata->vbus_pin[i]); ohci_at91_usb_set_power(pdata, i, 1); } @@ -586,37 +552,21 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) break; pdata->overcurrent_pin[i] = - of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags); - - if (!gpio_is_valid(pdata->overcurrent_pin[i])) - continue; - gpio = pdata->overcurrent_pin[i]; - - ret = gpio_request(gpio, "ohci_overcurrent"); - if (ret) { - dev_err(&pdev->dev, - "can't request overcurrent gpio %d\n", - gpio); + devm_gpiod_get_optional(&pdev->dev, + "atmel,oc-gpio", GPIOD_IN); + if (IS_ERR(pdata->overcurrent_pin[i])) { + err = PTR_ERR(pdata->overcurrent_pin[i]); + dev_err(&pdev->dev, "unable to claim gpio \"overcurrent\": %d\n", err); continue; } - ret = gpio_direction_input(gpio); - if (ret) { - dev_err(&pdev->dev, - "can't configure overcurrent gpio %d as input\n", - gpio); - gpio_free(gpio); - continue; - } - - ret = request_irq(gpio_to_irq(gpio), - ohci_hcd_at91_overcurrent_irq, - IRQF_SHARED, "ohci_overcurrent", pdev); - if (ret) { - gpio_free(gpio); - dev_err(&pdev->dev, - "can't get gpio IRQ for overcurrent\n"); - } + ret = devm_request_irq(&pdev->dev, + gpiod_to_irq(pdata->overcurrent_pin[i]), + ohci_hcd_at91_overcurrent_irq, + IRQF_SHARED, + "ohci_overcurrent", pdev); + if (ret) + dev_info(&pdev->dev, "failed to request gpio \"overcurrent\" IRQ\n"); } device_init_wakeup(&pdev->dev, 1); @@ -629,19 +579,8 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) int i; if (pdata) { - at91_for_each_port(i) { - if (!gpio_is_valid(pdata->vbus_pin[i])) - continue; + at91_for_each_port(i) ohci_at91_usb_set_power(pdata, i, 0); - gpio_free(pdata->vbus_pin[i]); - } - - at91_for_each_port(i) { - if (!gpio_is_valid(pdata->overcurrent_pin[i])) - continue; - free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev); - gpio_free(pdata->overcurrent_pin[i]); - } } device_init_wakeup(&pdev->dev, 0); diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index e5c33bc98ea4..05da2cb59612 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -11,62 +11,192 @@ * kind, whether express or implied. */ +#include <linux/clk.h> +#include <linux/io.h> #include <linux/interrupt.h> #include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/platform_device.h> -#include <linux/clk.h> - -#include <mach/da8xx.h> +#include <linux/phy/phy.h> #include <linux/platform_data/usb-davinci.h> +#include <linux/regulator/consumer.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <asm/unaligned.h> -#ifndef CONFIG_ARCH_DAVINCI_DA8XX -#error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX." -#endif +#include "ohci.h" -#define CFGCHIP2 DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG) +#define DRIVER_DESC "DA8XX" +#define DRV_NAME "ohci-da8xx" -static struct clk *usb11_clk; -static struct clk *usb20_clk; +static struct hc_driver __read_mostly ohci_da8xx_hc_driver; + +static int (*orig_ohci_hub_control)(struct usb_hcd *hcd, u16 typeReq, + u16 wValue, u16 wIndex, char *buf, u16 wLength); +static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf); + +struct da8xx_ohci_hcd { + struct usb_hcd *hcd; + struct clk *usb11_clk; + struct phy *usb11_phy; + struct regulator *vbus_reg; + struct notifier_block nb; + unsigned int reg_enabled; +}; + +#define to_da8xx_ohci(hcd) (struct da8xx_ohci_hcd *)(hcd_to_ohci(hcd)->priv) /* Over-current indicator change bitmask */ static volatile u16 ocic_mask; -static void ohci_da8xx_clock(int on) +static int ohci_da8xx_enable(struct usb_hcd *hcd) { - u32 cfgchip2; - - cfgchip2 = __raw_readl(CFGCHIP2); - if (on) { - clk_enable(usb11_clk); - - /* - * If USB 1.1 reference clock is sourced from USB 2.0 PHY, we - * need to enable the USB 2.0 module clocking, start its PHY, - * and not allow it to stop the clock during USB 2.0 suspend. - */ - if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX)) { - clk_enable(usb20_clk); - - cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN); - cfgchip2 |= CFGCHIP2_PHY_PLLON; - __raw_writel(cfgchip2, CFGCHIP2); - - pr_info("Waiting for USB PHY clock good...\n"); - while (!(__raw_readl(CFGCHIP2) & CFGCHIP2_PHYCLKGD)) - cpu_relax(); - } + struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); + int ret; + + ret = clk_prepare_enable(da8xx_ohci->usb11_clk); + if (ret) + return ret; + + ret = phy_init(da8xx_ohci->usb11_phy); + if (ret) + goto err_phy_init; + + ret = phy_power_on(da8xx_ohci->usb11_phy); + if (ret) + goto err_phy_power_on; + + return 0; + +err_phy_power_on: + phy_exit(da8xx_ohci->usb11_phy); +err_phy_init: + clk_disable_unprepare(da8xx_ohci->usb11_clk); + + return ret; +} + +static void ohci_da8xx_disable(struct usb_hcd *hcd) +{ + struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); + + phy_power_off(da8xx_ohci->usb11_phy); + phy_exit(da8xx_ohci->usb11_phy); + clk_disable_unprepare(da8xx_ohci->usb11_clk); +} - /* Enable USB 1.1 PHY */ - cfgchip2 |= CFGCHIP2_USB1SUSPENDM; - } else { - clk_disable(usb11_clk); - if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX)) - clk_disable(usb20_clk); +static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on) +{ + struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); + struct device *dev = hcd->self.controller; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); + int ret; + + if (hub && hub->set_power) + return hub->set_power(1, on); + + if (!da8xx_ohci->vbus_reg) + return 0; - /* Disable USB 1.1 PHY */ - cfgchip2 &= ~CFGCHIP2_USB1SUSPENDM; + if (on && !da8xx_ohci->reg_enabled) { + ret = regulator_enable(da8xx_ohci->vbus_reg); + if (ret) { + dev_err(dev, "Failed to enable regulator: %d\n", ret); + return ret; + } + da8xx_ohci->reg_enabled = 1; + + } else if (!on && da8xx_ohci->reg_enabled) { + ret = regulator_disable(da8xx_ohci->vbus_reg); + if (ret) { + dev_err(dev, "Failed to disable regulator: %d\n", ret); + return ret; + } + da8xx_ohci->reg_enabled = 0; } - __raw_writel(cfgchip2, CFGCHIP2); + + return 0; +} + +static int ohci_da8xx_get_power(struct usb_hcd *hcd) +{ + struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); + struct device *dev = hcd->self.controller; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); + + if (hub && hub->get_power) + return hub->get_power(1); + + if (da8xx_ohci->vbus_reg) + return regulator_is_enabled(da8xx_ohci->vbus_reg); + + return 1; +} + +static int ohci_da8xx_get_oci(struct usb_hcd *hcd) +{ + struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); + struct device *dev = hcd->self.controller; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); + unsigned int flags; + int ret; + + if (hub && hub->get_oci) + return hub->get_oci(1); + + if (!da8xx_ohci->vbus_reg) + return 0; + + ret = regulator_get_error_flags(da8xx_ohci->vbus_reg, &flags); + if (ret) + return ret; + + if (flags & REGULATOR_ERROR_OVER_CURRENT) + return 1; + + return 0; +} + +static int ohci_da8xx_has_set_power(struct usb_hcd *hcd) +{ + struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); + struct device *dev = hcd->self.controller; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); + + if (hub && hub->set_power) + return 1; + + if (da8xx_ohci->vbus_reg) + return 1; + + return 0; +} + +static int ohci_da8xx_has_oci(struct usb_hcd *hcd) +{ + struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); + struct device *dev = hcd->self.controller; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); + + if (hub && hub->get_oci) + return 1; + + if (da8xx_ohci->vbus_reg) + return 1; + + return 0; +} + +static int ohci_da8xx_has_potpgt(struct usb_hcd *hcd) +{ + struct device *dev = hcd->self.controller; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); + + if (hub && hub->potpgt) + return 1; + + return 0; } /* @@ -82,7 +212,51 @@ static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub, hub->set_power(port, 0); } -static int ohci_da8xx_init(struct usb_hcd *hcd) +static int ohci_da8xx_regulator_event(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct da8xx_ohci_hcd *da8xx_ohci = + container_of(nb, struct da8xx_ohci_hcd, nb); + + if (event & REGULATOR_EVENT_OVER_CURRENT) { + ocic_mask |= 1 << 1; + ohci_da8xx_set_power(da8xx_ohci->hcd, 0); + } + + return 0; +} + +static int ohci_da8xx_register_notify(struct usb_hcd *hcd) +{ + struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); + struct device *dev = hcd->self.controller; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); + int ret = 0; + + if (hub && hub->ocic_notify) { + ret = hub->ocic_notify(ohci_da8xx_ocic_handler); + } else if (da8xx_ohci->vbus_reg) { + da8xx_ohci->nb.notifier_call = ohci_da8xx_regulator_event; + ret = devm_regulator_register_notifier(da8xx_ohci->vbus_reg, + &da8xx_ohci->nb); + } + + if (ret) + dev_err(dev, "Failed to register notifier: %d\n", ret); + + return ret; +} + +static void ohci_da8xx_unregister_notify(struct usb_hcd *hcd) +{ + struct device *dev = hcd->self.controller; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); + + if (hub && hub->ocic_notify) + hub->ocic_notify(NULL); +} + +static int ohci_da8xx_reset(struct usb_hcd *hcd) { struct device *dev = hcd->self.controller; struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); @@ -92,7 +266,9 @@ static int ohci_da8xx_init(struct usb_hcd *hcd) dev_dbg(dev, "starting USB controller\n"); - ohci_da8xx_clock(1); + result = ohci_da8xx_enable(hcd); + if (result < 0) + return result; /* * DA8xx only have 1 port connected to the pins but the HC root hub @@ -100,9 +276,11 @@ static int ohci_da8xx_init(struct usb_hcd *hcd) */ ohci->num_ports = 1; - result = ohci_init(ohci); - if (result < 0) + result = ohci_setup(hcd); + if (result < 0) { + ohci_da8xx_disable(hcd); return result; + } /* * Since we're providing a board-specific root hub port power control @@ -111,45 +289,29 @@ static int ohci_da8xx_init(struct usb_hcd *hcd) * the correct hub descriptor... */ rh_a = ohci_readl(ohci, &ohci->regs->roothub.a); - if (hub->set_power) { + if (ohci_da8xx_has_set_power(hcd)) { rh_a &= ~RH_A_NPS; rh_a |= RH_A_PSM; } - if (hub->get_oci) { + if (ohci_da8xx_has_oci(hcd)) { rh_a &= ~RH_A_NOCP; rh_a |= RH_A_OCPM; } - rh_a &= ~RH_A_POTPGT; - rh_a |= hub->potpgt << 24; + if (ohci_da8xx_has_potpgt(hcd)) { + rh_a &= ~RH_A_POTPGT; + rh_a |= hub->potpgt << 24; + } ohci_writel(ohci, rh_a, &ohci->regs->roothub.a); return result; } -static void ohci_da8xx_stop(struct usb_hcd *hcd) -{ - ohci_stop(hcd); - ohci_da8xx_clock(0); -} - -static int ohci_da8xx_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int result; - - result = ohci_run(ohci); - if (result < 0) - ohci_da8xx_stop(hcd); - - return result; -} - /* * Update the status data from the hub with the over-current indicator change. */ static int ohci_da8xx_hub_status_data(struct usb_hcd *hcd, char *buf) { - int length = ohci_hub_status_data(hcd, buf); + int length = orig_ohci_hub_status_data(hcd, buf); /* See if we have OCIC bit set on port 1 */ if (ocic_mask & (1 << 1)) { @@ -171,7 +333,6 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct device *dev = hcd->self.controller; - struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); int temp; switch (typeReq) { @@ -185,11 +346,11 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = roothub_portstatus(hcd_to_ohci(hcd), wIndex - 1); /* The port power status (PPS) bit defaults to 1 */ - if (hub->get_power && hub->get_power(wIndex) == 0) + if (!ohci_da8xx_get_power(hcd)) temp &= ~RH_PS_PPS; /* The port over-current indicator (POCI) bit is always 0 */ - if (hub->get_oci && hub->get_oci(wIndex) > 0) + if (ohci_da8xx_get_oci(hcd) > 0) temp |= RH_PS_POCI; /* The over-current indicator change (OCIC) bit is 0 too */ @@ -214,10 +375,7 @@ check_port: dev_dbg(dev, "%sPortFeature(%u): %s\n", temp ? "Set" : "Clear", wIndex, "POWER"); - if (!hub->set_power) - return -EPIPE; - - return hub->set_power(wIndex, temp) ? -EPIPE : 0; + return ohci_da8xx_set_power(hcd, temp) ? -EPIPE : 0; case USB_PORT_FEAT_C_OVER_CURRENT: dev_dbg(dev, "%sPortFeature(%u): %s\n", temp ? "Set" : "Clear", wIndex, @@ -231,86 +389,61 @@ check_port: } } - return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); + return orig_ohci_hub_control(hcd, typeReq, wValue, + wIndex, buf, wLength); } -static const struct hc_driver ohci_da8xx_hc_driver = { - .description = hcd_name, - .product_desc = "DA8xx OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ohci_da8xx_init, - .start = ohci_da8xx_start, - .stop = ohci_da8xx_stop, - .shutdown = ohci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ohci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ohci_da8xx_hub_status_data, - .hub_control = ohci_da8xx_hub_control, - -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - /*-------------------------------------------------------------------------*/ +#ifdef CONFIG_OF +static const struct of_device_id da8xx_ohci_ids[] = { + { .compatible = "ti,da830-ohci" }, + { } +}; +MODULE_DEVICE_TABLE(of, da8xx_ohci_ids); +#endif - -/** - * usb_hcd_da8xx_probe - initialize DA8xx-based HCDs - * Context: !in_interrupt() - * - * Allocates basic resources for this USB host controller, and - * then invokes the start() method for the HCD associated with it - * through the hotplug entry's driver_data. - */ -static int usb_hcd_da8xx_probe(const struct hc_driver *driver, - struct platform_device *pdev) +static int ohci_da8xx_probe(struct platform_device *pdev) { - struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev); + struct da8xx_ohci_hcd *da8xx_ohci; struct usb_hcd *hcd; struct resource *mem; int error, irq; + hcd = usb_create_hcd(&ohci_da8xx_hc_driver, &pdev->dev, + dev_name(&pdev->dev)); + if (!hcd) + return -ENOMEM; - if (hub == NULL) - return -ENODEV; + da8xx_ohci = to_da8xx_ohci(hcd); + da8xx_ohci->hcd = hcd; - usb11_clk = devm_clk_get(&pdev->dev, "usb11"); - if (IS_ERR(usb11_clk)) - return PTR_ERR(usb11_clk); + da8xx_ohci->usb11_clk = devm_clk_get(&pdev->dev, "usb11"); + if (IS_ERR(da8xx_ohci->usb11_clk)) { + error = PTR_ERR(da8xx_ohci->usb11_clk); + if (error != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to get clock.\n"); + goto err; + } - usb20_clk = devm_clk_get(&pdev->dev, "usb20"); - if (IS_ERR(usb20_clk)) - return PTR_ERR(usb20_clk); + da8xx_ohci->usb11_phy = devm_phy_get(&pdev->dev, "usb-phy"); + if (IS_ERR(da8xx_ohci->usb11_phy)) { + error = PTR_ERR(da8xx_ohci->usb11_phy); + if (error != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to get phy.\n"); + goto err; + } - hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); - if (!hcd) - return -ENOMEM; + da8xx_ohci->vbus_reg = devm_regulator_get_optional(&pdev->dev, "vbus"); + if (IS_ERR(da8xx_ohci->vbus_reg)) { + error = PTR_ERR(da8xx_ohci->vbus_reg); + if (error == -ENODEV) { + da8xx_ohci->vbus_reg = NULL; + } else if (error == -EPROBE_DEFER) { + goto err; + } else { + dev_err(&pdev->dev, "Failed to get regulator\n"); + goto err; + } + } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); hcd->regs = devm_ioremap_resource(&pdev->dev, mem); @@ -321,60 +454,38 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, hcd->rsrc_start = mem->start; hcd->rsrc_len = resource_size(mem); - ohci_hcd_init(hcd_to_ohci(hcd)); - irq = platform_get_irq(pdev, 0); if (irq < 0) { error = -ENODEV; goto err; } + error = usb_add_hcd(hcd, irq, 0); if (error) goto err; device_wakeup_enable(hcd->self.controller); - if (hub->ocic_notify) { - error = hub->ocic_notify(ohci_da8xx_ocic_handler); - if (!error) - return 0; - } + error = ohci_da8xx_register_notify(hcd); + if (error) + goto err_remove_hcd; + + return 0; +err_remove_hcd: usb_remove_hcd(hcd); err: usb_put_hcd(hcd); return error; } -/** - * usb_hcd_da8xx_remove - shutdown processing for DA8xx-based HCDs - * @dev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_hcd_da8xx_probe(), first invoking - * the HCD's stop() method. It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - */ -static inline void -usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev) +static int ohci_da8xx_remove(struct platform_device *pdev) { - struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev); + struct usb_hcd *hcd = platform_get_drvdata(pdev); - hub->ocic_notify(NULL); + ohci_da8xx_unregister_notify(hcd); usb_remove_hcd(hcd); usb_put_hcd(hcd); -} - -static int ohci_hcd_da8xx_drv_probe(struct platform_device *dev) -{ - return usb_hcd_da8xx_probe(&ohci_da8xx_hc_driver, dev); -} - -static int ohci_hcd_da8xx_drv_remove(struct platform_device *dev) -{ - struct usb_hcd *hcd = platform_get_drvdata(dev); - - usb_hcd_da8xx_remove(hcd, dev); return 0; } @@ -397,7 +508,7 @@ static int ohci_da8xx_suspend(struct platform_device *pdev, if (ret) return ret; - ohci_da8xx_clock(0); + ohci_da8xx_disable(hcd); hcd->state = HC_STATE_SUSPENDED; return ret; @@ -407,32 +518,77 @@ static int ohci_da8xx_resume(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int ret; if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; - ohci_da8xx_clock(1); - dev->dev.power.power_state = PMSG_ON; - usb_hcd_resume_root_hub(hcd); + ret = ohci_da8xx_enable(hcd); + if (ret) + return ret; + + ohci_resume(hcd, false); + return 0; } #endif +static const struct ohci_driver_overrides da8xx_overrides __initconst = { + .reset = ohci_da8xx_reset, + .extra_priv_size = sizeof(struct da8xx_ohci_hcd), +}; + /* * Driver definition to register with platform structure. */ static struct platform_driver ohci_hcd_da8xx_driver = { - .probe = ohci_hcd_da8xx_drv_probe, - .remove = ohci_hcd_da8xx_drv_remove, + .probe = ohci_da8xx_probe, + .remove = ohci_da8xx_remove, .shutdown = usb_hcd_platform_shutdown, #ifdef CONFIG_PM .suspend = ohci_da8xx_suspend, .resume = ohci_da8xx_resume, #endif .driver = { - .name = "ohci", + .name = DRV_NAME, + .of_match_table = of_match_ptr(da8xx_ohci_ids), }, }; -MODULE_ALIAS("platform:ohci"); +static int __init ohci_da8xx_init(void) +{ + + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", DRV_NAME); + ohci_init_driver(&ohci_da8xx_hc_driver, &da8xx_overrides); + + /* + * The Davinci da8xx HW has some unusual quirks, which require + * da8xx-specific workarounds. We override certain hc_driver + * functions here to achieve that. We explicitly do not enhance + * ohci_driver_overrides to allow this more easily, since this + * is an unusual case, and we don't want to encourage others to + * override these functions by making it too easy. + */ + + orig_ohci_hub_control = ohci_da8xx_hc_driver.hub_control; + orig_ohci_hub_status_data = ohci_da8xx_hc_driver.hub_status_data; + + ohci_da8xx_hc_driver.hub_status_data = ohci_da8xx_hub_status_data; + ohci_da8xx_hc_driver.hub_control = ohci_da8xx_hub_control; + + return platform_driver_register(&ohci_hcd_da8xx_driver); +} +module_init(ohci_da8xx_init); + +static void __exit ohci_da8xx_exit(void) +{ + platform_driver_unregister(&ohci_hcd_da8xx_driver); +} +module_exit(ohci_da8xx_exit); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 86612ac3fda2..8685cf3e6292 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1219,11 +1219,6 @@ MODULE_LICENSE ("GPL"); #define SA1111_DRIVER ohci_hcd_sa1111_driver #endif -#ifdef CONFIG_USB_OHCI_HCD_DAVINCI -#include "ohci-da8xx.c" -#define DAVINCI_PLATFORM_DRIVER ohci_hcd_da8xx_driver -#endif - #ifdef CONFIG_USB_OHCI_HCD_PPC_OF #include "ohci-ppc-of.c" #define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver @@ -1303,19 +1298,9 @@ static int __init ohci_hcd_mod_init(void) goto error_tmio; #endif -#ifdef DAVINCI_PLATFORM_DRIVER - retval = platform_driver_register(&DAVINCI_PLATFORM_DRIVER); - if (retval < 0) - goto error_davinci; -#endif - return retval; /* Error path */ -#ifdef DAVINCI_PLATFORM_DRIVER - platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); - error_davinci: -#endif #ifdef TMIO_OHCI_DRIVER platform_driver_unregister(&TMIO_OHCI_DRIVER); error_tmio: @@ -1351,9 +1336,6 @@ module_init(ohci_hcd_mod_init); static void __exit ohci_hcd_mod_exit(void) { -#ifdef DAVINCI_PLATFORM_DRIVER - platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); -#endif #ifdef TMIO_OHCI_DRIVER platform_driver_unregister(&TMIO_OHCI_DRIVER); #endif diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index c9e315c6808a..ed8a762b8670 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c @@ -88,10 +88,9 @@ td_alloc (struct ohci_hcd *hc, gfp_t mem_flags) dma_addr_t dma; struct td *td; - td = dma_pool_alloc (hc->td_cache, mem_flags, &dma); + td = dma_pool_zalloc (hc->td_cache, mem_flags, &dma); if (td) { /* in case hc fetches it, make it look dead */ - memset (td, 0, sizeof *td); td->hwNextTD = cpu_to_hc32 (hc, dma); td->td_dma = dma; /* hashed in td_fill */ @@ -122,9 +121,8 @@ ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags) dma_addr_t dma; struct ed *ed; - ed = dma_pool_alloc (hc->ed_cache, mem_flags, &dma); + ed = dma_pool_zalloc (hc->ed_cache, mem_flags, &dma); if (ed) { - memset (ed, 0, sizeof (*ed)); INIT_LIST_HEAD (&ed->td_list); ed->dma = dma; } diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c index b7d4756232ae..6df8e2ed40fd 100644 --- a/drivers/usb/host/ohci-nxp.c +++ b/drivers/usb/host/ohci-nxp.c @@ -56,8 +56,6 @@ static struct hc_driver __read_mostly ohci_nxp_hc_driver; static struct i2c_client *isp1301_i2c_client; -extern int usb_disabled(void); - static struct clk *usb_host_clk; static void isp1301_configure_lpc32xx(void) @@ -127,6 +125,7 @@ static inline void isp1301_vbus_off(void) static void ohci_nxp_start_hc(void) { unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN; + __raw_writel(tmp, USB_OTG_STAT_CONTROL); isp1301_vbus_on(); } @@ -134,6 +133,7 @@ static void ohci_nxp_start_hc(void) static void ohci_nxp_stop_hc(void) { unsigned long tmp; + isp1301_vbus_off(); tmp = __raw_readl(USB_OTG_STAT_CONTROL) & ~HOST_EN; __raw_writel(tmp, USB_OTG_STAT_CONTROL); @@ -155,9 +155,8 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev) } isp1301_i2c_client = isp1301_get_client(isp1301_node); - if (!isp1301_i2c_client) { + if (!isp1301_i2c_client) return -EPROBE_DEFER; - } ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); if (ret) diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 495c1454b9e8..b08e385399b9 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -68,9 +68,6 @@ static inline int tps65010_set_gpio_out_value(unsigned gpio, unsigned value) #endif -extern int usb_disabled(void); -extern int ocpi_enable(void); - static struct clk *usb_host_ck; static struct clk *usb_dc_ck; @@ -296,15 +293,14 @@ static int ohci_omap_reset(struct usb_hcd *hcd) /*-------------------------------------------------------------------------*/ /** - * usb_hcd_omap_probe - initialize OMAP-based HCDs + * ohci_hcd_omap_probe - initialize OMAP-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. */ -static int usb_hcd_omap_probe (const struct hc_driver *driver, - struct platform_device *pdev) +static int ohci_hcd_omap_probe(struct platform_device *pdev) { int retval, irq; struct usb_hcd *hcd = 0; @@ -336,7 +332,8 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, } - hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev)); + hcd = usb_create_hcd(&ohci_omap_hc_driver, &pdev->dev, + dev_name(&pdev->dev)); if (!hcd) { retval = -ENOMEM; goto err0; @@ -384,17 +381,18 @@ err0: /* may be called with controller, bus, and devices active */ /** - * usb_hcd_omap_remove - shutdown processing for OMAP-based HCDs + * ohci_hcd_omap_remove - shutdown processing for OMAP-based HCDs * @dev: USB Host Controller being removed * Context: !in_interrupt() * - * Reverses the effect of usb_hcd_omap_probe(), first invoking + * Reverses the effect of ohci_hcd_omap_probe(), first invoking * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. */ -static inline void -usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) +static int ohci_hcd_omap_remove(struct platform_device *pdev) { + struct usb_hcd *hcd = platform_get_drvdata(pdev); + dev_dbg(hcd->self.controller, "stopping USB Controller\n"); usb_remove_hcd(hcd); omap_ohci_clock_power(0); @@ -409,21 +407,6 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) usb_put_hcd(hcd); clk_put(usb_dc_ck); clk_put(usb_host_ck); -} - -/*-------------------------------------------------------------------------*/ - -static int ohci_hcd_omap_drv_probe(struct platform_device *dev) -{ - return usb_hcd_omap_probe(&ohci_omap_hc_driver, dev); -} - -static int ohci_hcd_omap_drv_remove(struct platform_device *dev) -{ - struct usb_hcd *hcd = platform_get_drvdata(dev); - - usb_hcd_omap_remove(hcd, dev); - return 0; } @@ -472,8 +455,8 @@ static int ohci_omap_resume(struct platform_device *dev) * Driver definition to register with the OMAP bus */ static struct platform_driver ohci_hcd_omap_driver = { - .probe = ohci_hcd_omap_drv_probe, - .remove = ohci_hcd_omap_drv_remove, + .probe = ohci_hcd_omap_probe, + .remove = ohci_hcd_omap_remove, .shutdown = usb_hcd_platform_shutdown, #ifdef CONFIG_PM .suspend = ohci_omap_suspend, diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index a667cf2d5788..79efde8f21e0 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -404,7 +404,7 @@ static int ohci_pxa_of_init(struct platform_device *pdev) /** - * usb_hcd_pxa27x_probe - initialize pxa27x-based HCDs + * ohci_hcd_pxa27x_probe - initialize pxa27x-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and @@ -412,7 +412,7 @@ static int ohci_pxa_of_init(struct platform_device *pdev) * through the hotplug entry's driver_data. * */ -int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev) +static int ohci_hcd_pxa27x_probe(struct platform_device *pdev) { int retval, irq; struct usb_hcd *hcd; @@ -442,7 +442,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device if (IS_ERR(usb_clk)) return PTR_ERR(usb_clk); - hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x"); + hcd = usb_create_hcd(&ohci_pxa27x_hc_driver, &pdev->dev, "pxa27x"); if (!hcd) return -ENOMEM; @@ -503,17 +503,18 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device /* may be called with controller, bus, and devices active */ /** - * usb_hcd_pxa27x_remove - shutdown processing for pxa27x-based HCDs + * ohci_hcd_pxa27x_remove - shutdown processing for pxa27x-based HCDs * @dev: USB Host Controller being removed * Context: !in_interrupt() * - * Reverses the effect of usb_hcd_pxa27x_probe(), first invoking + * Reverses the effect of ohci_hcd_pxa27x_probe(), first invoking * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. * */ -void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev) +static int ohci_hcd_pxa27x_remove(struct platform_device *pdev) { + struct usb_hcd *hcd = platform_get_drvdata(pdev); struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd); unsigned int i; @@ -524,28 +525,11 @@ void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev) pxa27x_ohci_set_vbus_power(pxa_ohci, i, false); usb_put_hcd(hcd); + return 0; } /*-------------------------------------------------------------------------*/ -static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev) -{ - pr_debug ("In ohci_hcd_pxa27x_drv_probe"); - - if (usb_disabled()) - return -ENODEV; - - return usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev); -} - -static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_hcd_pxa27x_remove(hcd, pdev); - return 0; -} - #ifdef CONFIG_PM static int ohci_hcd_pxa27x_drv_suspend(struct device *dev) { @@ -598,8 +582,8 @@ static const struct dev_pm_ops ohci_hcd_pxa27x_pm_ops = { #endif static struct platform_driver ohci_hcd_pxa27x_driver = { - .probe = ohci_hcd_pxa27x_drv_probe, - .remove = ohci_hcd_pxa27x_drv_remove, + .probe = ohci_hcd_pxa27x_probe, + .remove = ohci_hcd_pxa27x_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "pxa27x-ohci", diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 7a1919ca543a..b006b93126f7 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -43,6 +43,8 @@ static const char hcd_name[] = "ohci-s3c2410"; static struct clk *clk; static struct clk *usb_clk; +static struct hc_driver __read_mostly ohci_s3c2410_hc_driver; + /* forward definitions */ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc); @@ -321,26 +323,29 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc) /* may be called with controller, bus, and devices active */ /* - * usb_hcd_s3c2410_remove - shutdown processing for HCD + * ohci_hcd_s3c2410_remove - shutdown processing for HCD * @dev: USB Host Controller being removed * Context: !in_interrupt() * - * Reverses the effect of usb_hcd_3c2410_probe(), first invoking + * Reverses the effect of ohci_hcd_3c2410_probe(), first invoking * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. * */ -static void -usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev) +static int +ohci_hcd_s3c2410_remove(struct platform_device *dev) { + struct usb_hcd *hcd = platform_get_drvdata(dev); + usb_remove_hcd(hcd); s3c2410_stop_hc(dev); usb_put_hcd(hcd); + return 0; } /** - * usb_hcd_s3c2410_probe - initialize S3C2410-based HCDs + * ohci_hcd_s3c2410_probe - initialize S3C2410-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and @@ -348,8 +353,7 @@ usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev) * through the hotplug entry's driver_data. * */ -static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, - struct platform_device *dev) +static int ohci_hcd_s3c2410_probe(struct platform_device *dev) { struct usb_hcd *hcd = NULL; struct s3c2410_hcd_info *info = dev_get_platdata(&dev->dev); @@ -358,7 +362,7 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, s3c2410_usb_set_power(info, 1, 1); s3c2410_usb_set_power(info, 2, 1); - hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx"); + hcd = usb_create_hcd(&ohci_s3c2410_hc_driver, &dev->dev, "s3c24xx"); if (hcd == NULL) return -ENOMEM; @@ -404,21 +408,6 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, /*-------------------------------------------------------------------------*/ -static struct hc_driver __read_mostly ohci_s3c2410_hc_driver; - -static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev) -{ - return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev); -} - -static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_hcd_s3c2410_remove(hcd, pdev); - return 0; -} - #ifdef CONFIG_PM static int ohci_hcd_s3c2410_drv_suspend(struct device *dev) { @@ -457,13 +446,21 @@ static const struct dev_pm_ops ohci_hcd_s3c2410_pm_ops = { .resume = ohci_hcd_s3c2410_drv_resume, }; +static const struct of_device_id ohci_hcd_s3c2410_dt_ids[] = { + { .compatible = "samsung,s3c2410-ohci" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, ohci_hcd_s3c2410_dt_ids); + static struct platform_driver ohci_hcd_s3c2410_driver = { - .probe = ohci_hcd_s3c2410_drv_probe, - .remove = ohci_hcd_s3c2410_drv_remove, + .probe = ohci_hcd_s3c2410_probe, + .remove = ohci_hcd_s3c2410_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "s3c2410-ohci", .pm = &ohci_hcd_s3c2410_pm_ops, + .of_match_table = ohci_hcd_s3c2410_dt_ids, }, }; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 6afe32381209..321de2e0161b 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1032,7 +1032,6 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, goto fail; dev->num_rings_cached = 0; - init_completion(&dev->cmd_completion); dev->udev = udev; /* Point to output device context in dcbaa. */ @@ -1370,7 +1369,7 @@ static u32 xhci_get_endpoint_max_burst(struct usb_device *udev, if (udev->speed == USB_SPEED_HIGH && (usb_endpoint_xfer_isoc(&ep->desc) || usb_endpoint_xfer_int(&ep->desc))) - return (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; + return usb_endpoint_maxp_mult(&ep->desc) - 1; return 0; } @@ -1415,10 +1414,10 @@ static u32 xhci_get_max_esit_payload(struct usb_device *udev, else if (udev->speed >= USB_SPEED_SUPER) return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); - max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); - max_burst = (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; + max_packet = usb_endpoint_maxp(&ep->desc); + max_burst = usb_endpoint_maxp_mult(&ep->desc); /* A 0 in max burst means 1 transfer per ESIT */ - return max_packet * (max_burst + 1); + return max_packet * max_burst; } /* Set up an endpoint with one ring segment. Do not allocate stream rings. @@ -1461,7 +1460,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, max_esit_payload = xhci_get_max_esit_payload(udev, ep); interval = xhci_get_endpoint_interval(udev, ep); mult = xhci_get_endpoint_mult(udev, ep); - max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); + max_packet = usb_endpoint_maxp(&ep->desc); max_burst = xhci_get_endpoint_max_burst(udev, ep); avg_trb_len = max_esit_payload; @@ -2384,7 +2383,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * "physically contiguous and 64-byte (cache line) aligned". */ xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma, - GFP_KERNEL); + flags); if (!xhci->dcbaa) goto fail; memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa)); @@ -2480,7 +2479,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->erst.entries = dma_alloc_coherent(dev, sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS, &dma, - GFP_KERNEL); + flags); if (!xhci->erst.entries) goto fail; xhci_dbg_trace(xhci, trace_xhci_dbg_init, @@ -2536,7 +2535,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * something other than the default (~1ms minimum between interrupts). * See section 5.5.1.2. */ - init_completion(&xhci->addr_dev); for (i = 0; i < MAX_HC_SLOTS; ++i) xhci->devs[i] = NULL; for (i = 0; i < USB_MAXCHILDREN; ++i) { diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c index 73f763c4f5f5..6e7ddf6cafae 100644 --- a/drivers/usb/host/xhci-mtk-sch.c +++ b/drivers/usb/host/xhci-mtk-sch.c @@ -337,7 +337,7 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, xhci_dbg(xhci, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n", __func__, usb_endpoint_type(&ep->desc), udev->speed, - GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)), + usb_endpoint_maxp(&ep->desc), usb_endpoint_dir_in(&ep->desc), ep); if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) { @@ -403,7 +403,7 @@ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, xhci_dbg(xhci, "%s() type:%d, speed:%d, mpks:%d, dir:%d, ep:%p\n", __func__, usb_endpoint_type(&ep->desc), udev->speed, - GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)), + usb_endpoint_maxp(&ep->desc), usb_endpoint_dir_in(&ep->desc), ep); if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 79959f17c38c..1094ebd2838f 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -94,6 +94,9 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) int ret; int i; + if (!mtk->has_ippc) + return 0; + /* power on host ip */ value = readl(&ippc->ip_pw_ctr1); value &= ~CTRL1_IP_HOST_PDN; @@ -139,6 +142,9 @@ static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk) int ret; int i; + if (!mtk->has_ippc) + return 0; + /* power down all u3 ports */ for (i = 0; i < mtk->num_u3_ports; i++) { value = readl(&ippc->u3_ctrl_p[i]); @@ -173,6 +179,9 @@ static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk) struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs; u32 value; + if (!mtk->has_ippc) + return 0; + /* reset whole ip */ value = readl(&ippc->ip_pw_ctr0); value |= CTRL0_IP_SW_RST; @@ -475,6 +484,7 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci) /* called during probe() after chip reset completes */ static int xhci_mtk_setup(struct usb_hcd *hcd) { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd); int ret; @@ -482,12 +492,21 @@ static int xhci_mtk_setup(struct usb_hcd *hcd) ret = xhci_mtk_ssusb_config(mtk); if (ret) return ret; + } + + ret = xhci_gen_setup(hcd, xhci_mtk_quirks); + if (ret) + return ret; + + if (usb_hcd_is_primary_hcd(hcd)) { + mtk->num_u3_ports = xhci->num_usb3_ports; + mtk->num_u2_ports = xhci->num_usb2_ports; ret = xhci_mtk_sch_init(mtk); if (ret) return ret; } - return xhci_gen_setup(hcd, xhci_mtk_quirks); + return ret; } static int xhci_mtk_probe(struct platform_device *pdev) @@ -586,7 +605,7 @@ static int xhci_mtk_probe(struct platform_device *pdev) mtk->hcd = platform_get_drvdata(pdev); platform_set_drvdata(pdev, mtk); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac"); hcd->regs = devm_ioremap_resource(dev, res); if (IS_ERR(hcd->regs)) { ret = PTR_ERR(hcd->regs); @@ -595,11 +614,16 @@ static int xhci_mtk_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - mtk->ippc_regs = devm_ioremap_resource(dev, res); - if (IS_ERR(mtk->ippc_regs)) { - ret = PTR_ERR(mtk->ippc_regs); - goto put_usb2_hcd; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ippc"); + if (res) { /* ippc register is optional */ + mtk->ippc_regs = devm_ioremap_resource(dev, res); + if (IS_ERR(mtk->ippc_regs)) { + ret = PTR_ERR(mtk->ippc_regs); + goto put_usb2_hcd; + } + mtk->has_ippc = true; + } else { + mtk->has_ippc = false; } for (phy_num = 0; phy_num < mtk->num_phys; phy_num++) { diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h index 7da677c79ea8..2845c49efe1b 100644 --- a/drivers/usb/host/xhci-mtk.h +++ b/drivers/usb/host/xhci-mtk.h @@ -118,6 +118,7 @@ struct xhci_hcd_mtk { struct usb_hcd *hcd; struct mu3h_sch_bw_info *sch_array; struct mu3c_ippc_regs __iomem *ippc_regs; + bool has_ippc; int num_u2_ports; int num_u3_ports; struct regulator *vusb33; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index ed56bf9ed885..ddfab301e366 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -100,6 +100,12 @@ static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen3 = { .plat_start = xhci_rcar_start, }; +static const struct xhci_plat_priv xhci_plat_renesas_rcar_r8a7796 = { + .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V3, + .init_quirk = xhci_rcar_init_quirk, + .plat_start = xhci_rcar_start, +}; + static const struct of_device_id usb_xhci_of_match[] = { { .compatible = "generic-xhci", @@ -124,6 +130,9 @@ static const struct of_device_id usb_xhci_of_match[] = { .compatible = "renesas,xhci-r8a7795", .data = &xhci_plat_renesas_rcar_gen3, }, { + .compatible = "renesas,xhci-r8a7796", + .data = &xhci_plat_renesas_rcar_r8a7796, + }, { .compatible = "renesas,rcar-gen2-xhci", .data = &xhci_plat_renesas_rcar_gen2, }, { diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index 0e4535e632ec..d28df386e780 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -19,6 +19,8 @@ #include "xhci-rcar.h" /* +* - The V3 firmware is for r8a7796 (with good performance). +* - The V2 firmware can be used on both r8a7795 (es1.x) and r8a7796. * - The V2 firmware is possible to use on R-Car Gen2. However, the V2 causes * performance degradation. So, this driver continues to use the V1 if R-Car * Gen2. @@ -26,6 +28,7 @@ */ MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V1); MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V2); +MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V3); /*** Register Offset ***/ #define RCAR_USB3_INT_ENA 0x224 /* Interrupt Enable */ @@ -92,6 +95,7 @@ static int xhci_rcar_is_gen3(struct device *dev) struct device_node *node = dev->of_node; return of_device_is_compatible(node, "renesas,xhci-r8a7795") || + of_device_is_compatible(node, "renesas,xhci-r8a7796") || of_device_is_compatible(node, "renesas,rcar-gen3-xhci"); } diff --git a/drivers/usb/host/xhci-rcar.h b/drivers/usb/host/xhci-rcar.h index 2941a25cfe98..d2ffe20401cf 100644 --- a/drivers/usb/host/xhci-rcar.h +++ b/drivers/usb/host/xhci-rcar.h @@ -13,6 +13,7 @@ #define XHCI_RCAR_FIRMWARE_NAME_V1 "r8a779x_usb3_v1.dlmem" #define XHCI_RCAR_FIRMWARE_NAME_V2 "r8a779x_usb3_v2.dlmem" +#define XHCI_RCAR_FIRMWARE_NAME_V3 "r8a779x_usb3_v3.dlmem" #if IS_ENABLED(CONFIG_USB_XHCI_RCAR) void xhci_rcar_start(struct usb_hcd *hcd); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 797137e26549..bdf6b13d9b67 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -89,6 +89,11 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, return seg->dma + (segment_offset * sizeof(*trb)); } +static bool trb_is_noop(union xhci_trb *trb) +{ + return TRB_TYPE_NOOP_LE32(trb->generic.field[3]); +} + static bool trb_is_link(union xhci_trb *trb) { return TRB_TYPE_LINK_LE32(trb->link.control); @@ -110,6 +115,20 @@ static bool link_trb_toggles_cycle(union xhci_trb *trb) return le32_to_cpu(trb->link.control) & LINK_TOGGLE; } +static bool last_td_in_urb(struct xhci_td *td) +{ + struct urb_priv *urb_priv = td->urb->hcpriv; + + return urb_priv->td_cnt == urb_priv->length; +} + +static void inc_td_cnt(struct urb *urb) +{ + struct urb_priv *urb_priv = urb->hcpriv; + + urb_priv->td_cnt++; +} + /* Updates trb to point to the next TRB in the ring, and updates seg if the next * TRB is in a new segment. This does not skip over link TRBs, and it does not * effect the ring dequeue or enqueue pointers. @@ -303,7 +322,6 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) "maybe the host is dead\n"); del_timer(&xhci->cmd_timer); xhci->xhc_state |= XHCI_STATE_DYING; - xhci_quiesce(xhci); xhci_halt(xhci); return -ESHUTDOWN; } @@ -473,9 +491,8 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, if (new_deq == cur_td->last_trb) td_last_trb_found = true; - if (cycle_found && - TRB_TYPE_LINK_LE32(new_deq->generic.field[3]) && - new_deq->generic.field[3] & cpu_to_le32(LINK_TOGGLE)) + if (cycle_found && trb_is_link(new_deq) && + link_trb_toggles_cycle(new_deq)) state->new_cycle_state ^= 0x1; next_trb(xhci, ep_ring, &new_seg, &new_deq); @@ -511,54 +528,32 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, * of this TD.) This is used to remove partially enqueued isoc TDs from a ring. */ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, - struct xhci_td *cur_td, bool flip_cycle) + struct xhci_td *td, bool flip_cycle) { - struct xhci_segment *cur_seg; - union xhci_trb *cur_trb; - - for (cur_seg = cur_td->start_seg, cur_trb = cur_td->first_trb; - true; - next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) { - if (TRB_TYPE_LINK_LE32(cur_trb->generic.field[3])) { - /* Unchain any chained Link TRBs, but - * leave the pointers intact. - */ - cur_trb->generic.field[3] &= cpu_to_le32(~TRB_CHAIN); - /* Flip the cycle bit (link TRBs can't be the first - * or last TRB). - */ - if (flip_cycle) - cur_trb->generic.field[3] ^= - cpu_to_le32(TRB_CYCLE); - xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, - "Cancel (unchain) link TRB"); - xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, - "Address = %p (0x%llx dma); " - "in seg %p (0x%llx dma)", - cur_trb, - (unsigned long long)xhci_trb_virt_to_dma(cur_seg, cur_trb), - cur_seg, - (unsigned long long)cur_seg->dma); + struct xhci_segment *seg = td->start_seg; + union xhci_trb *trb = td->first_trb; + + while (1) { + if (trb_is_link(trb)) { + /* unchain chained link TRBs */ + trb->link.control &= cpu_to_le32(~TRB_CHAIN); } else { - cur_trb->generic.field[0] = 0; - cur_trb->generic.field[1] = 0; - cur_trb->generic.field[2] = 0; + trb->generic.field[0] = 0; + trb->generic.field[1] = 0; + trb->generic.field[2] = 0; /* Preserve only the cycle bit of this TRB */ - cur_trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE); - /* Flip the cycle bit except on the first or last TRB */ - if (flip_cycle && cur_trb != cur_td->first_trb && - cur_trb != cur_td->last_trb) - cur_trb->generic.field[3] ^= - cpu_to_le32(TRB_CYCLE); - cur_trb->generic.field[3] |= cpu_to_le32( + trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE); + trb->generic.field[3] |= cpu_to_le32( TRB_TYPE(TRB_TR_NOOP)); - xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, - "TRB to noop at offset 0x%llx", - (unsigned long long) - xhci_trb_virt_to_dma(cur_seg, cur_trb)); } - if (cur_trb == cur_td->last_trb) + /* flip cycle if asked to */ + if (flip_cycle && trb != td->first_trb && trb != td->last_trb) + trb->generic.field[3] ^= cpu_to_le32(TRB_CYCLE); + + if (trb == td->last_trb) break; + + next_trb(xhci, ep_ring, &seg, &trb); } } @@ -574,39 +569,33 @@ static void xhci_stop_watchdog_timer_in_irq(struct xhci_hcd *xhci, ep->stop_cmds_pending--; } -/* Must be called with xhci->lock held in interrupt context */ +/* + * Must be called with xhci->lock held in interrupt context, + * releases and re-acquires xhci->lock + */ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci, - struct xhci_td *cur_td, int status) + struct xhci_td *cur_td, int status) { - struct usb_hcd *hcd; - struct urb *urb; - struct urb_priv *urb_priv; + struct urb *urb = cur_td->urb; + struct urb_priv *urb_priv = urb->hcpriv; + struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); - urb = cur_td->urb; - urb_priv = urb->hcpriv; - urb_priv->td_cnt++; - hcd = bus_to_hcd(urb->dev->bus); - - /* Only giveback urb when this is the last td in urb */ - if (urb_priv->td_cnt == urb_priv->length) { - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs--; - if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) { - if (xhci->quirks & XHCI_AMD_PLL_FIX) - usb_amd_quirk_pll_enable(); - } + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { + xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs--; + if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) { + if (xhci->quirks & XHCI_AMD_PLL_FIX) + usb_amd_quirk_pll_enable(); } - usb_hcd_unlink_urb_from_ep(hcd, urb); - - spin_unlock(&xhci->lock); - usb_hcd_giveback_urb(hcd, urb, status); - xhci_urb_free_priv(urb_priv); - spin_lock(&xhci->lock); } + xhci_urb_free_priv(urb_priv); + usb_hcd_unlink_urb_from_ep(hcd, urb); + spin_unlock(&xhci->lock); + usb_hcd_giveback_urb(hcd, urb, status); + spin_lock(&xhci->lock); } -void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci, struct xhci_ring *ring, - struct xhci_td *td) +static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci, + struct xhci_ring *ring, struct xhci_td *td) { struct device *dev = xhci_to_hcd(xhci)->self.controller; struct xhci_segment *seg = td->bounce_seg; @@ -752,7 +741,9 @@ remove_finished_td: ep_ring = xhci_urb_to_transfer_ring(xhci, cur_td->urb); if (ep_ring && cur_td->bounce_seg) xhci_unmap_td_bounce_buffer(xhci, ep_ring, cur_td); - xhci_giveback_urb_in_irq(xhci, cur_td, 0); + inc_td_cnt(cur_td->urb); + if (last_td_in_urb(cur_td)) + xhci_giveback_urb_in_irq(xhci, cur_td, 0); /* Stop processing the cancelled list if the watchdog timer is * running. @@ -777,7 +768,10 @@ static void xhci_kill_ring_urbs(struct xhci_hcd *xhci, struct xhci_ring *ring) if (cur_td->bounce_seg) xhci_unmap_td_bounce_buffer(xhci, ring, cur_td); - xhci_giveback_urb_in_irq(xhci, cur_td, -ESHUTDOWN); + + inc_td_cnt(cur_td->urb); + if (last_td_in_urb(cur_td)) + xhci_giveback_urb_in_irq(xhci, cur_td, -ESHUTDOWN); } } @@ -814,7 +808,10 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci, cur_td = list_first_entry(&ep->cancelled_td_list, struct xhci_td, cancelled_td_list); list_del_init(&cur_td->cancelled_td_list); - xhci_giveback_urb_in_irq(xhci, cur_td, -ESHUTDOWN); + + inc_td_cnt(cur_td->urb); + if (last_td_in_urb(cur_td)) + xhci_giveback_urb_in_irq(xhci, cur_td, -ESHUTDOWN); } } @@ -1003,8 +1000,7 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id, break; case COMP_CTX_STATE: xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed due to incorrect slot or ep state.\n"); - ep_state = le32_to_cpu(ep_ctx->ep_info); - ep_state &= EP_STATE_MASK; + ep_state = GET_EP_CTX_STATE(ep_ctx); slot_state = le32_to_cpu(slot_ctx->dev_state); slot_state = GET_SLOT_STATE(slot_state); xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, @@ -1096,12 +1092,12 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id, } static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id, - u32 cmd_comp_code) + struct xhci_command *command, u32 cmd_comp_code) { if (cmd_comp_code == COMP_SUCCESS) - xhci->slot_id = slot_id; + command->slot_id = slot_id; else - xhci->slot_id = 0; + command->slot_id = 0; } static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) @@ -1183,7 +1179,7 @@ static void xhci_handle_cmd_nec_get_fw(struct xhci_hcd *xhci, struct xhci_event_cmd *event) { if (!(xhci->quirks & XHCI_NEC_HOST)) { - xhci->error_bitmask |= 1 << 6; + xhci_warn(xhci, "WARN NEC_GET_FW command on non-NEC host\n"); return; } xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, @@ -1325,14 +1321,13 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, cmd_trb = xhci->cmd_ring->dequeue; cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, cmd_trb); - /* Is the command ring deq ptr out of sync with the deq seg ptr? */ - if (cmd_dequeue_dma == 0) { - xhci->error_bitmask |= 1 << 4; - return; - } - /* Does the DMA address match our internal dequeue pointer address? */ - if (cmd_dma != (u64) cmd_dequeue_dma) { - xhci->error_bitmask |= 1 << 5; + /* + * Check whether the completion event is for our internal kept + * command. + */ + if (!cmd_dequeue_dma || cmd_dma != (u64)cmd_dequeue_dma) { + xhci_warn(xhci, + "ERROR mismatched command completion event\n"); return; } @@ -1371,7 +1366,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, cmd_type = TRB_FIELD_TO_TYPE(le32_to_cpu(cmd_trb->generic.field[3])); switch (cmd_type) { case TRB_ENABLE_SLOT: - xhci_handle_cmd_enable_slot(xhci, slot_id, cmd_comp_code); + xhci_handle_cmd_enable_slot(xhci, slot_id, cmd, cmd_comp_code); break; case TRB_DISABLE_SLOT: xhci_handle_cmd_disable_slot(xhci, slot_id); @@ -1418,7 +1413,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, break; default: /* Skip over unknown commands on the event ring */ - xhci->error_bitmask |= 1 << 6; + xhci_info(xhci, "INFO unknown command type %d\n", cmd_type); break; } @@ -1519,10 +1514,10 @@ static void handle_port_status(struct xhci_hcd *xhci, bool bogus_port_status = false; /* Port status change events always have a successful completion code */ - if (GET_COMP_CODE(le32_to_cpu(event->generic.field[2])) != COMP_SUCCESS) { - xhci_warn(xhci, "WARN: xHC returned failed port status event\n"); - xhci->error_bitmask |= 1 << 8; - } + if (GET_COMP_CODE(le32_to_cpu(event->generic.field[2])) != COMP_SUCCESS) + xhci_warn(xhci, + "WARN: xHC returned failed port status event\n"); + port_id = GET_PORT_ID(le32_to_cpu(event->generic.field[0])); xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id); @@ -1759,7 +1754,7 @@ struct xhci_segment *trb_in_td(struct xhci_hcd *xhci, static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, unsigned int stream_id, - struct xhci_td *td, union xhci_trb *event_trb) + struct xhci_td *td, union xhci_trb *ep_trb) { struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; struct xhci_command *command; @@ -1798,8 +1793,7 @@ static int xhci_requires_manual_halt_cleanup(struct xhci_hcd *xhci, * endpoint anyway. Check if a babble halted the * endpoint. */ - if ((ep_ctx->ep_info & cpu_to_le32(EP_STATE_MASK)) == - cpu_to_le32(EP_STATE_HALTED)) + if (GET_EP_CTX_STATE(ep_ctx) == EP_STATE_HALTED) return 1; return 0; @@ -1824,7 +1818,7 @@ int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code) * Return 1 if the urb can be given back. */ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, - union xhci_trb *event_trb, struct xhci_transfer_event *event, + union xhci_trb *ep_trb, struct xhci_transfer_event *event, struct xhci_virt_ep *ep, int *status, bool skip) { struct xhci_virt_device *xdev; @@ -1833,7 +1827,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, int ep_index; struct urb *urb = NULL; struct xhci_ep_ctx *ep_ctx; - int ret = 0; struct urb_priv *urb_priv; u32 trb_comp_code; @@ -1866,7 +1859,7 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, * The class driver clears the device side halt later. */ xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index, - ep_ring->stream_id, td, event_trb); + ep_ring->stream_id, td, ep_trb); } else { /* Update ring dequeue pointer */ while (ep_ring->dequeue != td->last_trb) @@ -1889,41 +1882,54 @@ td_cleanup: * unsigned). Play it safe and say we didn't transfer anything. */ if (urb->actual_length > urb->transfer_buffer_length) { - xhci_warn(xhci, "URB transfer length is wrong, xHC issue? req. len = %u, act. len = %u\n", - urb->transfer_buffer_length, - urb->actual_length); + xhci_warn(xhci, "URB req %u and actual %u transfer length mismatch\n", + urb->transfer_buffer_length, urb->actual_length); urb->actual_length = 0; - if (td->urb->transfer_flags & URB_SHORT_NOT_OK) - *status = -EREMOTEIO; - else - *status = 0; + *status = 0; } list_del_init(&td->td_list); /* Was this TD slated to be cancelled but completed anyway? */ if (!list_empty(&td->cancelled_td_list)) list_del_init(&td->cancelled_td_list); - urb_priv->td_cnt++; + inc_td_cnt(urb); /* Giveback the urb when all the tds are completed */ - if (urb_priv->td_cnt == urb_priv->length) { - ret = 1; - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs--; - if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) { - if (xhci->quirks & XHCI_AMD_PLL_FIX) - usb_amd_quirk_pll_enable(); - } - } + if (last_td_in_urb(td)) { + if ((urb->actual_length != urb->transfer_buffer_length && + (urb->transfer_flags & URB_SHORT_NOT_OK)) || + (*status != 0 && !usb_endpoint_xfer_isoc(&urb->ep->desc))) + xhci_dbg(xhci, "Giveback URB %p, len = %d, expected = %d, status = %d\n", + urb, urb->actual_length, + urb->transfer_buffer_length, *status); + + /* set isoc urb status to 0 just as EHCI, UHCI, and OHCI */ + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) + *status = 0; + xhci_giveback_urb_in_irq(xhci, td, *status); } + return 0; +} - return ret; +/* sum trb lengths from ring dequeue up to stop_trb, _excluding_ stop_trb */ +static int sum_trb_lengths(struct xhci_hcd *xhci, struct xhci_ring *ring, + union xhci_trb *stop_trb) +{ + u32 sum; + union xhci_trb *trb = ring->dequeue; + struct xhci_segment *seg = ring->deq_seg; + + for (sum = 0; trb != stop_trb; next_trb(xhci, ring, &seg, &trb)) { + if (!trb_is_noop(trb) && !trb_is_link(trb)) + sum += TRB_LEN(le32_to_cpu(trb->generic.field[2])); + } + return sum; } /* * Process control tds, update urb status and actual_length. */ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, - union xhci_trb *event_trb, struct xhci_transfer_event *event, + union xhci_trb *ep_trb, struct xhci_transfer_event *event, struct xhci_virt_ep *ep, int *status) { struct xhci_virt_device *xdev; @@ -1932,6 +1938,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, int ep_index; struct xhci_ep_ctx *ep_ctx; u32 trb_comp_code; + u32 remaining, requested; + bool on_data_stage; slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); xdev = xhci->devs[slot_id]; @@ -1939,195 +1947,161 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); + requested = td->urb->transfer_buffer_length; + remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); + + /* not setup (dequeue), or status stage means we are at data stage */ + on_data_stage = (ep_trb != ep_ring->dequeue && ep_trb != td->last_trb); switch (trb_comp_code) { case COMP_SUCCESS: - if (event_trb == ep_ring->dequeue) { - xhci_warn(xhci, "WARN: Success on ctrl setup TRB " - "without IOC set??\n"); - *status = -ESHUTDOWN; - } else if (event_trb != td->last_trb) { - xhci_warn(xhci, "WARN: Success on ctrl data TRB " - "without IOC set??\n"); + if (ep_trb != td->last_trb) { + xhci_warn(xhci, "WARN: Success on ctrl %s TRB without IOC set?\n", + on_data_stage ? "data" : "setup"); *status = -ESHUTDOWN; - } else { - *status = 0; + break; } + *status = 0; break; case COMP_SHORT_TX: - if (td->urb->transfer_flags & URB_SHORT_NOT_OK) - *status = -EREMOTEIO; - else - *status = 0; + *status = 0; break; case COMP_STOP_SHORT: - if (event_trb == ep_ring->dequeue || event_trb == td->last_trb) - xhci_warn(xhci, "WARN: Stopped Short Packet on ctrl setup or status TRB\n"); + if (on_data_stage) + td->urb->actual_length = remaining; else - td->urb->actual_length = - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); - - return finish_td(xhci, td, event_trb, event, ep, status, false); + xhci_warn(xhci, "WARN: Stopped Short Packet on ctrl setup or status TRB\n"); + goto finish_td; case COMP_STOP: - /* Did we stop at data stage? */ - if (event_trb != ep_ring->dequeue && event_trb != td->last_trb) - td->urb->actual_length = - td->urb->transfer_buffer_length - - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); - /* fall through */ + if (on_data_stage) + td->urb->actual_length = requested - remaining; + goto finish_td; case COMP_STOP_INVAL: - return finish_td(xhci, td, event_trb, event, ep, status, false); + goto finish_td; default: if (!xhci_requires_manual_halt_cleanup(xhci, - ep_ctx, trb_comp_code)) + ep_ctx, trb_comp_code)) break; - xhci_dbg(xhci, "TRB error code %u, " - "halted endpoint index = %u\n", - trb_comp_code, ep_index); + xhci_dbg(xhci, "TRB error %u, halted endpoint index = %u\n", + trb_comp_code, ep_index); /* else fall through */ case COMP_STALL: /* Did we transfer part of the data (middle) phase? */ - if (event_trb != ep_ring->dequeue && - event_trb != td->last_trb) - td->urb->actual_length = - td->urb->transfer_buffer_length - - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); + if (on_data_stage) + td->urb->actual_length = requested - remaining; else if (!td->urb_length_set) td->urb->actual_length = 0; - - return finish_td(xhci, td, event_trb, event, ep, status, false); + goto finish_td; } + + /* stopped at setup stage, no data transferred */ + if (ep_trb == ep_ring->dequeue) + goto finish_td; + /* - * Did we transfer any data, despite the errors that might have - * happened? I.e. did we get past the setup stage? + * if on data stage then update the actual_length of the URB and flag it + * as set, so it won't be overwritten in the event for the last TRB. */ - if (event_trb != ep_ring->dequeue) { - /* The event was for the status stage */ - if (event_trb == td->last_trb) { - if (td->urb_length_set) { - /* Don't overwrite a previously set error code - */ - if ((*status == -EINPROGRESS || *status == 0) && - (td->urb->transfer_flags - & URB_SHORT_NOT_OK)) - /* Did we already see a short data - * stage? */ - *status = -EREMOTEIO; - } else { - td->urb->actual_length = - td->urb->transfer_buffer_length; - } - } else { - /* - * Maybe the event was for the data stage? If so, update - * already the actual_length of the URB and flag it as - * set, so that it is not overwritten in the event for - * the last TRB. - */ - td->urb_length_set = true; - td->urb->actual_length = - td->urb->transfer_buffer_length - - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); - xhci_dbg(xhci, "Waiting for status " - "stage event\n"); - return 0; - } + if (on_data_stage) { + td->urb_length_set = true; + td->urb->actual_length = requested - remaining; + xhci_dbg(xhci, "Waiting for status stage event\n"); + return 0; } - return finish_td(xhci, td, event_trb, event, ep, status, false); + /* at status stage */ + if (!td->urb_length_set) + td->urb->actual_length = requested; + +finish_td: + return finish_td(xhci, td, ep_trb, event, ep, status, false); } /* * Process isochronous tds, update urb packet status and actual_length. */ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, - union xhci_trb *event_trb, struct xhci_transfer_event *event, + union xhci_trb *ep_trb, struct xhci_transfer_event *event, struct xhci_virt_ep *ep, int *status) { struct xhci_ring *ep_ring; struct urb_priv *urb_priv; int idx; - int len = 0; - union xhci_trb *cur_trb; - struct xhci_segment *cur_seg; struct usb_iso_packet_descriptor *frame; u32 trb_comp_code; - bool skip_td = false; + bool sum_trbs_for_length = false; + u32 remaining, requested, ep_trb_len; + int short_framestatus; ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); urb_priv = td->urb->hcpriv; idx = urb_priv->td_cnt; frame = &td->urb->iso_frame_desc[idx]; + requested = frame->length; + remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); + ep_trb_len = TRB_LEN(le32_to_cpu(ep_trb->generic.field[2])); + short_framestatus = td->urb->transfer_flags & URB_SHORT_NOT_OK ? + -EREMOTEIO : 0; /* handle completion code */ switch (trb_comp_code) { case COMP_SUCCESS: - if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) { - frame->status = 0; + if (remaining) { + frame->status = short_framestatus; + if (xhci->quirks & XHCI_TRUST_TX_LENGTH) + sum_trbs_for_length = true; break; } - if ((xhci->quirks & XHCI_TRUST_TX_LENGTH)) - trb_comp_code = COMP_SHORT_TX; - /* fallthrough */ - case COMP_STOP_SHORT: + frame->status = 0; + break; case COMP_SHORT_TX: - frame->status = td->urb->transfer_flags & URB_SHORT_NOT_OK ? - -EREMOTEIO : 0; + frame->status = short_framestatus; + sum_trbs_for_length = true; break; case COMP_BW_OVER: frame->status = -ECOMM; - skip_td = true; break; case COMP_BUFF_OVER: case COMP_BABBLE: frame->status = -EOVERFLOW; - skip_td = true; break; case COMP_DEV_ERR: case COMP_STALL: frame->status = -EPROTO; - skip_td = true; break; case COMP_TX_ERR: frame->status = -EPROTO; - if (event_trb != td->last_trb) + if (ep_trb != td->last_trb) return 0; - skip_td = true; break; case COMP_STOP: + sum_trbs_for_length = true; + break; + case COMP_STOP_SHORT: + /* field normally containing residue now contains tranferred */ + frame->status = short_framestatus; + requested = remaining; + break; case COMP_STOP_INVAL: + requested = 0; + remaining = 0; break; default: + sum_trbs_for_length = true; frame->status = -1; break; } - if (trb_comp_code == COMP_SUCCESS || skip_td) { - frame->actual_length = frame->length; - td->urb->actual_length += frame->length; - } else if (trb_comp_code == COMP_STOP_SHORT) { - frame->actual_length = - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); - td->urb->actual_length += frame->actual_length; - } else { - for (cur_trb = ep_ring->dequeue, - cur_seg = ep_ring->deq_seg; cur_trb != event_trb; - next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) { - if (!TRB_TYPE_NOOP_LE32(cur_trb->generic.field[3]) && - !TRB_TYPE_LINK_LE32(cur_trb->generic.field[3])) - len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])); - } - len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); + if (sum_trbs_for_length) + frame->actual_length = sum_trb_lengths(xhci, ep_ring, ep_trb) + + ep_trb_len - remaining; + else + frame->actual_length = requested; - if (trb_comp_code != COMP_STOP_INVAL) { - frame->actual_length = len; - td->urb->actual_length += len; - } - } + td->urb->actual_length += frame->actual_length; - return finish_td(xhci, td, event_trb, event, ep, status, false); + return finish_td(xhci, td, ep_trb, event, ep, status, false); } static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, @@ -2162,119 +2136,62 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, * Process bulk and interrupt tds, update urb status and actual_length. */ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, - union xhci_trb *event_trb, struct xhci_transfer_event *event, + union xhci_trb *ep_trb, struct xhci_transfer_event *event, struct xhci_virt_ep *ep, int *status) { struct xhci_ring *ep_ring; - union xhci_trb *cur_trb; - struct xhci_segment *cur_seg; u32 trb_comp_code; + u32 remaining, requested, ep_trb_len; ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); + remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); + ep_trb_len = TRB_LEN(le32_to_cpu(ep_trb->generic.field[2])); + requested = td->urb->transfer_buffer_length; switch (trb_comp_code) { case COMP_SUCCESS: - /* Double check that the HW transferred everything. */ - if (event_trb != td->last_trb || - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { - xhci_warn(xhci, "WARN Successful completion " - "on short TX\n"); - if (td->urb->transfer_flags & URB_SHORT_NOT_OK) - *status = -EREMOTEIO; - else - *status = 0; - if ((xhci->quirks & XHCI_TRUST_TX_LENGTH)) - trb_comp_code = COMP_SHORT_TX; - } else { - *status = 0; + /* handle success with untransferred data as short packet */ + if (ep_trb != td->last_trb || remaining) { + xhci_warn(xhci, "WARN Successful completion on short TX\n"); + xhci_dbg(xhci, "ep %#x - asked for %d bytes, %d bytes untransferred\n", + td->urb->ep->desc.bEndpointAddress, + requested, remaining); } + *status = 0; break; - case COMP_STOP_SHORT: case COMP_SHORT_TX: - if (td->urb->transfer_flags & URB_SHORT_NOT_OK) - *status = -EREMOTEIO; - else - *status = 0; + xhci_dbg(xhci, "ep %#x - asked for %d bytes, %d bytes untransferred\n", + td->urb->ep->desc.bEndpointAddress, + requested, remaining); + *status = 0; + break; + case COMP_STOP_SHORT: + td->urb->actual_length = remaining; + goto finish_td; + case COMP_STOP_INVAL: + /* stopped on ep trb with invalid length, exclude it */ + ep_trb_len = 0; + remaining = 0; break; default: - /* Others already handled above */ + /* do nothing */ break; } - if (trb_comp_code == COMP_SHORT_TX) - xhci_dbg(xhci, "ep %#x - asked for %d bytes, " - "%d bytes untransferred\n", - td->urb->ep->desc.bEndpointAddress, - td->urb->transfer_buffer_length, - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); - /* Stopped - short packet completion */ - if (trb_comp_code == COMP_STOP_SHORT) { - td->urb->actual_length = - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); - if (td->urb->transfer_buffer_length < - td->urb->actual_length) { - xhci_warn(xhci, "HC gave bad length of %d bytes txed\n", - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); - td->urb->actual_length = 0; - /* status will be set by usb core for canceled urbs */ - } - /* Fast path - was this the last TRB in the TD for this URB? */ - } else if (event_trb == td->last_trb) { - if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { - td->urb->actual_length = - td->urb->transfer_buffer_length - - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); - if (td->urb->transfer_buffer_length < - td->urb->actual_length) { - xhci_warn(xhci, "HC gave bad length " - "of %d bytes left\n", - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); - td->urb->actual_length = 0; - if (td->urb->transfer_flags & URB_SHORT_NOT_OK) - *status = -EREMOTEIO; - else - *status = 0; - } - /* Don't overwrite a previously set error code */ - if (*status == -EINPROGRESS) { - if (td->urb->transfer_flags & URB_SHORT_NOT_OK) - *status = -EREMOTEIO; - else - *status = 0; - } - } else { - td->urb->actual_length = - td->urb->transfer_buffer_length; - /* Ignore a short packet completion if the - * untransferred length was zero. - */ - if (*status == -EREMOTEIO) - *status = 0; - } - } else { - /* Slow path - walk the list, starting from the dequeue - * pointer, to get the actual length transferred. - */ + if (ep_trb == td->last_trb) + td->urb->actual_length = requested - remaining; + else + td->urb->actual_length = + sum_trb_lengths(xhci, ep_ring, ep_trb) + + ep_trb_len - remaining; +finish_td: + if (remaining > requested) { + xhci_warn(xhci, "bad transfer trb length %d in event trb\n", + remaining); td->urb->actual_length = 0; - for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg; - cur_trb != event_trb; - next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) { - if (!TRB_TYPE_NOOP_LE32(cur_trb->generic.field[3]) && - !TRB_TYPE_LINK_LE32(cur_trb->generic.field[3])) - td->urb->actual_length += - TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])); - } - /* If the ring didn't stop on a Link or No-op TRB, add - * in the actual bytes transferred from the Normal TRB - */ - if (trb_comp_code != COMP_STOP_INVAL) - td->urb->actual_length += - TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); } - - return finish_td(xhci, td, event_trb, event, ep, status, false); + return finish_td(xhci, td, ep_trb, event, ep, status, false); } /* @@ -2293,16 +2210,13 @@ static int handle_tx_event(struct xhci_hcd *xhci, unsigned int slot_id; int ep_index; struct xhci_td *td = NULL; - dma_addr_t event_dma; - struct xhci_segment *event_seg; - union xhci_trb *event_trb; - struct urb *urb = NULL; + dma_addr_t ep_trb_dma; + struct xhci_segment *ep_seg; + union xhci_trb *ep_trb; int status = -EINPROGRESS; - struct urb_priv *urb_priv; struct xhci_ep_ctx *ep_ctx; struct list_head *tmp; u32 trb_comp_code; - int ret = 0; int td_num = 0; bool handling_skipped_tds = false; @@ -2328,9 +2242,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, ep = &xdev->eps[ep_index]; ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); - if (!ep_ring || - (le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == - EP_STATE_DISABLED) { + if (!ep_ring || GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) { xhci_err(xhci, "ERROR Transfer event for disabled endpoint " "or incorrect stream ring\n"); xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n", @@ -2352,7 +2264,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, td_num++; } - event_dma = le64_to_cpu(event->buffer); + ep_trb_dma = le64_to_cpu(event->buffer); trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); /* Look for common error cases */ switch (trb_comp_code) { @@ -2480,7 +2392,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, xhci_dbg(xhci, "td_list is empty while skip " "flag set. Clear skip flag.\n"); } - ret = 0; goto cleanup; } @@ -2489,7 +2400,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, ep->skip = false; xhci_dbg(xhci, "All tds on the ep_ring skipped. " "Clear skip flag.\n"); - ret = 0; goto cleanup; } @@ -2498,8 +2408,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, td_num--; /* Is this a TRB in the currently executing TD? */ - event_seg = trb_in_td(xhci, ep_ring->deq_seg, ep_ring->dequeue, - td->last_trb, event_dma, false); + ep_seg = trb_in_td(xhci, ep_ring->deq_seg, ep_ring->dequeue, + td->last_trb, ep_trb_dma, false); /* * Skip the Force Stopped Event. The event_trb(event_dma) of FSE @@ -2509,13 +2419,12 @@ static int handle_tx_event(struct xhci_hcd *xhci, * last TRB of the previous TD. The command completion handle * will take care the rest. */ - if (!event_seg && (trb_comp_code == COMP_STOP || + if (!ep_seg && (trb_comp_code == COMP_STOP || trb_comp_code == COMP_STOP_INVAL)) { - ret = 0; goto cleanup; } - if (!event_seg) { + if (!ep_seg) { if (!ep->skip || !usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { /* Some host controllers give a spurious @@ -2525,7 +2434,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) && ep_ring->last_td_was_short) { ep_ring->last_td_was_short = false; - ret = 0; goto cleanup; } /* HC is busted, give up! */ @@ -2536,11 +2444,11 @@ static int handle_tx_event(struct xhci_hcd *xhci, trb_comp_code); trb_in_td(xhci, ep_ring->deq_seg, ep_ring->dequeue, td->last_trb, - event_dma, true); + ep_trb_dma, true); return -ESHUTDOWN; } - ret = skip_isoc_td(xhci, td, event, ep, &status); + skip_isoc_td(xhci, td, event, ep, &status); goto cleanup; } if (trb_comp_code == COMP_SHORT_TX) @@ -2553,36 +2461,28 @@ static int handle_tx_event(struct xhci_hcd *xhci, ep->skip = false; } - event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / - sizeof(*event_trb)]; + ep_trb = &ep_seg->trbs[(ep_trb_dma - ep_seg->dma) / + sizeof(*ep_trb)]; /* * No-op TRB should not trigger interrupts. - * If event_trb is a no-op TRB, it means the + * If ep_trb is a no-op TRB, it means the * corresponding TD has been cancelled. Just ignore * the TD. */ - if (TRB_TYPE_NOOP_LE32(event_trb->generic.field[3])) { - xhci_dbg(xhci, - "event_trb is a no-op TRB. Skip it\n"); + if (trb_is_noop(ep_trb)) { + xhci_dbg(xhci, "ep_trb is a no-op TRB. Skip it\n"); goto cleanup; } - /* Now update the urb's actual_length and give back to - * the core - */ + /* update the urb's actual_length and give back to the core */ if (usb_endpoint_xfer_control(&td->urb->ep->desc)) - ret = process_ctrl_td(xhci, td, event_trb, event, ep, - &status); + process_ctrl_td(xhci, td, ep_trb, event, ep, &status); else if (usb_endpoint_xfer_isoc(&td->urb->ep->desc)) - ret = process_isoc_td(xhci, td, event_trb, event, ep, - &status); + process_isoc_td(xhci, td, ep_trb, event, ep, &status); else - ret = process_bulk_intr_td(xhci, td, event_trb, event, - ep, &status); - + process_bulk_intr_td(xhci, td, ep_trb, event, ep, + &status); cleanup: - - handling_skipped_tds = ep->skip && trb_comp_code != COMP_MISSED_INT && trb_comp_code != COMP_PING_ERR; @@ -2594,33 +2494,6 @@ cleanup: if (!handling_skipped_tds) inc_deq(xhci, xhci->event_ring); - if (ret) { - urb = td->urb; - urb_priv = urb->hcpriv; - - xhci_urb_free_priv(urb_priv); - - usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); - if ((urb->actual_length != urb->transfer_buffer_length && - (urb->transfer_flags & - URB_SHORT_NOT_OK)) || - (status != 0 && - !usb_endpoint_xfer_isoc(&urb->ep->desc))) - xhci_dbg(xhci, "Giveback URB %p, len = %d, " - "expected = %d, status = %d\n", - urb, urb->actual_length, - urb->transfer_buffer_length, - status); - spin_unlock(&xhci->lock); - /* EHCI, UHCI, and OHCI always unconditionally set the - * urb->status of an isochronous endpoint to 0. - */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) - status = 0; - usb_hcd_giveback_urb(bus_to_hcd(urb->dev->bus), urb, status); - spin_lock(&xhci->lock); - } - /* * If ep->skip is set, it means there are missed tds on the * endpoint ring need to take care of. @@ -2644,18 +2517,17 @@ static int xhci_handle_event(struct xhci_hcd *xhci) int update_ptrs = 1; int ret; + /* Event ring hasn't been allocated yet. */ if (!xhci->event_ring || !xhci->event_ring->dequeue) { - xhci->error_bitmask |= 1 << 1; - return 0; + xhci_err(xhci, "ERROR event ring not ready\n"); + return -ENOMEM; } event = xhci->event_ring->dequeue; /* Does the HC or OS own the TRB? */ if ((le32_to_cpu(event->event_cmd.flags) & TRB_CYCLE) != - xhci->event_ring->cycle_state) { - xhci->error_bitmask |= 1 << 2; + xhci->event_ring->cycle_state) return 0; - } /* * Barrier between reading the TRB_CYCLE (valid) flag above and any @@ -2663,7 +2535,7 @@ static int xhci_handle_event(struct xhci_hcd *xhci) */ rmb(); /* FIXME: Handle more event types. */ - switch ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK)) { + switch (le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) { case TRB_TYPE(TRB_COMPLETION): handle_cmd_completion(xhci, &event->event_cmd); break; @@ -2673,9 +2545,7 @@ static int xhci_handle_event(struct xhci_hcd *xhci) break; case TRB_TYPE(TRB_TRANSFER): ret = handle_tx_event(xhci, &event->trans_event); - if (ret < 0) - xhci->error_bitmask |= 1 << 9; - else + if (ret >= 0) update_ptrs = 0; break; case TRB_TYPE(TRB_DEV_NOTE): @@ -2686,7 +2556,9 @@ static int xhci_handle_event(struct xhci_hcd *xhci) TRB_TYPE(48)) handle_vendor_event(xhci, event); else - xhci->error_bitmask |= 1 << 3; + xhci_warn(xhci, "ERROR unknown event type %d\n", + TRB_FIELD_TO_TYPE( + le32_to_cpu(event->event_cmd.flags))); } /* Any of the above functions may drop and re-acquire the lock, so check * to make sure a watchdog timer didn't mark the host as non-responsive. @@ -2931,8 +2803,7 @@ static int prepare_transfer(struct xhci_hcd *xhci, return -EINVAL; } - ret = prepare_ring(xhci, ep_ring, - le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK, + ret = prepare_ring(xhci, ep_ring, GET_EP_CTX_STATE(ep_ctx), num_trbs, mem_flags); if (ret) return ret; @@ -3120,7 +2991,7 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred, if (xhci->quirks & XHCI_MTK_HOST) trb_buff_len = 0; - maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); + maxp = usb_endpoint_maxp(&urb->ep->desc); total_packet_count = DIV_ROUND_UP(td_total_len, maxp); /* Queueing functions don't count the current TRB into transferred */ @@ -3136,7 +3007,7 @@ static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len, unsigned int max_pkt; u32 new_buff_len; - max_pkt = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); + max_pkt = usb_endpoint_maxp(&urb->ep->desc); unalign = (enqd_len + *trb_buff_len) % max_pkt; /* we got lucky, last normal TRB data on segment is packet aligned */ @@ -3650,7 +3521,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, addr = start_addr + urb->iso_frame_desc[i].offset; td_len = urb->iso_frame_desc[i].length; td_remain_len = td_len; - max_pkt = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); + max_pkt = usb_endpoint_maxp(&urb->ep->desc); total_pkt_count = DIV_ROUND_UP(td_len, max_pkt); /* A zero-length transfer still involves at least one packet. */ @@ -3828,7 +3699,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, /* Check the ring to guarantee there is enough room for the whole urb. * Do not insert any td of the urb to the ring if the check failed. */ - ret = prepare_ring(xhci, ep_ring, le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK, + ret = prepare_ring(xhci, ep_ring, GET_EP_CTX_STATE(ep_ctx), num_trbs, mem_flags); if (ret) return ret; @@ -3841,8 +3712,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, /* Calculate the start frame and put it in urb->start_frame. */ if (HCC_CFC(xhci->hcc_params) && !list_empty(&ep_ring->td_list)) { - if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == - EP_STATE_RUNNING) { + if (GET_EP_CTX_STATE(ep_ctx) == EP_STATE_RUNNING) { urb->start_frame = xep->next_frame_id; goto skip_start_over; } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1a4ca02729c2..1cd56417cbec 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -113,12 +113,12 @@ int xhci_halt(struct xhci_hcd *xhci) ret = xhci_handshake(&xhci->op_regs->status, STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); - if (!ret) { - xhci->xhc_state |= XHCI_STATE_HALTED; - xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; - } else - xhci_warn(xhci, "Host not halted after %u microseconds.\n", - XHCI_MAX_HALT_USEC); + if (ret) { + xhci_warn(xhci, "Host halt failed, %d\n", ret); + return ret; + } + xhci->xhc_state |= XHCI_STATE_HALTED; + xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; return ret; } @@ -167,6 +167,12 @@ int xhci_reset(struct xhci_hcd *xhci) int ret, i; state = readl(&xhci->op_regs->status); + + if (state == ~(u32)0) { + xhci_warn(xhci, "Host not accessible, reset failed.\n"); + return -ENODEV; + } + if ((state & STS_HALT) == 0) { xhci_warn(xhci, "Host controller not halted, aborting reset.\n"); return 0; @@ -690,7 +696,6 @@ void xhci_stop(struct usb_hcd *hcd) xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; xhci_halt(xhci); xhci_reset(xhci); - spin_unlock_irq(&xhci->lock); } @@ -1645,8 +1650,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, /* If the HC already knows the endpoint is disabled, * or the HCD has noted it is disabled, ignore this request */ - if (((ep_ctx->ep_info & cpu_to_le32(EP_STATE_MASK)) == - cpu_to_le32(EP_STATE_DISABLED)) || + if ((GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) || le32_to_cpu(ctrl_ctx->drop_flags) & xhci_get_endpoint_flag(&ep->desc)) { /* Do not warn when called after a usb_device_reset */ @@ -3209,7 +3213,7 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, for (i = 0; i < num_eps; i++) { ep_index = xhci_get_endpoint_index(&eps[i]->desc); - max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&eps[i]->desc)); + max_packet = usb_endpoint_maxp(&eps[i]->desc); vdev->eps[ep_index].stream_info = xhci_alloc_stream_info(xhci, num_stream_ctxs, num_streams, @@ -3683,27 +3687,26 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) int ret, slot_id; struct xhci_command *command; - command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); + command = xhci_alloc_command(xhci, false, true, GFP_KERNEL); if (!command) return 0; /* xhci->slot_id and xhci->addr_dev are not thread-safe */ mutex_lock(&xhci->mutex); spin_lock_irqsave(&xhci->lock, flags); - command->completion = &xhci->addr_dev; ret = xhci_queue_slot_control(xhci, command, TRB_ENABLE_SLOT, 0); if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); mutex_unlock(&xhci->mutex); xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); - kfree(command); + xhci_free_command(xhci, command); return 0; } xhci_ring_cmd_db(xhci); spin_unlock_irqrestore(&xhci->lock, flags); wait_for_completion(command->completion); - slot_id = xhci->slot_id; + slot_id = command->slot_id; mutex_unlock(&xhci->mutex); if (!slot_id || command->status != COMP_SUCCESS) { @@ -3711,7 +3714,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) xhci_err(xhci, "Max number of devices this xHCI host supports is %u.\n", HCS_MAX_SLOTS( readl(&xhci->cap_regs->hcs_params1))); - kfree(command); + xhci_free_command(xhci, command); return 0; } @@ -3747,7 +3750,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) #endif - kfree(command); + xhci_free_command(xhci, command); /* Is this a LS or FS device under a HS hub? */ /* Hub or peripherial? */ return 1; @@ -3755,6 +3758,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) disable_slot: /* Disable slot, if we can do it without mem alloc */ spin_lock_irqsave(&xhci->lock, flags); + kfree(command->completion); command->completion = NULL; command->status = 0; if (!xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT, @@ -3816,14 +3820,13 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, } } - command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); + command = xhci_alloc_command(xhci, false, true, GFP_KERNEL); if (!command) { ret = -ENOMEM; goto out; } command->in_ctx = virt_dev->in_ctx; - command->completion = &xhci->addr_dev; slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx); @@ -3941,7 +3944,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK); out: mutex_unlock(&xhci->mutex); - kfree(command); + if (command) { + kfree(command->completion); + kfree(command); + } return ret; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f945380035d0..8ccc11a974b8 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -709,6 +709,8 @@ struct xhci_ep_ctx { #define EP_STATE_HALTED 2 #define EP_STATE_STOPPED 3 #define EP_STATE_ERROR 4 +#define GET_EP_CTX_STATE(ctx) (le32_to_cpu((ctx)->ep_info) & EP_STATE_MASK) + /* Mult - Max number of burtst within an interval, in EP companion desc. */ #define EP_MULT(p) (((p) & 0x3) << 8) #define CTX_TO_EP_MULT(p) (((p) >> 8) & 0x3) @@ -747,11 +749,6 @@ struct xhci_ep_ctx { #define MAX_PACKET_MASK (0xffff << 16) #define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff) -/* Get max packet size from ep desc. Bit 10..0 specify the max packet size. - * USB2.0 spec 9.6.6. - */ -#define GET_MAX_PACKET(p) ((p) & 0x7ff) - /* tx_info bitmasks */ #define EP_AVG_TRB_LENGTH(p) ((p) & 0xffff) #define EP_MAX_ESIT_PAYLOAD_LO(p) (((p) & 0xffff) << 16) @@ -789,6 +786,7 @@ struct xhci_command { /* Input context for changing device state */ struct xhci_container_ctx *in_ctx; u32 status; + int slot_id; /* If completion is null, no one is waiting on this command * and the structure can be freed after the command completes. */ @@ -997,7 +995,6 @@ struct xhci_virt_device { int num_rings_cached; #define XHCI_MAX_RINGS_CACHED 31 struct xhci_virt_ep eps[31]; - struct completion cmd_completion; u8 fake_port; u8 real_port; struct xhci_interval_bw_table *bw_table; @@ -1583,8 +1580,6 @@ struct xhci_hcd { /* slot enabling and address device helpers */ /* these are not thread safe so use mutex */ struct mutex mutex; - struct completion addr_dev; - int slot_id; /* For USB 3.0 LPM enable/disable. */ struct xhci_command *lpm_command; /* Internal mirror of the HW's dcbaa */ @@ -1618,8 +1613,6 @@ struct xhci_hcd { #define XHCI_STATE_DYING (1 << 0) #define XHCI_STATE_HALTED (1 << 1) #define XHCI_STATE_REMOVING (1 << 2) - /* Statistics */ - int error_bitmask; unsigned int quirks; #define XHCI_LINK_TRB_QUIRK (1 << 0) #define XHCI_RESET_EP_QUIRK (1 << 1) |