diff options
Diffstat (limited to 'drivers/usb/host')
39 files changed, 625 insertions, 456 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 1cb3004ea7b2..ab12c4bf0ef1 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -44,10 +44,10 @@ config USB_XHCI_PCI default y config USB_XHCI_PCI_RENESAS - tristate "Support for additional Renesas xHCI controller with firwmare" + tristate "Support for additional Renesas xHCI controller with firmware" help Say 'Y' to enable the support for the Renesas xHCI controller with - firwmare. Make sure you have the firwmare for the device and + firmware. Make sure you have the firwmare for the device and installed on your system for this device to work. If unsure, say 'N'. diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index 652fa29beb27..b1b777f33521 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c @@ -168,7 +168,7 @@ static void bcma_hcd_init_chip_mips(struct bcma_device *dev) } } -/** +/* * bcma_hcd_usb20_old_arm_init - Initialize old USB 2.0 controller on ARM * * Old USB 2.0 core is identified as BCMA_CORE_USB20_HOST and was introduced @@ -261,7 +261,7 @@ static void bcma_hcd_usb20_ns_init_hc(struct bcma_device *dev) usleep_range(1000, 2000); } -/** +/* * bcma_hcd_usb20_ns_init - Initialize Northstar USB 2.0 controller */ static int bcma_hcd_usb20_ns_init(struct bcma_hcd_device *bcma_hcd) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 7619cfb06883..0b7f1edd9eec 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -823,7 +823,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) break; case 0: /* illegal reserved capability */ cap = 0; - /* FALLTHROUGH */ + fallthrough; default: /* unknown */ break; } diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 9e9c232e896f..1e8b59ab2272 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -234,7 +234,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, break; case FSL_USB2_PHY_UTMI_WIDE: portsc |= PORT_PTS_PTW; - /* fall through */ + fallthrough; case FSL_USB2_PHY_UTMI: /* Presence of this node "has_fsl_erratum_a006918" * in device-tree is used to stop USB controller @@ -244,7 +244,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, dev_warn(dev, "USB PHY clock invalid\n"); return -EINVAL; } - /* fall through */ + fallthrough; case FSL_USB2_PHY_UTMI_DUAL: /* PHY_CLK_VALID bit is de-featured from all controller * versions below 2.4 and is to be checked only for @@ -683,7 +683,7 @@ static const struct ehci_driver_overrides ehci_fsl_overrides __initconst = { /** * fsl_ehci_drv_remove - shutdown processing for FSL-based HCDs - * @dev: USB Host Controller being removed + * @pdev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of usb_hcd_fsl_probe(). diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index cf2b7ae93b7e..6257be4110ca 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -982,7 +982,7 @@ rescan: start_unlink_async(ehci, qh); else start_unlink_intr(ehci, qh); - /* FALL THROUGH */ + fallthrough; case QH_STATE_COMPLETING: /* already in unlinking */ case QH_STATE_UNLINK: /* wait for hw to finish? */ case QH_STATE_UNLINK_WAIT: @@ -999,7 +999,7 @@ idle_timeout: qh_destroy(ehci, qh); break; } - /* fall through */ + fallthrough; default: /* caller was supposed to have unlinked any requests; * that's not our job. just leak this memory. diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index fc125b3d06e7..8771a2ed6926 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -24,7 +24,6 @@ #include <linux/slab.h> #include <linux/usb/ulpi.h> #include <linux/pm_runtime.h> -#include <linux/gpio.h> #include <linux/clk.h> #include <linux/usb.h> #include <linux/usb/hcd.h> @@ -78,6 +77,7 @@ static const struct ehci_driver_overrides ehci_omap_overrides __initconst = { /** * ehci_hcd_omap_probe - initialize TI-based HCDs + * @pdev: Pointer to this platform device's information * * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index af3c1b9b38b2..71ec3025686f 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -124,8 +124,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) case 0x005b: /* CK804 */ case 0x00d8: /* CK8 */ case 0x00e8: /* CK8S */ - if (pci_set_consistent_dma_mask(pdev, - DMA_BIT_MASK(31)) < 0) + if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(31)) < 0) ehci_warn(ehci, "can't enable NVidia " "workaround for >2GB RAM\n"); break; diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index e9a49007cce4..006c4f6188a5 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -475,11 +475,13 @@ static const struct of_device_id vt8500_ehci_ids[] = { }; MODULE_DEVICE_TABLE(of, vt8500_ehci_ids); +#ifdef CONFIG_ACPI static const struct acpi_device_id ehci_acpi_match[] = { { "PNP0D20", 0 }, /* EHCI controller without debug */ { } }; MODULE_DEVICE_TABLE(acpi, ehci_acpi_match); +#endif static const struct platform_device_id ehci_platform_table[] = { { "ehci-platform", 0 }, diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 8a5c9b3ebe1e..a826715ae9bd 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -874,7 +874,7 @@ qh_make ( switch (urb->dev->speed) { case USB_SPEED_LOW: info1 |= QH_LOW_SPEED; - /* FALL THROUGH */ + fallthrough; case USB_SPEED_FULL: /* EPS 0 means "full" */ diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index da7b00a6110b..847979f265b1 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -2475,7 +2475,7 @@ restart: ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n", type, frame, q.ptr); /* BUG(); */ - /* FALL THROUGH */ + fallthrough; case Q_TYPE_QH: case Q_TYPE_FSTN: /* End of the iTDs and siTDs */ diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c index 3235d5307403..63c646c8f7d6 100644 --- a/drivers/usb/host/fhci-sched.c +++ b/drivers/usb/host/fhci-sched.c @@ -701,7 +701,6 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) u32 data_len = urb->transfer_buffer_length; int urb_state = 0; int toggle = 0; - struct td *td; u8 *data; u16 cnt = 0; @@ -770,7 +769,7 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) usb_endpoint_maxp(&urb->ep->desc)) == 0)) urb_state = US_BULK0; while (data_len > 4096) { - td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, + fhci_td_fill(fhci, urb, urb_priv, ed, cnt, usb_pipeout(urb->pipe) ? FHCI_TA_OUT : FHCI_TA_IN, cnt ? USB_TD_TOGGLE_CARRY : @@ -781,7 +780,7 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) cnt++; } - td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, + fhci_td_fill(fhci, urb, urb_priv, ed, cnt, usb_pipeout(urb->pipe) ? FHCI_TA_OUT : FHCI_TA_IN, cnt ? USB_TD_TOGGLE_CARRY : toggle, data, data_len, 0, 0, true); @@ -789,7 +788,7 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) if (urb->transfer_flags & URB_ZERO_PACKET && cnt < urb_priv->num_of_tds) { - td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, + fhci_td_fill(fhci, urb, urb_priv, ed, cnt, usb_pipeout(urb->pipe) ? FHCI_TA_OUT : FHCI_TA_IN, USB_TD_TOGGLE_CARRY, NULL, 0, 0, 0, true); @@ -798,7 +797,7 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) break; case FHCI_TF_INTR: urb->start_frame = get_frame_num(fhci) + 1; - td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, + fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, usb_pipeout(urb->pipe) ? FHCI_TA_OUT : FHCI_TA_IN, USB_TD_TOGGLE_DATA0, data, data_len, urb->interval, urb->start_frame, true); @@ -808,12 +807,12 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) ed->max_pkt_size = usb_endpoint_maxp(&urb->ep->desc); /* setup stage */ - td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, FHCI_TA_SETUP, + fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, FHCI_TA_SETUP, USB_TD_TOGGLE_DATA0, urb->setup_packet, 8, 0, 0, true); /* data stage */ if (data_len > 0) { - td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, + fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, usb_pipeout(urb->pipe) ? FHCI_TA_OUT : FHCI_TA_IN, USB_TD_TOGGLE_DATA1, data, data_len, 0, 0, @@ -822,12 +821,12 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) /* status stage */ if (data_len > 0) - td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, + fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, (usb_pipeout(urb->pipe) ? FHCI_TA_IN : FHCI_TA_OUT), USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true); else - td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, + fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, FHCI_TA_IN, USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true); @@ -844,7 +843,7 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) */ frame += cnt * urb->interval; frame &= 0x07ff; - td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, + fhci_td_fill(fhci, urb, urb_priv, ed, cnt, usb_pipeout(urb->pipe) ? FHCI_TA_OUT : FHCI_TA_IN, USB_TD_TOGGLE_DATA0, diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c index f3308ce25043..d98fd9e1af0b 100644 --- a/drivers/usb/host/fhci-tds.c +++ b/drivers/usb/host/fhci-tds.c @@ -467,17 +467,15 @@ u32 fhci_host_transaction(struct fhci_usb *usb, /* Reset the Tx BD ring */ void fhci_flush_bds(struct fhci_usb *usb) { - u16 extra_data; u16 td_status; - u32 buf; struct usb_td __iomem *td; struct endpoint *ep = usb->ep0; td = ep->td_base; while (1) { td_status = in_be16(&td->status); - buf = in_be32(&td->buf_ptr); - extra_data = in_be16(&td->extra); + in_be32(&td->buf_ptr); + in_be16(&td->extra); /* if the TD is not empty - we'll confirm it as Timeout */ if (td_status & TD_R) @@ -524,7 +522,6 @@ void fhci_flush_actual_frame(struct fhci_usb *usb) { u8 mode; u16 tb_ptr; - u16 extra_data; u16 td_status; u32 buf_ptr; struct usb_td __iomem *td; @@ -538,7 +535,7 @@ void fhci_flush_actual_frame(struct fhci_usb *usb) td = cpm_muram_addr(tb_ptr); td_status = in_be16(&td->status); buf_ptr = in_be32(&td->buf_ptr); - extra_data = in_be16(&td->extra); + in_be16(&td->extra); do { if (td_status & TD_R) { out_be16(&td->status, (td_status & ~TD_R) | TD_TO); @@ -552,7 +549,7 @@ void fhci_flush_actual_frame(struct fhci_usb *usb) td = next_bd(ep->td_base, td, td_status); td_status = in_be16(&td->status); buf_ptr = in_be32(&td->buf_ptr); - extra_data = in_be16(&td->extra); + in_be16(&td->extra); } while ((td_status & TD_R) || buf_ptr); fhci_td_transaction_confirm(usb); diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index f967adf2d8df..194df8282471 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -2807,7 +2807,7 @@ static struct fotg210_qh *qh_make(struct fotg210_hcd *fotg210, struct urb *urb, switch (urb->dev->speed) { case USB_SPEED_LOW: info1 |= QH_LOW_SPEED; - /* FALL THROUGH */ + fallthrough; case USB_SPEED_FULL: /* EPS 0 means "full" */ @@ -4634,7 +4634,7 @@ static inline int scan_frame_queue(struct fotg210_hcd *fotg210, unsigned frame, default: fotg210_dbg(fotg210, "corrupt type %d frame %d shadow %p\n", type, frame, q.ptr); - /* FALL THROUGH */ + fallthrough; case Q_TYPE_QH: case Q_TYPE_FSTN: /* End of the iTDs and siTDs */ @@ -5010,7 +5010,6 @@ static int fotg210_run(struct usb_hcd *hcd) { struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); u32 temp; - u32 hcc_params; hcd->uses_new_polling = 1; @@ -5033,7 +5032,7 @@ static int fotg210_run(struct usb_hcd *hcd) * Scsi_Host.highmem_io, and so forth. It's readonly to all * host side drivers though. */ - hcc_params = fotg210_readl(fotg210, &fotg210->caps->hcc_params); + fotg210_readl(fotg210, &fotg210->caps->hcc_params); /* * Philips, Intel, and maybe others need CMD_RUN before the @@ -5412,7 +5411,7 @@ rescan: */ if (tmp) start_unlink_async(fotg210, qh); - /* FALL THROUGH */ + fallthrough; case QH_STATE_UNLINK: /* wait for hw to finish? */ case QH_STATE_UNLINK_WAIT: idle_timeout: @@ -5426,7 +5425,7 @@ idle_timeout: qh_destroy(fotg210, qh); break; } - /* fall through */ + fallthrough; default: /* caller was supposed to have unlinked any requests; * that's not our job. just leak this memory. @@ -5558,7 +5557,7 @@ static void fotg210_init(struct fotg210_hcd *fotg210) iowrite32(value, &fotg210->regs->otgcsr); } -/** +/* * fotg210_hcd_probe - initialize faraday FOTG210 HCDs * * Allocates basic resources for this USB host controller, and @@ -5657,7 +5656,7 @@ fail_create_hcd: return retval; } -/** +/* * fotg210_hcd_remove - shutdown processing for EHCI HCDs * @dev: USB Host Controller being removed * diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index 5835f9966204..b2716cb72471 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -224,7 +224,7 @@ static void setup_etd_dword0(struct imx21 *imx21, ((u32) maxpacket << DW0_MAXPKTSIZ)); } -/** +/* * Copy buffer to data controller data memory. * We cannot use memcpy_toio() because the hardware requires 32bit writes */ diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 4a3a2852523f..2cecb36d241b 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -1748,7 +1748,7 @@ static int isp1362_bus_suspend(struct usb_hcd *hcd) isp1362_hcd->hc_control &= ~OHCI_CTRL_HCFS; isp1362_hcd->hc_control |= OHCI_USB_RESET; isp1362_write_reg32(isp1362_hcd, HCCONTROL, isp1362_hcd->hc_control); - /* FALL THROUGH */ + fallthrough; case OHCI_USB_RESET: status = -EBUSY; pr_warn("%s: needs reinit!\n", __func__); diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index 4c49688a069d..9bbfcc3fdd3c 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h @@ -56,7 +56,7 @@ typedef const unsigned char isp1362_reg_t; #define ISP1362_REG_NO(r) (r) #define ISP1362_REG(name, addr, width, rw) \ -static isp1362_reg_t ISP1362_REG_##name = addr +static isp1362_reg_t __maybe_unused ISP1362_REG_##name = addr #define REG_ACCESS_TEST(r) do {} while (0) #define REG_WIDTH_TEST(r, w) do {} while (0) diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index 8819f502b6a6..0894f6caccb2 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -11,9 +11,9 @@ * * Based on: * o MAX3421E datasheet - * http://datasheets.maximintegrated.com/en/ds/MAX3421E.pdf + * https://datasheets.maximintegrated.com/en/ds/MAX3421E.pdf * o MAX3421E Programming Guide - * http://www.hdl.co.jp/ftpdata/utl-001/AN3785.pdf + * https://www.hdl.co.jp/ftpdata/utl-001/AN3785.pdf * o gadget/dummy_hcd.c * For USB HCD implementation. * o Arduino MAX3421 driver @@ -317,7 +317,7 @@ static const int hrsl_to_error[] = { }; /* - * See http://www.beyondlogic.org/usbnutshell/usb4.shtml#Control for a + * See https://www.beyondlogic.org/usbnutshell/usb4.shtml#Control for a * reasonable overview of how control transfers use the the IN/OUT * tokens. */ @@ -925,7 +925,7 @@ max3421_handle_error(struct usb_hcd *hcd, u8 hrsl) spi_wr8(hcd, MAX3421_REG_HCTL, BIT(sndtog + MAX3421_HCTL_SNDTOG0_BIT)); } - /* FALL THROUGH */ + fallthrough; case MAX3421_HRSL_BADBC: /* bad byte count */ case MAX3421_HRSL_PIDERR: /* received PID is corrupted */ case MAX3421_HRSL_PKTERR: /* packet error (stuff, EOP) */ @@ -1715,7 +1715,7 @@ max3421_hub_control(struct usb_hcd *hcd, u16 type_req, u16 value, u16 index, dev_dbg(hcd->self.controller, "power-off\n"); max3421_gpout_set_value(hcd, pdata->vbus_gpout, !pdata->vbus_active_level); - /* FALLS THROUGH */ + fallthrough; default: max3421_hcd->port_status &= ~(1 << value); } @@ -1768,7 +1768,7 @@ max3421_hub_control(struct usb_hcd *hcd, u16 type_req, u16 value, u16 index, break; case USB_PORT_FEAT_RESET: max3421_reset_port(hcd); - /* FALLS THROUGH */ + fallthrough; default: if ((max3421_hcd->port_status & USB_PORT_STAT_POWER) != 0) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index b635c6a1b1a9..0487a4b0501e 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -153,7 +153,7 @@ static struct regmap *at91_dt_syscon_sfr(void) /* always called with process context; sleeping is OK */ -/** +/* * usb_hcd_at91_probe - initialize AT91-based HCDs * Context: !in_interrupt() * @@ -244,9 +244,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, /* may be called with controller, bus, and devices active */ -/** +/* * usb_hcd_at91_remove - shutdown processing for AT91-based HCDs - * @dev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of usb_hcd_at91_probe(), first invoking diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 4de91653a2c7..dd37e77dae00 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -16,7 +16,7 @@ * OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller * interfaces (though some non-x86 Intel chips use it). It supports * smarter hardware than UHCI. A download link for the spec available - * through the http://www.usb.org website. + * through the https://www.usb.org website. * * This file is licenced under the GPL. */ @@ -385,7 +385,7 @@ sanitize: ed_free (ohci, ed); break; } - /* fall through */ + fallthrough; default: /* caller was supposed to have unlinked any requests; * that's not our job. can't recover; must leak ed. @@ -1051,7 +1051,7 @@ int ohci_restart(struct ohci_hcd *ohci) ed->ed_next = ohci->ed_rm_list; ed->ed_prev = NULL; ohci->ed_rm_list = ed; - /* FALLTHROUGH */ + fallthrough; case ED_UNLINK: break; default: diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 634f3c7bf774..44504c1751e0 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -58,7 +58,7 @@ __acquires(ohci->lock) ohci->hc_control |= OHCI_USB_RESET; ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control); - /* FALL THROUGH */ + fallthrough; case OHCI_USB_RESET: status = -EBUSY; ohci_dbg (ohci, "needs reinit!\n"); diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index d8d35d456456..9ccdf2c216b5 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -18,7 +18,7 @@ #include <linux/clk.h> #include <linux/dma-mapping.h> #include <linux/err.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/io.h> #include <linux/jiffies.h> #include <linux/kernel.h> @@ -53,38 +53,29 @@ #define DRIVER_DESC "OHCI OMAP driver" -#ifdef CONFIG_TPS65010 -#include <linux/mfd/tps65010.h> -#else - -#define LOW 0 -#define HIGH 1 - -#define GPIO1 1 - -static inline int tps65010_set_gpio_out_value(unsigned gpio, unsigned value) -{ - return 0; -} - -#endif - -static struct clk *usb_host_ck; -static struct clk *usb_dc_ck; +struct ohci_omap_priv { + struct clk *usb_host_ck; + struct clk *usb_dc_ck; + struct gpio_desc *power; + struct gpio_desc *overcurrent; +}; static const char hcd_name[] = "ohci-omap"; static struct hc_driver __read_mostly ohci_omap_hc_driver; -static void omap_ohci_clock_power(int on) +#define hcd_to_ohci_omap_priv(h) \ + ((struct ohci_omap_priv *)hcd_to_ohci(h)->priv) + +static void omap_ohci_clock_power(struct ohci_omap_priv *priv, int on) { if (on) { - clk_enable(usb_dc_ck); - clk_enable(usb_host_ck); + clk_enable(priv->usb_dc_ck); + clk_enable(priv->usb_host_ck); /* guesstimate for T5 == 1x 32K clock + APLL lock time */ udelay(100); } else { - clk_disable(usb_host_ck); - clk_disable(usb_dc_ck); + clk_disable(priv->usb_host_ck); + clk_disable(priv->usb_dc_ck); } } @@ -92,22 +83,22 @@ static void omap_ohci_clock_power(int on) * Board specific gang-switched transceiver power on/off. * NOTE: OSK supplies power from DC, not battery. */ -static int omap_ohci_transceiver_power(int on) +static int omap_ohci_transceiver_power(struct ohci_omap_priv *priv, int on) { if (on) { if (machine_is_omap_innovator() && cpu_is_omap1510()) __raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL) | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), INNOVATOR_FPGA_CAM_USB_CONTROL); - else if (machine_is_omap_osk()) - tps65010_set_gpio_out_value(GPIO1, LOW); + else if (priv->power) + gpiod_set_value(priv->power, 0); } else { if (machine_is_omap_innovator() && cpu_is_omap1510()) __raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL) & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), INNOVATOR_FPGA_CAM_USB_CONTROL); - else if (machine_is_omap_osk()) - tps65010_set_gpio_out_value(GPIO1, HIGH); + else if (priv->power) + gpiod_set_value(priv->power, 1); } return 0; @@ -196,6 +187,7 @@ static int ohci_omap_reset(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct omap_usb_config *config = dev_get_platdata(hcd->self.controller); + struct ohci_omap_priv *priv = hcd_to_ohci_omap_priv(hcd); int need_transceiver = (config->otg != 0); int ret; @@ -235,7 +227,7 @@ static int ohci_omap_reset(struct usb_hcd *hcd) } #endif - omap_ohci_clock_power(1); + omap_ohci_clock_power(priv, 1); if (cpu_is_omap15xx()) { omap_1510_local_bus_power(1); @@ -266,8 +258,6 @@ static int ohci_omap_reset(struct usb_hcd *hcd) /* gpio9 for overcurrent detction */ omap_cfg_reg(W8_1610_GPIO9); - gpio_request(9, "OHCI overcurrent"); - gpio_direction_input(9); /* for paranoia's sake: disable USB.PUEN */ omap_cfg_reg(W4_USB_HIGHZ); @@ -281,7 +271,7 @@ static int ohci_omap_reset(struct usb_hcd *hcd) } /* FIXME hub_wq hub requests should manage power switching */ - omap_ohci_transceiver_power(1); + omap_ohci_transceiver_power(priv, 1); /* board init will have already handled HMC and mux setup. * any external transceiver should already be initialized @@ -305,6 +295,7 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev) { int retval, irq; struct usb_hcd *hcd = 0; + struct ohci_omap_priv *priv; if (pdev->num_resources != 2) { dev_err(&pdev->dev, "invalid num_resources: %i\n", @@ -318,34 +309,58 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev) return -ENODEV; } - usb_host_ck = clk_get(&pdev->dev, "usb_hhc_ck"); - if (IS_ERR(usb_host_ck)) - return PTR_ERR(usb_host_ck); + hcd = usb_create_hcd(&ohci_omap_hc_driver, &pdev->dev, + dev_name(&pdev->dev)); + if (!hcd) + return -ENOMEM; - if (!cpu_is_omap15xx()) - usb_dc_ck = clk_get(&pdev->dev, "usb_dc_ck"); - else - usb_dc_ck = clk_get(&pdev->dev, "lb_ck"); + hcd->rsrc_start = pdev->resource[0].start; + hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; + priv = hcd_to_ohci_omap_priv(hcd); - if (IS_ERR(usb_dc_ck)) { - clk_put(usb_host_ck); - return PTR_ERR(usb_dc_ck); + /* Obtain two optional GPIO lines */ + priv->power = devm_gpiod_get_optional(&pdev->dev, "power", GPIOD_ASIS); + if (IS_ERR(priv->power)) { + retval = PTR_ERR(priv->power); + goto err_put_hcd; } + if (priv->power) + gpiod_set_consumer_name(priv->power, "OHCI power"); + /* + * This "overcurrent" GPIO line isn't really used in the code, + * but has a designated hardware function. + * TODO: implement proper overcurrent handling. + */ + priv->overcurrent = devm_gpiod_get_optional(&pdev->dev, "overcurrent", + GPIOD_IN); + if (IS_ERR(priv->overcurrent)) { + retval = PTR_ERR(priv->overcurrent); + goto err_put_hcd; + } + if (priv->overcurrent) + gpiod_set_consumer_name(priv->overcurrent, "OHCI overcurrent"); - hcd = usb_create_hcd(&ohci_omap_hc_driver, &pdev->dev, - dev_name(&pdev->dev)); - if (!hcd) { - retval = -ENOMEM; - goto err0; + priv->usb_host_ck = clk_get(&pdev->dev, "usb_hhc_ck"); + if (IS_ERR(priv->usb_host_ck)) { + retval = PTR_ERR(priv->usb_host_ck); + goto err_put_hcd; + } + + if (!cpu_is_omap15xx()) + priv->usb_dc_ck = clk_get(&pdev->dev, "usb_dc_ck"); + else + priv->usb_dc_ck = clk_get(&pdev->dev, "lb_ck"); + + if (IS_ERR(priv->usb_dc_ck)) { + retval = PTR_ERR(priv->usb_dc_ck); + goto err_put_host_ck; } - hcd->rsrc_start = pdev->resource[0].start; - hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { dev_dbg(&pdev->dev, "request_mem_region failed\n"); retval = -EBUSY; - goto err1; + goto err_put_dc_ck; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); @@ -370,11 +385,12 @@ err3: iounmap(hcd->regs); err2: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err1: +err_put_dc_ck: + clk_put(priv->usb_dc_ck); +err_put_host_ck: + clk_put(priv->usb_host_ck); +err_put_hcd: usb_put_hcd(hcd); -err0: - clk_put(usb_dc_ck); - clk_put(usb_host_ck); return retval; } @@ -393,21 +409,20 @@ err0: static int ohci_hcd_omap_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ohci_omap_priv *priv = hcd_to_ohci_omap_priv(hcd); dev_dbg(hcd->self.controller, "stopping USB Controller\n"); usb_remove_hcd(hcd); - omap_ohci_clock_power(0); + omap_ohci_clock_power(priv, 0); if (!IS_ERR_OR_NULL(hcd->usb_phy)) { (void) otg_set_host(hcd->usb_phy->otg, 0); usb_put_phy(hcd->usb_phy); } - if (machine_is_omap_osk()) - gpio_free(9); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + clk_put(priv->usb_dc_ck); + clk_put(priv->usb_host_ck); usb_put_hcd(hcd); - clk_put(usb_dc_ck); - clk_put(usb_host_ck); return 0; } @@ -419,6 +434,7 @@ static int ohci_omap_suspend(struct platform_device *pdev, pm_message_t message) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); + struct ohci_omap_priv *priv = hcd_to_ohci_omap_priv(hcd); bool do_wakeup = device_may_wakeup(&pdev->dev); int ret; @@ -430,7 +446,7 @@ static int ohci_omap_suspend(struct platform_device *pdev, pm_message_t message) if (ret) return ret; - omap_ohci_clock_power(0); + omap_ohci_clock_power(priv, 0); return ret; } @@ -438,12 +454,13 @@ static int ohci_omap_resume(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); + struct ohci_omap_priv *priv = hcd_to_ohci_omap_priv(hcd); if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; - omap_ohci_clock_power(1); + omap_ohci_clock_power(priv, 1); ohci_resume(hcd, false); return 0; } @@ -470,7 +487,8 @@ static struct platform_driver ohci_hcd_omap_driver = { static const struct ohci_driver_overrides omap_overrides __initconst = { .product_desc = "OMAP OHCI", - .reset = ohci_omap_reset + .reset = ohci_omap_reset, + .extra_priv_size = sizeof(struct ohci_omap_priv), }; static int __init ohci_omap_init(void) diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 585222af24ff..41efe927d8f3 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -232,10 +232,6 @@ static const struct pci_device_id ohci_pci_quirks[] = { .driver_data = (unsigned long)ohci_quirk_qemu, }, - /* FIXME for some of the early AMD 760 southbridges, OHCI - * won't work at all. blacklist them. - */ - {}, }; diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 4ccb85a67bb3..3b445312beea 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -647,7 +647,7 @@ static void td_submit_urb ( /* ... and periodic urbs have extra accounting */ periodic = ohci_to_hcd(ohci)->self.bandwidth_int_reqs++ == 0 && ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0; - /* FALLTHROUGH */ + fallthrough; case PIPE_BULK: info = is_out ? TD_T_TOGGLE | TD_CC | TD_DP_OUT @@ -879,11 +879,11 @@ static void ed_halted(struct ohci_hcd *ohci, struct td *td, int cc) case TD_DATAUNDERRUN: if ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0) break; - /* fallthrough */ + fallthrough; case TD_CC_STALL: if (usb_pipecontrol (urb->pipe)) break; - /* fallthrough */ + fallthrough; default: ohci_dbg (ohci, "urb %p path %s ep%d%s %08x cc %d --> status %d\n", diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index d961097c90f0..de5e570c58ba 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -343,7 +343,7 @@ ohci_hcd_s3c2410_remove(struct platform_device *dev) return 0; } -/** +/* * ohci_hcd_s3c2410_probe - initialize S3C2410-based HCDs * Context: !in_interrupt() * diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index fb6f5e9ae5c6..7f857bad9e95 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -97,13 +97,13 @@ static void tmio_stop_hc(struct platform_device *dev) switch (ohci->num_ports) { default: dev_err(&dev->dev, "Unsupported amount of ports: %d\n", ohci->num_ports); - /* fall through */ + fallthrough; case 3: pm |= CCR_PM_USBPW3; - /* fall through */ + fallthrough; case 2: pm |= CCR_PM_USBPW2; - /* fall through */ + fallthrough; case 1: pm |= CCR_PM_USBPW1; } diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index b85a39588f9d..aac6285b37f8 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -162,7 +162,7 @@ struct td { /* map OHCI TD status codes (CC) to errno values */ -static const int cc_to_error [16] = { +static const int __maybe_unused cc_to_error [16] = { /* No Error */ 0, /* CRC Error */ -EILSEQ, /* Bit Stuff */ -EPROTO, diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 120666a0d590..cfa7dd2cc7d3 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -1858,7 +1858,7 @@ static struct ehci_qh *qh_make(struct oxu_hcd *oxu, switch (urb->dev->speed) { case USB_SPEED_LOW: info1 |= (1 << 12); /* EPS "low" */ - /* FALL THROUGH */ + fallthrough; case USB_SPEED_FULL: /* EPS 0 means "full" */ @@ -2037,16 +2037,15 @@ static struct ehci_qh *qh_append_tds(struct oxu_hcd *oxu, static int submit_async(struct oxu_hcd *oxu, struct urb *urb, struct list_head *qtd_list, gfp_t mem_flags) { - struct ehci_qtd *qtd; - int epnum; + int epnum = urb->ep->desc.bEndpointAddress; unsigned long flags; struct ehci_qh *qh = NULL; int rc = 0; +#ifdef OXU_URB_TRACE + struct ehci_qtd *qtd; qtd = list_entry(qtd_list->next, struct ehci_qtd, qtd_list); - epnum = urb->ep->desc.bEndpointAddress; -#ifdef OXU_URB_TRACE oxu_dbg(oxu, "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n", __func__, urb->dev->devpath, urb, epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", @@ -3378,7 +3377,7 @@ static int oxu_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) switch (qh->qh_state) { case QH_STATE_LINKED: intr_deschedule(oxu, qh); - /* FALL THROUGH */ + fallthrough; case QH_STATE_IDLE: qh_completions(oxu, qh); break; @@ -3450,7 +3449,7 @@ rescan: if (!tmp) goto nogood; unlink_async(oxu, qh); - /* FALL THROUGH */ + fallthrough; case QH_STATE_UNLINK: /* wait for hw to finish? */ idle_timeout: spin_unlock_irqrestore(&oxu->lock, flags); @@ -3461,7 +3460,7 @@ idle_timeout: qh_put(qh); break; } - /* fall through */ + fallthrough; default: nogood: /* caller was supposed to have unlinked any requests; diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 0b949acfa258..b8961c0381cf 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -1133,7 +1133,7 @@ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) } EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); -/** +/* * PCI Quirks for xHCI. * * Takes care of the handoff between the Pre-OS (i.e. BIOS) and the OS. diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 0c03ac6b0213..63719cdf6a4e 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -475,16 +475,14 @@ static void pipe_stop(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe) static void clear_all_buffer(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe) { - u16 tmp; - if (!pipe || pipe->info.pipenum == 0) return; pipe_stop(r8a66597, pipe); r8a66597_bset(r8a66597, ACLRM, pipe->pipectr); - tmp = r8a66597_read(r8a66597, pipe->pipectr); - tmp = r8a66597_read(r8a66597, pipe->pipectr); - tmp = r8a66597_read(r8a66597, pipe->pipectr); + r8a66597_read(r8a66597, pipe->pipectr); + r8a66597_read(r8a66597, pipe->pipectr); + r8a66597_read(r8a66597, pipe->pipectr); r8a66597_bclr(r8a66597, ACLRM, pipe->pipectr); } diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index 93e2cca5262d..c57178db7994 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/** +/* * xhci-dbgcap.c - xHCI debug capability support * * Copyright (C) 2017 Intel Corporation @@ -14,24 +14,27 @@ #include "xhci-trace.h" #include "xhci-dbgcap.h" -static inline void * -dbc_dma_alloc_coherent(struct xhci_hcd *xhci, size_t size, - dma_addr_t *dma_handle, gfp_t flags) +static void dbc_free_ctx(struct device *dev, struct xhci_container_ctx *ctx) { - void *vaddr; - - vaddr = dma_alloc_coherent(xhci_to_hcd(xhci)->self.sysdev, - size, dma_handle, flags); - return vaddr; + if (!ctx) + return; + dma_free_coherent(dev, ctx->size, ctx->bytes, ctx->dma); + kfree(ctx); } -static inline void -dbc_dma_free_coherent(struct xhci_hcd *xhci, size_t size, - void *cpu_addr, dma_addr_t dma_handle) +/* we use only one segment for DbC rings */ +static void dbc_ring_free(struct device *dev, struct xhci_ring *ring) { - if (cpu_addr) - dma_free_coherent(xhci_to_hcd(xhci)->self.sysdev, - size, cpu_addr, dma_handle); + if (!ring) + return; + + if (ring->first_seg && ring->first_seg->trbs) { + dma_free_coherent(dev, TRB_SEGMENT_SIZE, + ring->first_seg->trbs, + ring->first_seg->dma); + kfree(ring->first_seg); + } + kfree(ring); } static u32 xhci_dbc_populate_strings(struct dbc_str_descs *strings) @@ -83,16 +86,14 @@ static u32 xhci_dbc_populate_strings(struct dbc_str_descs *strings) return string_length; } -static void xhci_dbc_init_contexts(struct xhci_hcd *xhci, u32 string_length) +static void xhci_dbc_init_contexts(struct xhci_dbc *dbc, u32 string_length) { - struct xhci_dbc *dbc; struct dbc_info_context *info; struct xhci_ep_ctx *ep_ctx; u32 dev_info; dma_addr_t deq, dma; unsigned int max_burst; - dbc = xhci->dbc; if (!dbc) return; @@ -121,7 +122,7 @@ static void xhci_dbc_init_contexts(struct xhci_hcd *xhci, u32 string_length) ep_ctx->deq = cpu_to_le64(deq | dbc->ring_in->cycle_state); /* Set DbC context and info registers: */ - xhci_write_64(xhci, dbc->ctx->dma, &dbc->regs->dccp); + lo_hi_writeq(dbc->ctx->dma, &dbc->regs->dccp); dev_info = cpu_to_le32((DBC_VENDOR_ID << 16) | DBC_PROTOCOL); writel(dev_info, &dbc->regs->devinfo1); @@ -134,10 +135,8 @@ static void xhci_dbc_giveback(struct dbc_request *req, int status) __releases(&dbc->lock) __acquires(&dbc->lock) { - struct dbc_ep *dep = req->dep; - struct xhci_dbc *dbc = dep->dbc; - struct xhci_hcd *xhci = dbc->xhci; - struct device *dev = xhci_to_hcd(dbc->xhci)->self.sysdev; + struct xhci_dbc *dbc = req->dbc; + struct device *dev = dbc->dev; list_del_init(&req->list_pending); req->trb_dma = 0; @@ -151,11 +150,11 @@ static void xhci_dbc_giveback(struct dbc_request *req, int status) dma_unmap_single(dev, req->dma, req->length, - dbc_ep_dma_direction(dep)); + dbc_ep_dma_direction(req)); /* Give back the transfer request: */ spin_unlock(&dbc->lock); - req->complete(xhci, req); + req->complete(dbc, req); spin_lock(&dbc->lock); } @@ -187,18 +186,25 @@ static void xhci_dbc_flush_requests(struct xhci_dbc *dbc) } struct dbc_request * -dbc_alloc_request(struct dbc_ep *dep, gfp_t gfp_flags) +dbc_alloc_request(struct xhci_dbc *dbc, unsigned int direction, gfp_t flags) { struct dbc_request *req; - req = kzalloc(sizeof(*req), gfp_flags); + if (direction != BULK_IN && + direction != BULK_OUT) + return NULL; + + if (!dbc) + return NULL; + + req = kzalloc(sizeof(*req), flags); if (!req) return NULL; - req->dep = dep; + req->dbc = dbc; INIT_LIST_HEAD(&req->list_pending); INIT_LIST_HEAD(&req->list_pool); - req->direction = dep->direction; + req->direction = direction; trace_xhci_dbc_alloc_request(req); @@ -206,7 +212,7 @@ dbc_alloc_request(struct dbc_ep *dep, gfp_t gfp_flags) } void -dbc_free_request(struct dbc_ep *dep, struct dbc_request *req) +dbc_free_request(struct dbc_request *req) { trace_xhci_dbc_free_request(req); @@ -242,7 +248,7 @@ static int xhci_dbc_queue_bulk_tx(struct dbc_ep *dep, u64 addr; union xhci_trb *trb; unsigned int num_trbs; - struct xhci_dbc *dbc = dep->dbc; + struct xhci_dbc *dbc = req->dbc; struct xhci_ring *ring = dep->ring; u32 length, control, cycle; @@ -286,14 +292,12 @@ static int xhci_dbc_queue_bulk_tx(struct dbc_ep *dep, } static int -dbc_ep_do_queue(struct dbc_ep *dep, struct dbc_request *req) +dbc_ep_do_queue(struct dbc_request *req) { int ret; - struct device *dev; - struct xhci_dbc *dbc = dep->dbc; - struct xhci_hcd *xhci = dbc->xhci; - - dev = xhci_to_hcd(xhci)->self.sysdev; + struct xhci_dbc *dbc = req->dbc; + struct device *dev = dbc->dev; + struct dbc_ep *dep = &dbc->eps[req->direction]; if (!req->length || !req->buf) return -EINVAL; @@ -306,13 +310,13 @@ dbc_ep_do_queue(struct dbc_ep *dep, struct dbc_request *req) req->length, dbc_ep_dma_direction(dep)); if (dma_mapping_error(dev, req->dma)) { - xhci_err(xhci, "failed to map buffer\n"); + dev_err(dbc->dev, "failed to map buffer\n"); return -EFAULT; } ret = xhci_dbc_queue_bulk_tx(dep, req); if (ret) { - xhci_err(xhci, "failed to queue trbs\n"); + dev_err(dbc->dev, "failed to queue trbs\n"); dma_unmap_single(dev, req->dma, req->length, @@ -325,16 +329,22 @@ dbc_ep_do_queue(struct dbc_ep *dep, struct dbc_request *req) return 0; } -int dbc_ep_queue(struct dbc_ep *dep, struct dbc_request *req, - gfp_t gfp_flags) +int dbc_ep_queue(struct dbc_request *req) { unsigned long flags; - struct xhci_dbc *dbc = dep->dbc; + struct xhci_dbc *dbc = req->dbc; int ret = -ESHUTDOWN; + if (!dbc) + return -ENODEV; + + if (req->direction != BULK_IN && + req->direction != BULK_OUT) + return -EINVAL; + spin_lock_irqsave(&dbc->lock, flags); if (dbc->state == DS_CONFIGURED) - ret = dbc_ep_do_queue(dep, req); + ret = dbc_ep_do_queue(req); spin_unlock_irqrestore(&dbc->lock, flags); mod_delayed_work(system_wq, &dbc->event_work, 0); @@ -344,10 +354,9 @@ int dbc_ep_queue(struct dbc_ep *dep, struct dbc_request *req, return ret; } -static inline void xhci_dbc_do_eps_init(struct xhci_hcd *xhci, bool direction) +static inline void xhci_dbc_do_eps_init(struct xhci_dbc *dbc, bool direction) { struct dbc_ep *dep; - struct xhci_dbc *dbc = xhci->dbc; dep = &dbc->eps[direction]; dep->dbc = dbc; @@ -357,125 +366,205 @@ static inline void xhci_dbc_do_eps_init(struct xhci_hcd *xhci, bool direction) INIT_LIST_HEAD(&dep->list_pending); } -static void xhci_dbc_eps_init(struct xhci_hcd *xhci) +static void xhci_dbc_eps_init(struct xhci_dbc *dbc) { - xhci_dbc_do_eps_init(xhci, BULK_OUT); - xhci_dbc_do_eps_init(xhci, BULK_IN); + xhci_dbc_do_eps_init(dbc, BULK_OUT); + xhci_dbc_do_eps_init(dbc, BULK_IN); } -static void xhci_dbc_eps_exit(struct xhci_hcd *xhci) +static void xhci_dbc_eps_exit(struct xhci_dbc *dbc) { - struct xhci_dbc *dbc = xhci->dbc; - memset(dbc->eps, 0, sizeof(struct dbc_ep) * ARRAY_SIZE(dbc->eps)); } -static int xhci_dbc_mem_init(struct xhci_hcd *xhci, gfp_t flags) +static int dbc_erst_alloc(struct device *dev, struct xhci_ring *evt_ring, + struct xhci_erst *erst, gfp_t flags) +{ + erst->entries = dma_alloc_coherent(dev, sizeof(struct xhci_erst_entry), + &erst->erst_dma_addr, flags); + if (!erst->entries) + return -ENOMEM; + + erst->num_entries = 1; + erst->entries[0].seg_addr = cpu_to_le64(evt_ring->first_seg->dma); + erst->entries[0].seg_size = cpu_to_le32(TRBS_PER_SEGMENT); + erst->entries[0].rsvd = 0; + return 0; +} + +static void dbc_erst_free(struct device *dev, struct xhci_erst *erst) +{ + if (erst->entries) + dma_free_coherent(dev, sizeof(struct xhci_erst_entry), + erst->entries, erst->erst_dma_addr); + erst->entries = NULL; +} + +static struct xhci_container_ctx * +dbc_alloc_ctx(struct device *dev, gfp_t flags) +{ + struct xhci_container_ctx *ctx; + + ctx = kzalloc(sizeof(*ctx), flags); + if (!ctx) + return NULL; + + /* xhci 7.6.9, all three contexts; info, ep-out and ep-in. Each 64 bytes*/ + ctx->size = 3 * DBC_CONTEXT_SIZE; + ctx->bytes = dma_alloc_coherent(dev, ctx->size, &ctx->dma, flags); + if (!ctx->bytes) { + kfree(ctx); + return NULL; + } + return ctx; +} + +struct xhci_ring * +xhci_dbc_ring_alloc(struct device *dev, enum xhci_ring_type type, gfp_t flags) +{ + struct xhci_ring *ring; + struct xhci_segment *seg; + dma_addr_t dma; + + ring = kzalloc(sizeof(*ring), flags); + if (!ring) + return NULL; + + ring->num_segs = 1; + ring->type = type; + + seg = kzalloc(sizeof(*seg), flags); + if (!seg) + goto seg_fail; + + ring->first_seg = seg; + ring->last_seg = seg; + seg->next = seg; + + seg->trbs = dma_alloc_coherent(dev, TRB_SEGMENT_SIZE, &dma, flags); + if (!seg->trbs) + goto dma_fail; + + seg->dma = dma; + + /* Only event ring does not use link TRB */ + if (type != TYPE_EVENT) { + union xhci_trb *trb = &seg->trbs[TRBS_PER_SEGMENT - 1]; + + trb->link.segment_ptr = cpu_to_le64(dma); + trb->link.control = cpu_to_le32(LINK_TOGGLE | TRB_TYPE(TRB_LINK)); + } + INIT_LIST_HEAD(&ring->td_list); + xhci_initialize_ring_info(ring, 1); + return ring; +dma_fail: + kfree(seg); +seg_fail: + kfree(ring); + return NULL; +} + +static int xhci_dbc_mem_init(struct xhci_dbc *dbc, gfp_t flags) { int ret; dma_addr_t deq; u32 string_length; - struct xhci_dbc *dbc = xhci->dbc; + struct device *dev = dbc->dev; /* Allocate various rings for events and transfers: */ - dbc->ring_evt = xhci_ring_alloc(xhci, 1, 1, TYPE_EVENT, 0, flags); + dbc->ring_evt = xhci_dbc_ring_alloc(dev, TYPE_EVENT, flags); if (!dbc->ring_evt) goto evt_fail; - dbc->ring_in = xhci_ring_alloc(xhci, 1, 1, TYPE_BULK, 0, flags); + dbc->ring_in = xhci_dbc_ring_alloc(dev, TYPE_BULK, flags); if (!dbc->ring_in) goto in_fail; - dbc->ring_out = xhci_ring_alloc(xhci, 1, 1, TYPE_BULK, 0, flags); + dbc->ring_out = xhci_dbc_ring_alloc(dev, TYPE_BULK, flags); if (!dbc->ring_out) goto out_fail; /* Allocate and populate ERST: */ - ret = xhci_alloc_erst(xhci, dbc->ring_evt, &dbc->erst, flags); + ret = dbc_erst_alloc(dev, dbc->ring_evt, &dbc->erst, flags); if (ret) goto erst_fail; /* Allocate context data structure: */ - dbc->ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags); + dbc->ctx = dbc_alloc_ctx(dev, flags); /* was sysdev, and is still */ if (!dbc->ctx) goto ctx_fail; /* Allocate the string table: */ dbc->string_size = sizeof(struct dbc_str_descs); - dbc->string = dbc_dma_alloc_coherent(xhci, - dbc->string_size, - &dbc->string_dma, - flags); + dbc->string = dma_alloc_coherent(dev, dbc->string_size, + &dbc->string_dma, flags); if (!dbc->string) goto string_fail; /* Setup ERST register: */ writel(dbc->erst.erst_size, &dbc->regs->ersts); - xhci_write_64(xhci, dbc->erst.erst_dma_addr, &dbc->regs->erstba); + + lo_hi_writeq(dbc->erst.erst_dma_addr, &dbc->regs->erstba); deq = xhci_trb_virt_to_dma(dbc->ring_evt->deq_seg, dbc->ring_evt->dequeue); - xhci_write_64(xhci, deq, &dbc->regs->erdp); + lo_hi_writeq(deq, &dbc->regs->erdp); /* Setup strings and contexts: */ string_length = xhci_dbc_populate_strings(dbc->string); - xhci_dbc_init_contexts(xhci, string_length); + xhci_dbc_init_contexts(dbc, string_length); - xhci_dbc_eps_init(xhci); + xhci_dbc_eps_init(dbc); dbc->state = DS_INITIALIZED; return 0; string_fail: - xhci_free_container_ctx(xhci, dbc->ctx); + dbc_free_ctx(dev, dbc->ctx); dbc->ctx = NULL; ctx_fail: - xhci_free_erst(xhci, &dbc->erst); + dbc_erst_free(dev, &dbc->erst); erst_fail: - xhci_ring_free(xhci, dbc->ring_out); + dbc_ring_free(dev, dbc->ring_out); dbc->ring_out = NULL; out_fail: - xhci_ring_free(xhci, dbc->ring_in); + dbc_ring_free(dev, dbc->ring_in); dbc->ring_in = NULL; in_fail: - xhci_ring_free(xhci, dbc->ring_evt); + dbc_ring_free(dev, dbc->ring_evt); dbc->ring_evt = NULL; evt_fail: return -ENOMEM; } -static void xhci_dbc_mem_cleanup(struct xhci_hcd *xhci) +static void xhci_dbc_mem_cleanup(struct xhci_dbc *dbc) { - struct xhci_dbc *dbc = xhci->dbc; - if (!dbc) return; - xhci_dbc_eps_exit(xhci); + xhci_dbc_eps_exit(dbc); if (dbc->string) { - dbc_dma_free_coherent(xhci, - dbc->string_size, - dbc->string, dbc->string_dma); + dma_free_coherent(dbc->dev, dbc->string_size, + dbc->string, dbc->string_dma); dbc->string = NULL; } - xhci_free_container_ctx(xhci, dbc->ctx); + dbc_free_ctx(dbc->dev, dbc->ctx); dbc->ctx = NULL; - xhci_free_erst(xhci, &dbc->erst); - xhci_ring_free(xhci, dbc->ring_out); - xhci_ring_free(xhci, dbc->ring_in); - xhci_ring_free(xhci, dbc->ring_evt); + dbc_erst_free(dbc->dev, &dbc->erst); + dbc_ring_free(dbc->dev, dbc->ring_out); + dbc_ring_free(dbc->dev, dbc->ring_in); + dbc_ring_free(dbc->dev, dbc->ring_evt); dbc->ring_in = NULL; dbc->ring_out = NULL; dbc->ring_evt = NULL; } -static int xhci_do_dbc_start(struct xhci_hcd *xhci) +static int xhci_do_dbc_start(struct xhci_dbc *dbc) { int ret; u32 ctrl; - struct xhci_dbc *dbc = xhci->dbc; if (dbc->state != DS_DISABLED) return -EINVAL; @@ -487,7 +576,7 @@ static int xhci_do_dbc_start(struct xhci_hcd *xhci) if (ret) return ret; - ret = xhci_dbc_mem_init(xhci, GFP_ATOMIC); + ret = xhci_dbc_mem_init(dbc, GFP_ATOMIC); if (ret) return ret; @@ -505,10 +594,8 @@ static int xhci_do_dbc_start(struct xhci_hcd *xhci) return 0; } -static int xhci_do_dbc_stop(struct xhci_hcd *xhci) +static int xhci_do_dbc_stop(struct xhci_dbc *dbc) { - struct xhci_dbc *dbc = xhci->dbc; - if (dbc->state == DS_DISABLED) return -1; @@ -518,76 +605,81 @@ static int xhci_do_dbc_stop(struct xhci_hcd *xhci) return 0; } -static int xhci_dbc_start(struct xhci_hcd *xhci) +static int xhci_dbc_start(struct xhci_dbc *dbc) { int ret; unsigned long flags; - struct xhci_dbc *dbc = xhci->dbc; WARN_ON(!dbc); - pm_runtime_get_sync(xhci_to_hcd(xhci)->self.controller); + pm_runtime_get_sync(dbc->dev); /* note this was self.controller */ spin_lock_irqsave(&dbc->lock, flags); - ret = xhci_do_dbc_start(xhci); + ret = xhci_do_dbc_start(dbc); spin_unlock_irqrestore(&dbc->lock, flags); if (ret) { - pm_runtime_put(xhci_to_hcd(xhci)->self.controller); + pm_runtime_put(dbc->dev); /* note this was self.controller */ return ret; } return mod_delayed_work(system_wq, &dbc->event_work, 1); } -static void xhci_dbc_stop(struct xhci_hcd *xhci) +static void xhci_dbc_stop(struct xhci_dbc *dbc) { int ret; unsigned long flags; - struct xhci_dbc *dbc = xhci->dbc; - struct dbc_port *port = &dbc->port; WARN_ON(!dbc); - cancel_delayed_work_sync(&dbc->event_work); + switch (dbc->state) { + case DS_DISABLED: + return; + case DS_CONFIGURED: + case DS_STALLED: + if (dbc->driver->disconnect) + dbc->driver->disconnect(dbc); + break; + default: + break; + } - if (port->registered) - xhci_dbc_tty_unregister_device(xhci); + cancel_delayed_work_sync(&dbc->event_work); spin_lock_irqsave(&dbc->lock, flags); - ret = xhci_do_dbc_stop(xhci); + ret = xhci_do_dbc_stop(dbc); spin_unlock_irqrestore(&dbc->lock, flags); if (!ret) { - xhci_dbc_mem_cleanup(xhci); - pm_runtime_put_sync(xhci_to_hcd(xhci)->self.controller); + xhci_dbc_mem_cleanup(dbc); + pm_runtime_put_sync(dbc->dev); /* note, was self.controller */ } } static void -dbc_handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event) +dbc_handle_port_status(struct xhci_dbc *dbc, union xhci_trb *event) { u32 portsc; - struct xhci_dbc *dbc = xhci->dbc; portsc = readl(&dbc->regs->portsc); if (portsc & DBC_PORTSC_CONN_CHANGE) - xhci_info(xhci, "DbC port connect change\n"); + dev_info(dbc->dev, "DbC port connect change\n"); if (portsc & DBC_PORTSC_RESET_CHANGE) - xhci_info(xhci, "DbC port reset change\n"); + dev_info(dbc->dev, "DbC port reset change\n"); if (portsc & DBC_PORTSC_LINK_CHANGE) - xhci_info(xhci, "DbC port link status change\n"); + dev_info(dbc->dev, "DbC port link status change\n"); if (portsc & DBC_PORTSC_CONFIG_CHANGE) - xhci_info(xhci, "DbC config error change\n"); + dev_info(dbc->dev, "DbC config error change\n"); /* Port reset change bit will be cleared in other place: */ writel(portsc & ~DBC_PORTSC_RESET_CHANGE, &dbc->regs->portsc); } -static void dbc_handle_xfer_event(struct xhci_hcd *xhci, union xhci_trb *event) +static void dbc_handle_xfer_event(struct xhci_dbc *dbc, union xhci_trb *event) { struct dbc_ep *dep; struct xhci_ring *ring; @@ -601,7 +693,7 @@ static void dbc_handle_xfer_event(struct xhci_hcd *xhci, union xhci_trb *event) remain_length = EVENT_TRB_LEN(le32_to_cpu(event->generic.field[2])); ep_id = TRB_TO_EP_ID(le32_to_cpu(event->generic.field[3])); dep = (ep_id == EPID_OUT) ? - get_out_ep(xhci) : get_in_ep(xhci); + get_out_ep(dbc) : get_in_ep(dbc); ring = dep->ring; switch (comp_code) { @@ -615,11 +707,11 @@ static void dbc_handle_xfer_event(struct xhci_hcd *xhci, union xhci_trb *event) case COMP_BABBLE_DETECTED_ERROR: case COMP_USB_TRANSACTION_ERROR: case COMP_STALL_ERROR: - xhci_warn(xhci, "tx error %d detected\n", comp_code); + dev_warn(dbc->dev, "tx error %d detected\n", comp_code); status = -comp_code; break; default: - xhci_err(xhci, "unknown tx error %d\n", comp_code); + dev_err(dbc->dev, "unknown tx error %d\n", comp_code); status = -comp_code; break; } @@ -633,7 +725,7 @@ static void dbc_handle_xfer_event(struct xhci_hcd *xhci, union xhci_trb *event) } if (!req) { - xhci_warn(xhci, "no matched request\n"); + dev_warn(dbc->dev, "no matched request\n"); return; } @@ -644,13 +736,23 @@ static void dbc_handle_xfer_event(struct xhci_hcd *xhci, union xhci_trb *event) xhci_dbc_giveback(req, status); } +static void inc_evt_deq(struct xhci_ring *ring) +{ + /* If on the last TRB of the segment go back to the beginning */ + if (ring->dequeue == &ring->deq_seg->trbs[TRBS_PER_SEGMENT - 1]) { + ring->cycle_state ^= 1; + ring->dequeue = ring->deq_seg->trbs; + return; + } + ring->dequeue++; +} + static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) { dma_addr_t deq; struct dbc_ep *dep; union xhci_trb *evt; u32 ctrl, portsc; - struct xhci_hcd *xhci = dbc->xhci; bool update_erdp = false; /* DbC state machine: */ @@ -663,7 +765,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) portsc = readl(&dbc->regs->portsc); if (portsc & DBC_PORTSC_CONN_STATUS) { dbc->state = DS_CONNECTED; - xhci_info(xhci, "DbC connected\n"); + dev_info(dbc->dev, "DbC connected\n"); } return EVT_DONE; @@ -671,7 +773,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) ctrl = readl(&dbc->regs->control); if (ctrl & DBC_CTRL_DBC_RUN) { dbc->state = DS_CONFIGURED; - xhci_info(xhci, "DbC configured\n"); + dev_info(dbc->dev, "DbC configured\n"); portsc = readl(&dbc->regs->portsc); writel(portsc, &dbc->regs->portsc); return EVT_GSER; @@ -683,7 +785,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) portsc = readl(&dbc->regs->portsc); if (!(portsc & DBC_PORTSC_PORT_ENABLED) && !(portsc & DBC_PORTSC_CONN_STATUS)) { - xhci_info(xhci, "DbC cable unplugged\n"); + dev_info(dbc->dev, "DbC cable unplugged\n"); dbc->state = DS_ENABLED; xhci_dbc_flush_requests(dbc); @@ -692,7 +794,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) /* Handle debug port reset event: */ if (portsc & DBC_PORTSC_RESET_CHANGE) { - xhci_info(xhci, "DbC port reset\n"); + dev_info(dbc->dev, "DbC port reset\n"); writel(portsc, &dbc->regs->portsc); dbc->state = DS_ENABLED; xhci_dbc_flush_requests(dbc); @@ -704,16 +806,16 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) ctrl = readl(&dbc->regs->control); if ((ctrl & DBC_CTRL_HALT_IN_TR) || (ctrl & DBC_CTRL_HALT_OUT_TR)) { - xhci_info(xhci, "DbC Endpoint stall\n"); + dev_info(dbc->dev, "DbC Endpoint stall\n"); dbc->state = DS_STALLED; if (ctrl & DBC_CTRL_HALT_IN_TR) { - dep = get_in_ep(xhci); + dep = get_in_ep(dbc); xhci_dbc_flush_endpoint_requests(dep); } if (ctrl & DBC_CTRL_HALT_OUT_TR) { - dep = get_out_ep(xhci); + dep = get_out_ep(dbc); xhci_dbc_flush_endpoint_requests(dep); } @@ -738,7 +840,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) return EVT_DONE; default: - xhci_err(xhci, "Unknown DbC state %d\n", dbc->state); + dev_err(dbc->dev, "Unknown DbC state %d\n", dbc->state); break; } @@ -756,16 +858,17 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) switch (le32_to_cpu(evt->event_cmd.flags) & TRB_TYPE_BITMASK) { case TRB_TYPE(TRB_PORT_STATUS): - dbc_handle_port_status(xhci, evt); + dbc_handle_port_status(dbc, evt); break; case TRB_TYPE(TRB_TRANSFER): - dbc_handle_xfer_event(xhci, evt); + dbc_handle_xfer_event(dbc, evt); break; default: break; } - inc_deq(xhci, dbc->ring_evt); + inc_evt_deq(dbc->ring_evt); + evt = dbc->ring_evt->dequeue; update_erdp = true; } @@ -774,7 +877,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) if (update_erdp) { deq = xhci_trb_virt_to_dma(dbc->ring_evt->deq_seg, dbc->ring_evt->dequeue); - xhci_write_64(xhci, deq, &dbc->regs->erdp); + lo_hi_writeq(deq, &dbc->regs->erdp); } return EVT_DONE; @@ -782,14 +885,11 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) static void xhci_dbc_handle_events(struct work_struct *work) { - int ret; enum evtreturn evtr; struct xhci_dbc *dbc; unsigned long flags; - struct xhci_hcd *xhci; dbc = container_of(to_delayed_work(work), struct xhci_dbc, event_work); - xhci = dbc->xhci; spin_lock_irqsave(&dbc->lock, flags); evtr = xhci_dbc_do_handle_events(dbc); @@ -797,21 +897,17 @@ static void xhci_dbc_handle_events(struct work_struct *work) switch (evtr) { case EVT_GSER: - ret = xhci_dbc_tty_register_device(xhci); - if (ret) { - xhci_err(xhci, "failed to alloc tty device\n"); - break; - } - - xhci_info(xhci, "DbC now attached to /dev/ttyDBC0\n"); + if (dbc->driver->configure) + dbc->driver->configure(dbc); break; case EVT_DISC: - xhci_dbc_tty_unregister_device(xhci); + if (dbc->driver->disconnect) + dbc->driver->disconnect(dbc); break; case EVT_DONE: break; default: - xhci_info(xhci, "stop handling dbc events\n"); + dev_info(dbc->dev, "stop handling dbc events\n"); return; } @@ -864,6 +960,7 @@ static int xhci_do_dbc_init(struct xhci_hcd *xhci) spin_unlock_irqrestore(&xhci->lock, flags); dbc->xhci = xhci; + dbc->dev = xhci_to_hcd(xhci)->self.sysdev; INIT_DELAYED_WORK(&dbc->event_work, xhci_dbc_handle_events); spin_lock_init(&dbc->lock); @@ -912,13 +1009,15 @@ static ssize_t dbc_store(struct device *dev, const char *buf, size_t count) { struct xhci_hcd *xhci; + struct xhci_dbc *dbc; xhci = hcd_to_xhci(dev_get_drvdata(dev)); + dbc = xhci->dbc; if (!strncmp(buf, "enable", 6)) - xhci_dbc_start(xhci); + xhci_dbc_start(dbc); else if (!strncmp(buf, "disable", 7)) - xhci_dbc_stop(xhci); + xhci_dbc_stop(dbc); else return -EINVAL; @@ -936,7 +1035,7 @@ int xhci_dbc_init(struct xhci_hcd *xhci) if (ret) goto init_err3; - ret = xhci_dbc_tty_register_driver(xhci); + ret = xhci_dbc_tty_probe(xhci); if (ret) goto init_err2; @@ -947,7 +1046,7 @@ int xhci_dbc_init(struct xhci_hcd *xhci) return 0; init_err1: - xhci_dbc_tty_unregister_driver(); + xhci_dbc_tty_remove(xhci->dbc); init_err2: xhci_do_dbc_exit(xhci); init_err3: @@ -962,8 +1061,8 @@ void xhci_dbc_exit(struct xhci_hcd *xhci) return; device_remove_file(dev, &dev_attr_dbc); - xhci_dbc_tty_unregister_driver(); - xhci_dbc_stop(xhci); + xhci_dbc_tty_remove(xhci->dbc); + xhci_dbc_stop(xhci->dbc); xhci_do_dbc_exit(xhci); } @@ -978,7 +1077,7 @@ int xhci_dbc_suspend(struct xhci_hcd *xhci) if (dbc->state == DS_CONFIGURED) dbc->resume_required = 1; - xhci_dbc_stop(xhci); + xhci_dbc_stop(dbc); return 0; } @@ -993,7 +1092,7 @@ int xhci_dbc_resume(struct xhci_hcd *xhci) if (dbc->resume_required) { dbc->resume_required = 0; - xhci_dbc_start(xhci); + xhci_dbc_start(dbc); } return ret; diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h index ce0c6072bd48..c70b78d504eb 100644 --- a/drivers/usb/host/xhci-dbgcap.h +++ b/drivers/usb/host/xhci-dbgcap.h @@ -84,28 +84,11 @@ enum dbc_state { DS_STALLED, }; -struct dbc_request { - void *buf; - unsigned int length; - dma_addr_t dma; - void (*complete)(struct xhci_hcd *xhci, - struct dbc_request *req); - struct list_head list_pool; - int status; - unsigned int actual; - - struct dbc_ep *dep; - struct list_head list_pending; - dma_addr_t trb_dma; - union xhci_trb *trb; - unsigned direction:1; -}; - struct dbc_ep { struct xhci_dbc *dbc; struct list_head list_pending; struct xhci_ring *ring; - unsigned direction:1; + unsigned int direction:1; }; #define DBC_QUEUE_SIZE 16 @@ -127,12 +110,16 @@ struct dbc_port { struct kfifo write_fifo; bool registered; - struct dbc_ep *in; - struct dbc_ep *out; +}; + +struct dbc_driver { + int (*configure)(struct xhci_dbc *dbc); + void (*disconnect)(struct xhci_dbc *dbc); }; struct xhci_dbc { spinlock_t lock; /* device access */ + struct device *dev; struct xhci_hcd *xhci; struct dbc_regs __iomem *regs; struct xhci_ring *ring_evt; @@ -150,7 +137,25 @@ struct xhci_dbc { unsigned resume_required:1; struct dbc_ep eps[2]; - struct dbc_port port; + const struct dbc_driver *driver; + void *priv; +}; + +struct dbc_request { + void *buf; + unsigned int length; + dma_addr_t dma; + void (*complete)(struct xhci_dbc *dbc, + struct dbc_request *req); + struct list_head list_pool; + int status; + unsigned int actual; + + struct xhci_dbc *dbc; + struct list_head list_pending; + dma_addr_t trb_dma; + union xhci_trb *trb; + unsigned direction:1; }; #define dbc_bulkout_ctx(d) \ @@ -178,30 +183,26 @@ enum evtreturn { EVT_DISC, }; -static inline struct dbc_ep *get_in_ep(struct xhci_hcd *xhci) +static inline struct dbc_ep *get_in_ep(struct xhci_dbc *dbc) { - struct xhci_dbc *dbc = xhci->dbc; - return &dbc->eps[BULK_IN]; } -static inline struct dbc_ep *get_out_ep(struct xhci_hcd *xhci) +static inline struct dbc_ep *get_out_ep(struct xhci_dbc *dbc) { - struct xhci_dbc *dbc = xhci->dbc; - return &dbc->eps[BULK_OUT]; } #ifdef CONFIG_USB_XHCI_DBGCAP int xhci_dbc_init(struct xhci_hcd *xhci); void xhci_dbc_exit(struct xhci_hcd *xhci); -int xhci_dbc_tty_register_driver(struct xhci_hcd *xhci); -void xhci_dbc_tty_unregister_driver(void); -int xhci_dbc_tty_register_device(struct xhci_hcd *xhci); -void xhci_dbc_tty_unregister_device(struct xhci_hcd *xhci); -struct dbc_request *dbc_alloc_request(struct dbc_ep *dep, gfp_t gfp_flags); -void dbc_free_request(struct dbc_ep *dep, struct dbc_request *req); -int dbc_ep_queue(struct dbc_ep *dep, struct dbc_request *req, gfp_t gfp_flags); +int xhci_dbc_tty_probe(struct xhci_hcd *xhci); +void xhci_dbc_tty_remove(struct xhci_dbc *dbc); +struct dbc_request *dbc_alloc_request(struct xhci_dbc *dbc, + unsigned int direction, + gfp_t flags); +void dbc_free_request(struct dbc_request *req); +int dbc_ep_queue(struct dbc_request *req); #ifdef CONFIG_PM int xhci_dbc_suspend(struct xhci_hcd *xhci); int xhci_dbc_resume(struct xhci_hcd *xhci); diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c index be726c791323..0b942112b6f8 100644 --- a/drivers/usb/host/xhci-dbgtty.c +++ b/drivers/usb/host/xhci-dbgtty.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/** +/* * xhci-dbgtty.c - tty glue for xHCI debug capability * * Copyright (C) 2017 Intel Corporation @@ -14,6 +14,16 @@ #include "xhci.h" #include "xhci-dbgcap.h" +static int dbc_tty_init(void); +static void dbc_tty_exit(void); + +static struct tty_driver *dbc_tty_driver; + +static inline struct dbc_port *dbc_to_port(struct xhci_dbc *dbc) +{ + return dbc->priv; +} + static unsigned int dbc_send_packet(struct dbc_port *port, char *packet, unsigned int size) { @@ -48,7 +58,7 @@ static int dbc_start_tx(struct dbc_port *port) list_del(&req->list_pool); spin_unlock(&port->port_lock); - status = dbc_ep_queue(port->out, req, GFP_ATOMIC); + status = dbc_ep_queue(req); spin_lock(&port->port_lock); if (status) { @@ -80,7 +90,7 @@ static void dbc_start_rx(struct dbc_port *port) req->length = DBC_MAX_PACKET; spin_unlock(&port->port_lock); - status = dbc_ep_queue(port->in, req, GFP_ATOMIC); + status = dbc_ep_queue(req); spin_lock(&port->port_lock); if (status) { @@ -91,11 +101,10 @@ static void dbc_start_rx(struct dbc_port *port) } static void -dbc_read_complete(struct xhci_hcd *xhci, struct dbc_request *req) +dbc_read_complete(struct xhci_dbc *dbc, struct dbc_request *req) { unsigned long flags; - struct xhci_dbc *dbc = xhci->dbc; - struct dbc_port *port = &dbc->port; + struct dbc_port *port = dbc_to_port(dbc); spin_lock_irqsave(&port->port_lock, flags); list_add_tail(&req->list_pool, &port->read_queue); @@ -103,11 +112,10 @@ dbc_read_complete(struct xhci_hcd *xhci, struct dbc_request *req) spin_unlock_irqrestore(&port->port_lock, flags); } -static void dbc_write_complete(struct xhci_hcd *xhci, struct dbc_request *req) +static void dbc_write_complete(struct xhci_dbc *dbc, struct dbc_request *req) { unsigned long flags; - struct xhci_dbc *dbc = xhci->dbc; - struct dbc_port *port = &dbc->port; + struct dbc_port *port = dbc_to_port(dbc); spin_lock_irqsave(&port->port_lock, flags); list_add(&req->list_pool, &port->write_pool); @@ -118,35 +126,36 @@ static void dbc_write_complete(struct xhci_hcd *xhci, struct dbc_request *req) case -ESHUTDOWN: break; default: - xhci_warn(xhci, "unexpected write complete status %d\n", + dev_warn(dbc->dev, "unexpected write complete status %d\n", req->status); break; } spin_unlock_irqrestore(&port->port_lock, flags); } -static void xhci_dbc_free_req(struct dbc_ep *dep, struct dbc_request *req) +static void xhci_dbc_free_req(struct dbc_request *req) { kfree(req->buf); - dbc_free_request(dep, req); + dbc_free_request(req); } static int -xhci_dbc_alloc_requests(struct dbc_ep *dep, struct list_head *head, - void (*fn)(struct xhci_hcd *, struct dbc_request *)) +xhci_dbc_alloc_requests(struct xhci_dbc *dbc, unsigned int direction, + struct list_head *head, + void (*fn)(struct xhci_dbc *, struct dbc_request *)) { int i; struct dbc_request *req; for (i = 0; i < DBC_QUEUE_SIZE; i++) { - req = dbc_alloc_request(dep, GFP_KERNEL); + req = dbc_alloc_request(dbc, direction, GFP_KERNEL); if (!req) break; req->length = DBC_MAX_PACKET; req->buf = kmalloc(req->length, GFP_KERNEL); if (!req->buf) { - dbc_free_request(dep, req); + dbc_free_request(req); break; } @@ -158,14 +167,14 @@ xhci_dbc_alloc_requests(struct dbc_ep *dep, struct list_head *head, } static void -xhci_dbc_free_requests(struct dbc_ep *dep, struct list_head *head) +xhci_dbc_free_requests(struct list_head *head) { struct dbc_request *req; while (!list_empty(head)) { req = list_entry(head->next, struct dbc_request, list_pool); list_del(&req->list_pool); - xhci_dbc_free_req(dep, req); + xhci_dbc_free_req(req); } } @@ -279,55 +288,6 @@ static const struct tty_operations dbc_tty_ops = { .unthrottle = dbc_tty_unthrottle, }; -static struct tty_driver *dbc_tty_driver; - -int xhci_dbc_tty_register_driver(struct xhci_hcd *xhci) -{ - int status; - struct xhci_dbc *dbc = xhci->dbc; - - dbc_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV); - if (IS_ERR(dbc_tty_driver)) { - status = PTR_ERR(dbc_tty_driver); - dbc_tty_driver = NULL; - return status; - } - - dbc_tty_driver->driver_name = "dbc_serial"; - dbc_tty_driver->name = "ttyDBC"; - - dbc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - dbc_tty_driver->subtype = SERIAL_TYPE_NORMAL; - dbc_tty_driver->init_termios = tty_std_termios; - dbc_tty_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - dbc_tty_driver->init_termios.c_ispeed = 9600; - dbc_tty_driver->init_termios.c_ospeed = 9600; - dbc_tty_driver->driver_state = &dbc->port; - - tty_set_operations(dbc_tty_driver, &dbc_tty_ops); - - status = tty_register_driver(dbc_tty_driver); - if (status) { - xhci_err(xhci, - "can't register dbc tty driver, err %d\n", status); - put_tty_driver(dbc_tty_driver); - dbc_tty_driver = NULL; - } - - return status; -} - -void xhci_dbc_tty_unregister_driver(void) -{ - if (dbc_tty_driver) { - tty_unregister_driver(dbc_tty_driver); - put_tty_driver(dbc_tty_driver); - dbc_tty_driver = NULL; - } -} - static void dbc_rx_push(unsigned long _port) { struct dbc_request *req; @@ -418,7 +378,7 @@ static const struct tty_port_operations dbc_port_ops = { }; static void -xhci_dbc_tty_init_port(struct xhci_hcd *xhci, struct dbc_port *port) +xhci_dbc_tty_init_port(struct xhci_dbc *dbc, struct dbc_port *port) { tty_port_init(&port->port); spin_lock_init(&port->port_lock); @@ -427,8 +387,6 @@ xhci_dbc_tty_init_port(struct xhci_hcd *xhci, struct dbc_port *port) INIT_LIST_HEAD(&port->read_queue); INIT_LIST_HEAD(&port->write_pool); - port->in = get_in_ep(xhci); - port->out = get_out_ep(xhci); port->port.ops = &dbc_port_ops; port->n_read = 0; } @@ -440,14 +398,16 @@ xhci_dbc_tty_exit_port(struct dbc_port *port) tty_port_destroy(&port->port); } -int xhci_dbc_tty_register_device(struct xhci_hcd *xhci) +int xhci_dbc_tty_register_device(struct xhci_dbc *dbc) { int ret; struct device *tty_dev; - struct xhci_dbc *dbc = xhci->dbc; - struct dbc_port *port = &dbc->port; + struct dbc_port *port = dbc_to_port(dbc); + + if (port->registered) + return -EBUSY; - xhci_dbc_tty_init_port(xhci, port); + xhci_dbc_tty_init_port(dbc, port); tty_dev = tty_port_register_device(&port->port, dbc_tty_driver, 0, NULL); if (IS_ERR(tty_dev)) { @@ -459,12 +419,12 @@ int xhci_dbc_tty_register_device(struct xhci_hcd *xhci) if (ret) goto buf_alloc_fail; - ret = xhci_dbc_alloc_requests(port->in, &port->read_pool, + ret = xhci_dbc_alloc_requests(dbc, BULK_IN, &port->read_pool, dbc_read_complete); if (ret) goto request_fail; - ret = xhci_dbc_alloc_requests(port->out, &port->write_pool, + ret = xhci_dbc_alloc_requests(dbc, BULK_OUT, &port->write_pool, dbc_write_complete); if (ret) goto request_fail; @@ -474,8 +434,8 @@ int xhci_dbc_tty_register_device(struct xhci_hcd *xhci) return 0; request_fail: - xhci_dbc_free_requests(port->in, &port->read_pool); - xhci_dbc_free_requests(port->out, &port->write_pool); + xhci_dbc_free_requests(&port->read_pool); + xhci_dbc_free_requests(&port->write_pool); kfifo_free(&port->write_fifo); buf_alloc_fail: @@ -484,22 +444,113 @@ buf_alloc_fail: register_fail: xhci_dbc_tty_exit_port(port); - xhci_err(xhci, "can't register tty port, err %d\n", ret); + dev_err(dbc->dev, "can't register tty port, err %d\n", ret); return ret; } -void xhci_dbc_tty_unregister_device(struct xhci_hcd *xhci) +void xhci_dbc_tty_unregister_device(struct xhci_dbc *dbc) { - struct xhci_dbc *dbc = xhci->dbc; - struct dbc_port *port = &dbc->port; + struct dbc_port *port = dbc_to_port(dbc); + if (!port->registered) + return; tty_unregister_device(dbc_tty_driver, 0); xhci_dbc_tty_exit_port(port); port->registered = false; kfifo_free(&port->write_fifo); - xhci_dbc_free_requests(get_out_ep(xhci), &port->read_pool); - xhci_dbc_free_requests(get_out_ep(xhci), &port->read_queue); - xhci_dbc_free_requests(get_in_ep(xhci), &port->write_pool); + xhci_dbc_free_requests(&port->read_pool); + xhci_dbc_free_requests(&port->read_queue); + xhci_dbc_free_requests(&port->write_pool); +} + +static const struct dbc_driver dbc_driver = { + .configure = xhci_dbc_tty_register_device, + .disconnect = xhci_dbc_tty_unregister_device, +}; + +int xhci_dbc_tty_probe(struct xhci_hcd *xhci) +{ + struct xhci_dbc *dbc = xhci->dbc; + struct dbc_port *port; + int status; + + /* dbc_tty_init will be called by module init() in the future */ + status = dbc_tty_init(); + if (status) + return status; + + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) { + status = -ENOMEM; + goto out; + } + + dbc->driver = &dbc_driver; + dbc->priv = port; + + + dbc_tty_driver->driver_state = port; + + return 0; +out: + /* dbc_tty_exit will be called by module_exit() in the future */ + dbc_tty_exit(); + return status; +} + +/* + * undo what probe did, assume dbc is stopped already. + * we also assume tty_unregister_device() is called before this + */ +void xhci_dbc_tty_remove(struct xhci_dbc *dbc) +{ + struct dbc_port *port = dbc_to_port(dbc); + + dbc->driver = NULL; + dbc->priv = NULL; + kfree(port); + + /* dbc_tty_exit will be called by module_exit() in the future */ + dbc_tty_exit(); +} + +static int dbc_tty_init(void) +{ + int ret; + + dbc_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV); + if (IS_ERR(dbc_tty_driver)) + return PTR_ERR(dbc_tty_driver); + + dbc_tty_driver->driver_name = "dbc_serial"; + dbc_tty_driver->name = "ttyDBC"; + + dbc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + dbc_tty_driver->subtype = SERIAL_TYPE_NORMAL; + dbc_tty_driver->init_termios = tty_std_termios; + dbc_tty_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + dbc_tty_driver->init_termios.c_ispeed = 9600; + dbc_tty_driver->init_termios.c_ospeed = 9600; + + tty_set_operations(dbc_tty_driver, &dbc_tty_ops); + + ret = tty_register_driver(dbc_tty_driver); + if (ret) { + pr_err("Can't register dbc tty driver\n"); + put_tty_driver(dbc_tty_driver); + } + return ret; +} + +static void dbc_tty_exit(void) +{ + if (dbc_tty_driver) { + tty_unregister_driver(dbc_tty_driver); + put_tty_driver(dbc_tty_driver); + dbc_tty_driver = NULL; + } } diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c index 76c3f29562d2..92e25a62fdb5 100644 --- a/drivers/usb/host/xhci-debugfs.c +++ b/drivers/usb/host/xhci-debugfs.c @@ -110,6 +110,7 @@ static void xhci_debugfs_free_regset(struct xhci_regset *regset) kfree(regset); } +__printf(6, 7) static void xhci_debugfs_regset(struct xhci_hcd *xhci, u32 base, const struct debugfs_reg32 *regs, size_t nregs, struct dentry *parent, diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index f37316d2c8fa..c3554e37e09f 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -612,7 +612,7 @@ static void xhci_port_set_test_mode(struct xhci_hcd *xhci, temp |= test_mode << PORT_TEST_MODE_SHIFT; writel(temp, port->addr + PORTPMSC); xhci->test_mode = test_mode; - if (test_mode == TEST_FORCE_EN) + if (test_mode == USB_TEST_FORCE_ENABLE) xhci_start(xhci); } @@ -666,7 +666,7 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci) xhci_err(xhci, "Not in test mode, do nothing.\n"); return 0; } - if (xhci->test_mode == TEST_FORCE_EN && + if (xhci->test_mode == USB_TEST_FORCE_ENABLE && !(xhci->xhc_state & XHCI_STATE_HALTED)) { retval = xhci_halt(xhci); if (retval) @@ -1241,7 +1241,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = readl(ports[wIndex]->addr); /* Disable port */ if (link_state == USB_SS_PORT_LS_SS_DISABLED) { - xhci_dbg(xhci, "Disable port %d\n", wIndex); + xhci_dbg(xhci, "Disable port %d-%d\n", + hcd->self.busnum, wIndex + 1); temp = xhci_port_state_to_neutral(temp); /* * Clear all change bits, so that we get a new @@ -1257,7 +1258,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* Put link in RxDetect (enable port) */ if (link_state == USB_SS_PORT_LS_RX_DETECT) { - xhci_dbg(xhci, "Enable port %d\n", wIndex); + xhci_dbg(xhci, "Enable port %d-%d\n", + hcd->self.busnum, wIndex + 1); xhci_set_link_state(xhci, ports[wIndex], link_state); temp = readl(ports[wIndex]->addr); @@ -1289,8 +1291,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, goto error; } - xhci_dbg(xhci, "Enable compliance mode transition for port %d\n", - wIndex); + xhci_dbg(xhci, "Enable compliance mode transition for port %d-%d\n", + hcd->self.busnum, wIndex + 1); xhci_set_link_state(xhci, ports[wIndex], link_state); @@ -1304,8 +1306,9 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } /* Can't set port link state above '3' (U3) */ if (link_state > USB_SS_PORT_LS_U3) { - xhci_warn(xhci, "Cannot set port %d link state %d\n", - wIndex, link_state); + xhci_warn(xhci, "Cannot set port %d-%d link state %d\n", + hcd->self.busnum, wIndex + 1, + link_state); goto error; } @@ -1340,8 +1343,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, spin_unlock_irqrestore(&xhci->lock, flags); if (!wait_for_completion_timeout(&bus_state->u3exit_done[wIndex], msecs_to_jiffies(100))) - xhci_dbg(xhci, "missing U0 port change event for port %d\n", - wIndex); + xhci_dbg(xhci, "missing U0 port change event for port %d-%d\n", + hcd->self.busnum, wIndex + 1); spin_lock_irqsave(&xhci->lock, flags); temp = readl(ports[wIndex]->addr); break; @@ -1386,15 +1389,15 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, writel(temp, ports[wIndex]->addr); temp = readl(ports[wIndex]->addr); - xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); + xhci_dbg(xhci, "set port reset, actual port %d-%d status = 0x%x\n", + hcd->self.busnum, wIndex + 1, temp); break; case USB_PORT_FEAT_REMOTE_WAKE_MASK: xhci_set_remote_wake_mask(xhci, ports[wIndex], wake_mask); temp = readl(ports[wIndex]->addr); - xhci_dbg(xhci, "set port remote wake mask, " - "actual port %d status = 0x%x\n", - wIndex, temp); + xhci_dbg(xhci, "set port remote wake mask, actual port %d-%d status = 0x%x\n", + hcd->self.busnum, wIndex + 1, temp); break; case USB_PORT_FEAT_BH_PORT_RESET: temp |= PORT_WR; @@ -1421,7 +1424,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* 4.19.6 Port Test Modes (USB2 Test Mode) */ if (hcd->speed != HCD_USB2) goto error; - if (test_mode > TEST_FORCE_EN || test_mode < TEST_J) + if (test_mode > USB_TEST_FORCE_ENABLE || + test_mode < USB_TEST_J) goto error; retval = xhci_enter_test_mode(xhci, test_mode, wIndex, &flags); @@ -1634,8 +1638,8 @@ retry: spin_unlock_irqrestore(&xhci->lock, flags); msleep(XHCI_PORT_POLLING_LFPS_TIME); spin_lock_irqsave(&xhci->lock, flags); - xhci_dbg(xhci, "port %d polling in bus suspend, waiting\n", - port_index); + xhci_dbg(xhci, "port %d-%d polling in bus suspend, waiting\n", + hcd->self.busnum, port_index + 1); goto retry; } /* bail out if port detected a over-current condition */ @@ -1653,7 +1657,8 @@ retry: xhci_dbg(xhci, "Bus suspend bailout, port connect change\n"); return -EBUSY; } - xhci_dbg(xhci, "port %d not suspended\n", port_index); + xhci_dbg(xhci, "port %d-%d not suspended\n", + hcd->self.busnum, port_index + 1); t2 &= ~PORT_PLS_MASK; t2 |= PORT_LINK_STROBE | XDEV_U3; set_bit(port_index, &bus_state->bus_suspended); @@ -1783,7 +1788,8 @@ int xhci_bus_resume(struct usb_hcd *hcd) if ((xhci->quirks & XHCI_MISSING_CAS) && (hcd->speed >= HCD_USB3) && xhci_port_missing_cas_quirk(ports[port_index])) { - xhci_dbg(xhci, "reset stuck port %d\n", port_index); + xhci_dbg(xhci, "reset stuck port %d-%d\n", + hcd->self.busnum, port_index + 1); clear_bit(port_index, &bus_state->bus_suspended); continue; } @@ -1830,8 +1836,8 @@ int xhci_bus_resume(struct usb_hcd *hcd) sret = xhci_handshake(ports[port_index]->addr, PORT_PLC, PORT_PLC, 10 * 1000); if (sret) { - xhci_warn(xhci, "port %d resume PLC timeout\n", - port_index); + xhci_warn(xhci, "port %d-%d resume PLC timeout\n", + hcd->self.busnum, port_index + 1); continue; } xhci_test_and_clear_bit(xhci, ports[port_index], PORT_PLC); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 9764122c9cdf..696fad50b478 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -96,8 +96,9 @@ static void xhci_free_segments_for_ring(struct xhci_hcd *xhci, * DMA address of the next segment. The caller needs to set any Link TRB * related flags, such as End TRB, Toggle Cycle, and no snoop. */ -static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, - struct xhci_segment *next, enum xhci_ring_type type) +static void xhci_link_segments(struct xhci_segment *prev, + struct xhci_segment *next, + enum xhci_ring_type type, bool chain_links) { u32 val; @@ -112,11 +113,7 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control); val &= ~TRB_TYPE_BITMASK; val |= TRB_TYPE(TRB_LINK); - /* Always set the chain bit with 0.95 hardware */ - /* Set chain bit for isoc rings on AMD 0.96 host */ - if (xhci_link_trb_quirk(xhci) || - (type == TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST))) + if (chain_links) val |= TRB_CHAIN; prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val); } @@ -131,13 +128,19 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring, unsigned int num_segs) { struct xhci_segment *next; + bool chain_links; if (!ring || !first || !last) return; + /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */ + chain_links = !!(xhci_link_trb_quirk(xhci) || + (ring->type == TYPE_ISOC && + (xhci->quirks & XHCI_AMD_0x96_HOST))); + next = ring->enq_seg->next; - xhci_link_segments(xhci, ring->enq_seg, first, ring->type); - xhci_link_segments(xhci, last, next, ring->type); + xhci_link_segments(ring->enq_seg, first, ring->type, chain_links); + xhci_link_segments(last, next, ring->type, chain_links); ring->num_segs += num_segs; ring->num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs; @@ -290,8 +293,8 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring) kfree(ring); } -static void xhci_initialize_ring_info(struct xhci_ring *ring, - unsigned int cycle_state) +void xhci_initialize_ring_info(struct xhci_ring *ring, + unsigned int cycle_state) { /* The ring is empty, so the enqueue pointer == dequeue pointer */ ring->enqueue = ring->first_seg->trbs; @@ -321,6 +324,12 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, enum xhci_ring_type type, unsigned int max_packet, gfp_t flags) { struct xhci_segment *prev; + bool chain_links; + + /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */ + chain_links = !!(xhci_link_trb_quirk(xhci) || + (type == TYPE_ISOC && + (xhci->quirks & XHCI_AMD_0x96_HOST))); prev = xhci_segment_alloc(xhci, cycle_state, max_packet, flags); if (!prev) @@ -341,18 +350,18 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, } return -ENOMEM; } - xhci_link_segments(xhci, prev, next, type); + xhci_link_segments(prev, next, type, chain_links); prev = next; num_segs--; } - xhci_link_segments(xhci, prev, *first, type); + xhci_link_segments(prev, *first, type, chain_links); *last = prev; return 0; } -/** +/* * Create a new ring with zero or more segments. * * Link each segment together into a ring. diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index f6b4089bfc4a..3057cfc76d6a 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -2,7 +2,7 @@ /* * xhci-plat.c - xHCI host controller driver platform Bus Glue. * - * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de> * * A lot of code borrowed from the Linux xHCI driver. @@ -454,12 +454,14 @@ static const struct dev_pm_ops xhci_plat_pm_ops = { NULL) }; +#ifdef CONFIG_ACPI static const struct acpi_device_id usb_xhci_acpi_match[] = { /* XHCI-compliant USB Controller */ { "PNP0D10", }, { } }; MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match); +#endif static struct platform_driver usb_xhci_driver = { .probe = xhci_plat_probe, diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index ee6bf01775bb..014d79334f50 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -1853,11 +1853,7 @@ static const char * const tegra124_supply_names[] = { "avddio-pex", "dvddio-pex", "avdd-usb", - "avdd-pll-utmip", - "avdd-pll-erefe", - "avdd-usb-ss-pll", "hvdd-usb-ss", - "hvdd-usb-ss-pll-e", }; static const struct tegra_xusb_phy_type tegra124_phy_types[] = { @@ -1931,10 +1927,6 @@ static const char * const tegra210_supply_names[] = { "dvddio-pex", "hvddio-pex", "avdd-usb", - "avdd-pll-utmip", - "avdd-pll-uerefe", - "dvdd-pex-pll", - "hvdd-pex-pll-e", }; static const struct tegra_xusb_phy_type tegra210_phy_types[] = { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ed468eed299c..3c41b14ecce7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1271,7 +1271,7 @@ static int xhci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); } -/** +/* * xhci_get_endpoint_index - Used for passing endpoint bitmasks between the core and * HCDs. Find the index for an endpoint given its descriptor. Use the return * value to right shift 1 for the bitmask. diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index c295e8a7f5ae..ea1754f185a2 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -2015,6 +2015,8 @@ int xhci_alloc_erst(struct xhci_hcd *xhci, struct xhci_ring *evt_ring, struct xhci_erst *erst, gfp_t flags); +void xhci_initialize_ring_info(struct xhci_ring *ring, + unsigned int cycle_state); void xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst); void xhci_free_endpoint_ring(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, |