diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-sh.c | 9 | ||||
-rw-r--r-- | drivers/usb/host/max3421-hcd.c | 16 | ||||
-rw-r--r-- | drivers/usb/host/oxu210hp-hcd.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/sl811-hcd.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/xhci-caps.h | 6 | ||||
-rw-r--r-- | drivers/usb/host/xhci-dbgcap.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/xhci-dbgtty.c | 98 | ||||
-rw-r--r-- | drivers/usb/host/xhci-debugfs.c | 25 | ||||
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/xhci-plat.c | 6 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 20 | ||||
-rw-r--r-- | drivers/usb/host/xhci-tegra.c | 7 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 4 |
14 files changed, 125 insertions, 79 deletions
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index 5d0d972fb7b1..2d23690d72c5 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -119,8 +119,12 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) if (IS_ERR(priv->iclk)) priv->iclk = NULL; - clk_enable(priv->fclk); - clk_enable(priv->iclk); + ret = clk_enable(priv->fclk); + if (ret) + goto fail_request_resource; + ret = clk_enable(priv->iclk); + if (ret) + goto fail_iclk; ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret != 0) { @@ -136,6 +140,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) fail_add_hcd: clk_disable(priv->iclk); +fail_iclk: clk_disable(priv->fclk); fail_request_resource: diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index 9fe4f48b1898..0881fdd1823e 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -779,11 +779,17 @@ max3421_check_unlink(struct usb_hcd *hcd) retval = 1; dev_dbg(&spi->dev, "%s: URB %p unlinked=%d", __func__, urb, urb->unlinked); - usb_hcd_unlink_urb_from_ep(hcd, urb); - spin_unlock_irqrestore(&max3421_hcd->lock, - flags); - usb_hcd_giveback_urb(hcd, urb, 0); - spin_lock_irqsave(&max3421_hcd->lock, flags); + if (urb == max3421_hcd->curr_urb) { + max3421_hcd->urb_done = 1; + max3421_hcd->hien &= ~(BIT(MAX3421_HI_HXFRDN_BIT) | + BIT(MAX3421_HI_RCVDAV_BIT)); + } else { + usb_hcd_unlink_urb_from_ep(hcd, urb); + spin_unlock_irqrestore(&max3421_hcd->lock, + flags); + usb_hcd_giveback_urb(hcd, urb, 0); + spin_lock_irqsave(&max3421_hcd->lock, flags); + } } } } diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index a6c20facf945..fce800ba4c61 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -15,6 +15,7 @@ #include <linux/ioport.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/string_choices.h> #include <linux/errno.h> #include <linux/timer.h> #include <linux/list.h> @@ -2756,7 +2757,7 @@ static void ehci_port_power(struct oxu_hcd *oxu, int is_on) if (!HCS_PPC(oxu->hcs_params)) return; - oxu_dbg(oxu, "...power%s ports...\n", is_on ? "up" : "down"); + oxu_dbg(oxu, "...power%s ports...\n", str_up_down(is_on)); for (port = HCS_N_PORTS(oxu->hcs_params); port > 0; ) { if (is_on) oxu_hub_control(oxu_to_hcd(oxu), SetPortFeature, diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 036f5fd6d159..fa2e4badd288 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -48,6 +48,7 @@ #include <linux/usb/hcd.h> #include <linux/platform_device.h> #include <linux/prefetch.h> +#include <linux/string_choices.h> #include <linux/debugfs.h> #include <linux/seq_file.h> @@ -98,7 +99,7 @@ static void port_power(struct sl811 *sl811, int is_on) if (sl811->board && sl811->board->port_power) { /* switch VBUS, at 500mA unless hub power budget gets set */ dev_dbg(hcd->self.controller, "power %s\n", - is_on ? "on" : "off"); + str_on_off(is_on)); sl811->board->port_power(hcd->self.controller, is_on); } diff --git a/drivers/usb/host/xhci-caps.h b/drivers/usb/host/xhci-caps.h index 9e94cebf4a56..f6b9a00a0ab9 100644 --- a/drivers/usb/host/xhci-caps.h +++ b/drivers/usb/host/xhci-caps.h @@ -83,3 +83,9 @@ #define HCC2_CIC(p) ((p) & (1 << 5)) /* true: HC support Extended TBC Capability, Isoc burst count > 65535 */ #define HCC2_ETC(p) ((p) & (1 << 6)) +/* true: HC support Extended TBC TRB Status Capability */ +#define HCC2_ETC_TSC(p) ((p) & (1 << 7)) +/* true: HC support Get/Set Extended Property Capability */ +#define HCC2_GSC(p) ((p) & (1 << 8)) +/* true: HC support Virtualization Based Trusted I/O Capability */ +#define HCC2_VTC(p) ((p) & (1 << 9)) diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index 227e513867dd..fd7895b24367 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -957,7 +957,7 @@ static void xhci_dbc_handle_events(struct work_struct *work) /* set fast poll rate if there are pending data transfers */ if (!list_empty(&dbc->eps[BULK_OUT].list_pending) || !list_empty(&dbc->eps[BULK_IN].list_pending)) - poll_interval = 1; + poll_interval = 0; break; default: dev_info(dbc->dev, "stop handling dbc events\n"); diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c index d719c16ea30b..60ed753c85bb 100644 --- a/drivers/usb/host/xhci-dbgtty.c +++ b/drivers/usb/host/xhci-dbgtty.c @@ -110,15 +110,74 @@ static void dbc_start_rx(struct dbc_port *port) } } +/* + * Queue received data to tty buffer and push it. + * + * Returns nr of remaining bytes that didn't fit tty buffer, i.e. 0 if all + * bytes sucessfullt moved. In case of error returns negative errno. + * Call with lock held + */ +static int dbc_rx_push_buffer(struct dbc_port *port, struct dbc_request *req) +{ + char *packet = req->buf; + unsigned int n, size = req->actual; + int count; + + if (!req->actual) + return 0; + + /* if n_read is set then request was partially moved to tty buffer */ + n = port->n_read; + if (n) { + packet += n; + size -= n; + } + + count = tty_insert_flip_string(&port->port, packet, size); + if (count) + tty_flip_buffer_push(&port->port); + if (count != size) { + port->n_read += count; + return size - count; + } + + port->n_read = 0; + return 0; +} + static void dbc_read_complete(struct xhci_dbc *dbc, struct dbc_request *req) { unsigned long flags; struct dbc_port *port = dbc_to_port(dbc); + struct tty_struct *tty; + int untransferred; + + tty = port->port.tty; spin_lock_irqsave(&port->port_lock, flags); + + /* + * Only defer copyig data to tty buffer in case: + * - !list_empty(&port->read_queue), there are older pending data + * - tty is throttled + * - failed to copy all data to buffer, defer remaining part + */ + + if (list_empty(&port->read_queue) && tty && !tty_throttled(tty)) { + untransferred = dbc_rx_push_buffer(port, req); + if (untransferred == 0) { + list_add_tail(&req->list_pool, &port->read_pool); + if (req->status != -ESHUTDOWN) + dbc_start_rx(port); + goto out; + } + } + + /* defer moving data from req to tty buffer to a tasklet */ list_add_tail(&req->list_pool, &port->read_queue); tasklet_schedule(&port->push); +out: spin_unlock_irqrestore(&port->port_lock, flags); } @@ -331,10 +390,10 @@ static void dbc_rx_push(struct tasklet_struct *t) struct dbc_request *req; struct tty_struct *tty; unsigned long flags; - bool do_push = false; bool disconnect = false; struct dbc_port *port = from_tasklet(port, t, push); struct list_head *queue = &port->read_queue; + int untransferred; spin_lock_irqsave(&port->port_lock, flags); tty = port->port.tty; @@ -356,42 +415,15 @@ static void dbc_rx_push(struct tasklet_struct *t) break; } - if (req->actual) { - char *packet = req->buf; - unsigned int n, size = req->actual; - int count; - - n = port->n_read; - if (n) { - packet += n; - size -= n; - } - - count = tty_insert_flip_string(&port->port, packet, - size); - if (count) - do_push = true; - if (count != size) { - port->n_read += count; - break; - } - port->n_read = 0; - } + untransferred = dbc_rx_push_buffer(port, req); + if (untransferred > 0) + break; list_move_tail(&req->list_pool, &port->read_pool); } - if (do_push) - tty_flip_buffer_push(&port->port); - - if (!list_empty(queue) && tty) { - if (!tty_throttled(tty)) { - if (do_push) - tasklet_schedule(&port->push); - else - pr_warn("ttyDBC0: RX not scheduled?\n"); - } - } + if (!list_empty(queue)) + tasklet_schedule(&port->push); if (!disconnect) dbc_start_rx(port); diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c index 4f0c1b96e208..1f5ef174abea 100644 --- a/drivers/usb/host/xhci-debugfs.c +++ b/drivers/usb/host/xhci-debugfs.c @@ -232,16 +232,7 @@ static struct xhci_file_map ring_files[] = { static int xhci_ring_open(struct inode *inode, struct file *file) { - int i; - struct xhci_file_map *f_map; - const char *file_name = file_dentry(file)->d_iname; - - for (i = 0; i < ARRAY_SIZE(ring_files); i++) { - f_map = &ring_files[i]; - - if (strcmp(f_map->name, file_name) == 0) - break; - } + const struct xhci_file_map *f_map = debugfs_get_aux(file); return single_open(file, f_map->show, inode->i_private); } @@ -318,16 +309,7 @@ static struct xhci_file_map context_files[] = { static int xhci_context_open(struct inode *inode, struct file *file) { - int i; - struct xhci_file_map *f_map; - const char *file_name = file_dentry(file)->d_iname; - - for (i = 0; i < ARRAY_SIZE(context_files); i++) { - f_map = &context_files[i]; - - if (strcmp(f_map->name, file_name) == 0) - break; - } + const struct xhci_file_map *f_map = debugfs_get_aux(file); return single_open(file, f_map->show, inode->i_private); } @@ -410,7 +392,8 @@ static void xhci_debugfs_create_files(struct xhci_hcd *xhci, int i; for (i = 0; i < nentries; i++) - debugfs_create_file(files[i].name, 0444, parent, data, fops); + debugfs_create_file_aux(files[i].name, 0444, parent, + data, &files[i], fops); } static struct dentry *xhci_debugfs_create_ring_dir(struct xhci_hcd *xhci, diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 15db90c54a45..92703efda1f7 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -436,7 +436,7 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, goto free_segments; } - xhci_link_rings(xhci, ring, &new_ring); + xhci_link_rings(xhci, &new_ring, ring); trace_xhci_ring_expansion(ring); xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion, "ring expansion succeed, now has %d segments", diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index e6c9006bd568..d85ffa9ffaa7 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -290,7 +290,8 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); - if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) + if ((priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) || + (xhci->quirks & XHCI_SKIP_PHY_INIT)) hcd->skip_phy_initialization = 1; if (priv && (priv->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK)) @@ -329,6 +330,8 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s usb3_hcd->can_do_streams = 1; if (xhci->shared_hcd) { + xhci->shared_hcd->rsrc_start = hcd->rsrc_start; + xhci->shared_hcd->rsrc_len = hcd->rsrc_len; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; @@ -566,6 +569,7 @@ EXPORT_SYMBOL_GPL(xhci_plat_pm_ops); static const struct acpi_device_id usb_xhci_acpi_match[] = { /* XHCI-compliant USB Controller */ { "PNP0D10", }, + { "PNP0D15", }, { } }; MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 4cf5363875c7..965bffce301e 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -55,6 +55,7 @@ #include <linux/jiffies.h> #include <linux/scatterlist.h> #include <linux/slab.h> +#include <linux/string_choices.h> #include <linux/dma-mapping.h> #include "xhci.h" #include "xhci-trace.h" @@ -422,7 +423,8 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci, if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) && !(xhci->xhc_state & XHCI_STATE_DYING)) { xhci->current_cmd = cur_cmd; - xhci_mod_cmd_timer(xhci); + if (cur_cmd) + xhci_mod_cmd_timer(xhci); xhci_ring_cmd_db(xhci); } } @@ -1199,8 +1201,6 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, * Keep retrying until the EP starts and stops again, on * chips where this is known to help. Wait for 100ms. */ - if (!(xhci->quirks & XHCI_NEC_HOST)) - break; if (time_is_before_jiffies(ep->stop_time + msecs_to_jiffies(100))) break; fallthrough; @@ -1651,12 +1651,13 @@ static void xhci_handle_cmd_nec_get_fw(struct xhci_hcd *xhci, NEC_FW_MINOR(le32_to_cpu(event->status))); } -static void xhci_complete_del_and_free_cmd(struct xhci_command *cmd, u32 status) +static void xhci_complete_del_and_free_cmd(struct xhci_command *cmd, u32 comp_code, u32 comp_param) { list_del(&cmd->cmd_list); if (cmd->completion) { - cmd->status = status; + cmd->status = comp_code; + cmd->comp_param = comp_param; complete(cmd->completion); } else { kfree(cmd); @@ -1668,7 +1669,7 @@ void xhci_cleanup_command_queue(struct xhci_hcd *xhci) struct xhci_command *cur_cmd, *tmp_cmd; xhci->current_cmd = NULL; list_for_each_entry_safe(cur_cmd, tmp_cmd, &xhci->cmd_list, cmd_list) - xhci_complete_del_and_free_cmd(cur_cmd, COMP_COMMAND_ABORTED); + xhci_complete_del_and_free_cmd(cur_cmd, COMP_COMMAND_ABORTED, 0); } void xhci_handle_command_timeout(struct work_struct *work) @@ -1753,6 +1754,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_event_cmd *event) { unsigned int slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); + u32 status = le32_to_cpu(event->status); u64 cmd_dma; dma_addr_t cmd_dequeue_dma; u32 cmd_comp_code; @@ -1881,7 +1883,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, } event_handled: - xhci_complete_del_and_free_cmd(cmd, cmd_comp_code); + xhci_complete_del_and_free_cmd(cmd, cmd_comp_code, COMP_PARAM(status)); inc_deq(xhci, xhci->cmd_ring); } @@ -3440,8 +3442,8 @@ static void check_interval(struct urb *urb, struct xhci_ep_ctx *ep_ctx) if (xhci_interval != ep_interval) { dev_dbg_ratelimited(&urb->dev->dev, "Driver uses different interval (%d microframe%s) than xHCI (%d microframe%s)\n", - ep_interval, ep_interval == 1 ? "" : "s", - xhci_interval, xhci_interval == 1 ? "" : "s"); + ep_interval, str_plural(ep_interval), + xhci_interval, str_plural(xhci_interval)); urb->interval = xhci_interval; /* Convert back to frames for LS/FS devices */ if (urb->dev->speed == USB_SPEED_LOW || diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index 06ae193ec874..22dc86fb5254 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -26,6 +26,7 @@ #include <linux/regulator/consumer.h> #include <linux/reset.h> #include <linux/slab.h> +#include <linux/string_choices.h> #include <linux/usb/otg.h> #include <linux/usb/phy.h> #include <linux/usb/role.h> @@ -724,7 +725,7 @@ static void tegra_xusb_mbox_handle(struct tegra_xusb *tegra, if (err < 0) { dev_err(dev, "failed to %s LFPS detection on USB3#%u: %d\n", - enable ? "enable" : "disable", port, err); + str_enable_disable(enable), port, err); rsp.cmd = MBOX_CMD_NAK; } else { rsp.cmd = MBOX_CMD_ACK; @@ -1349,7 +1350,7 @@ static void tegra_xhci_id_work(struct work_struct *work) u32 status; int ret; - dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off"); + dev_dbg(tegra->dev, "host mode %s\n", str_on_off(tegra->host_mode)); mutex_lock(&tegra->lock); @@ -1667,7 +1668,7 @@ static int tegra_xusb_probe(struct platform_device *pdev) goto put_padctl; } - if (!of_property_read_bool(pdev->dev.of_node, "power-domains")) { + if (!of_property_present(pdev->dev.of_node, "power-domains")) { tegra->host_rst = devm_reset_control_get(&pdev->dev, "xusb_host"); if (IS_ERR(tegra->host_rst)) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5ebde8cae4fc..45653114ccd7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/slab.h> +#include <linux/string_choices.h> #include <linux/dmi.h> #include <linux/dma-mapping.h> @@ -4523,7 +4524,7 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, hlpm_addr = ports[port_num]->addr + PORTHLPMC; xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", - enable ? "enable" : "disable", port_num + 1); + str_enable_disable(enable), port_num + 1); if (enable) { /* Host supports BESL timeout instead of HIRD */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 4914f0a10cff..8c164340a2c3 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -529,6 +529,7 @@ struct xhci_command { /* Input context for changing device state */ struct xhci_container_ctx *in_ctx; u32 status; + u32 comp_param; int slot_id; /* If completion is null, no one is waiting on this command * and the structure can be freed after the command completes. @@ -959,6 +960,9 @@ struct xhci_event_cmd { __le32 flags; }; +/* status bitmasks */ +#define COMP_PARAM(p) ((p) & 0xffffff) /* Command Completion Parameter */ + /* Address device - disable SetAddress */ #define TRB_BSR (1<<9) |