diff options
Diffstat (limited to 'drivers/usb/host')
| -rw-r--r-- | drivers/usb/host/fhci-sched.c | 10 | ||||
| -rw-r--r-- | drivers/usb/host/u132-hcd.c | 5 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-dbgcap.c | 7 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-hub.c | 63 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-mtk.c | 19 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-plat.c | 39 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-rcar.c | 1 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 33 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-tegra.c | 68 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-trace.h | 30 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.c | 40 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.h | 54 | 
12 files changed, 270 insertions, 99 deletions
| diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c index 3d12cdd5f999..3235d5307403 100644 --- a/drivers/usb/host/fhci-sched.c +++ b/drivers/usb/host/fhci-sched.c @@ -727,8 +727,7 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)  		}  		ed->speed = (urb->dev->speed == USB_SPEED_LOW) ?  			FHCI_LOW_SPEED : FHCI_FULL_SPEED; -		ed->max_pkt_size = usb_maxpacket(urb->dev, -			urb->pipe, usb_pipeout(urb->pipe)); +		ed->max_pkt_size = usb_endpoint_maxp(&urb->ep->desc);  		urb->ep->hcpriv = ed;  		fhci_dbg(fhci, "new ep speed=%d max_pkt_size=%d\n",  			 ed->speed, ed->max_pkt_size); @@ -768,8 +767,7 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)  		if (urb->transfer_flags & URB_ZERO_PACKET &&  				urb->transfer_buffer_length > 0 &&  				((urb->transfer_buffer_length % -				usb_maxpacket(urb->dev, urb->pipe, -				usb_pipeout(urb->pipe))) == 0)) +				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, @@ -807,8 +805,8 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)  		break;  	case FHCI_TF_CTRL:  		ed->dev_addr = usb_pipedevice(urb->pipe); -		ed->max_pkt_size = usb_maxpacket(urb->dev, urb->pipe, -			usb_pipeout(urb->pipe)); +		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,  			USB_TD_TOGGLE_DATA0, urb->setup_packet, 8, 0, 0, true); diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 934584f0a20a..4a5c9b599c57 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -3203,7 +3203,12 @@ static int __init u132_hcd_init(void)  		return -ENODEV;  	printk(KERN_INFO "driver %s\n", hcd_name);  	workqueue = create_singlethread_workqueue("u132"); +	if (!workqueue) +		return -ENOMEM;  	retval = platform_driver_register(&u132_platform_driver); +	if (retval) +		destroy_workqueue(workqueue); +  	return retval;  } diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index c78be578abb0..52e32644a4b2 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -421,8 +421,6 @@ static int xhci_dbc_mem_init(struct xhci_hcd *xhci, gfp_t flags)  	string_length = xhci_dbc_populate_strings(dbc->string);  	xhci_dbc_init_contexts(xhci, string_length); -	mmiowb(); -  	xhci_dbc_eps_init(xhci);  	dbc->state = DS_INITIALIZED; @@ -516,7 +514,6 @@ static int xhci_do_dbc_stop(struct xhci_hcd *xhci)  		return -1;  	writel(0, &dbc->regs->control); -	xhci_dbc_mem_cleanup(xhci);  	dbc->state = DS_DISABLED;  	return 0; @@ -562,8 +559,10 @@ static void xhci_dbc_stop(struct xhci_hcd *xhci)  	ret = xhci_do_dbc_stop(xhci);  	spin_unlock_irqrestore(&dbc->lock, flags); -	if (!ret) +	if (!ret) { +		xhci_dbc_mem_cleanup(xhci);  		pm_runtime_put_sync(xhci_to_hcd(xhci)->self.controller); +	}  }  static void diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index e2eece693655..3abe70ff1b1e 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -487,8 +487,8 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,  	/* Write 1 to disable the port */  	writel(port_status | PORT_PE, addr);  	port_status = readl(addr); -	xhci_dbg(xhci, "disable port, actual port %d status  = 0x%x\n", -			wIndex, port_status); +	xhci_dbg(xhci, "disable port %d-%d, portsc: 0x%x\n", +		 hcd->self.busnum, wIndex + 1, port_status);  }  static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, @@ -537,8 +537,9 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,  	/* Change bits are all write 1 to clear */  	writel(port_status | status, addr);  	port_status = readl(addr); -	xhci_dbg(xhci, "clear port %s change, actual port %d status  = 0x%x\n", -			port_change_bit, wIndex, port_status); + +	xhci_dbg(xhci, "clear port%d %s change, portsc: 0x%x\n", +		 wIndex + 1, port_change_bit, port_status);  }  struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd) @@ -565,13 +566,16 @@ static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,  	rhub = xhci_get_rhub(hcd);  	port = rhub->ports[index];  	temp = readl(port->addr); + +	xhci_dbg(xhci, "set port power %d-%d %s, portsc: 0x%x\n", +		 hcd->self.busnum, index + 1, on ? "ON" : "OFF", temp); +  	temp = xhci_port_state_to_neutral(temp); +  	if (on) {  		/* Power on */  		writel(temp | PORT_POWER, port->addr); -		temp = readl(port->addr); -		xhci_dbg(xhci, "set port power, actual port %d status  = 0x%x\n", -						index, temp); +		readl(port->addr);  	} else {  		/* Power off */  		writel(temp & ~PORT_POWER, port->addr); @@ -666,12 +670,17 @@ void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,  			 u32 link_state)  {  	u32 temp; +	u32 portsc; -	temp = readl(port->addr); -	temp = xhci_port_state_to_neutral(temp); +	portsc = readl(port->addr); +	temp = xhci_port_state_to_neutral(portsc);  	temp &= ~PORT_PLS_MASK;  	temp |= PORT_LINK_STROBE | link_state;  	writel(temp, port->addr); + +	xhci_dbg(xhci, "Set port %d-%d link state, portsc: 0x%x, write 0x%x", +		 port->rhub->hcd->self.busnum, port->hcd_portnum + 1, +		 portsc, temp);  }  static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, @@ -840,7 +849,9 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,  	} else if (time_after_eq(jiffies, bus_state->resume_done[wIndex])) {  		int time_left; -		xhci_dbg(xhci, "Resume USB2 port %d\n", wIndex + 1); +		xhci_dbg(xhci, "resume USB2 port %d-%d\n", +			 hcd->self.busnum, wIndex + 1); +  		bus_state->resume_done[wIndex] = 0;  		clear_bit(wIndex, &bus_state->resuming_ports); @@ -867,9 +878,8 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,  		} else {  			int port_status = readl(port->addr); -			xhci_warn(xhci, "Port resume %i msec timed out, portsc = 0x%x\n", -				  XHCI_MAX_REXIT_TIMEOUT_MS, -				  port_status); +			xhci_warn(xhci, "Port resume timed out, port %d-%d: 0x%x\n", +				  hcd->self.busnum, wIndex + 1, port_status);  			*status |= USB_PORT_STAT_SUSPEND;  			clear_bit(wIndex, &bus_state->rexit_ports);  		} @@ -1124,9 +1134,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  		if (status == 0xffffffff)  			goto error; -		xhci_dbg(xhci, "get port status, actual port %d status  = 0x%x\n", -				wIndex, temp); -		xhci_dbg(xhci, "Get port status returned 0x%x\n", status); +		xhci_dbg(xhci, "Get port status %d-%d read: 0x%x, return 0x%x", +			 hcd->self.busnum, wIndex + 1, temp, status);  		put_unaligned(cpu_to_le32(status), (__le32 *) buf);  		/* if USB 3.1 extended port status return additional 4 bytes */ @@ -1182,7 +1191,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  			temp = readl(ports[wIndex]->addr);  			if ((temp & PORT_PE) == 0 || (temp & PORT_RESET)  				|| (temp & PORT_PLS_MASK) >= XDEV_U3) { -				xhci_warn(xhci, "USB core suspending device not in U0/U1/U2.\n"); +				xhci_warn(xhci, "USB core suspending port %d-%d not in U0/U1/U2\n", +					  hcd->self.busnum, wIndex + 1);  				goto error;  			} @@ -1545,20 +1555,25 @@ int xhci_bus_suspend(struct usb_hcd *hcd)  	port_index = max_ports;  	while (port_index--) {  		u32 t1, t2; - +		int retries = 10; +retry:  		t1 = readl(ports[port_index]->addr);  		t2 = xhci_port_state_to_neutral(t1);  		portsc_buf[port_index] = 0; -		/* Bail out if a USB3 port has a new device in link training */ -		if ((hcd->speed >= HCD_USB3) && +		/* +		 * Give a USB3 port in link training time to finish, but don't +		 * prevent suspend as port might be stuck +		 */ +		if ((hcd->speed >= HCD_USB3) && retries-- &&  		    (t1 & PORT_PLS_MASK) == XDEV_POLLING) { -			bus_state->bus_suspended = 0;  			spin_unlock_irqrestore(&xhci->lock, flags); -			xhci_dbg(xhci, "Bus suspend bailout, port in polling\n"); -			return -EBUSY; +			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); +			goto retry;  		} -  		/* suspend ports in U0, or bail out for new connect changes */  		if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) {  			if ((t1 & PORT_CSC) && wake_enabled) { diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 60987c787e44..026fe18972d3 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -206,19 +206,6 @@ static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk)  	return xhci_mtk_host_enable(mtk);  } -/* ignore the error if the clock does not exist */ -static struct clk *optional_clk_get(struct device *dev, const char *id) -{ -	struct clk *opt_clk; - -	opt_clk = devm_clk_get(dev, id); -	/* ignore error number except EPROBE_DEFER */ -	if (IS_ERR(opt_clk) && (PTR_ERR(opt_clk) != -EPROBE_DEFER)) -		opt_clk = NULL; - -	return opt_clk; -} -  static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk)  {  	struct device *dev = mtk->dev; @@ -229,15 +216,15 @@ static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk)  		return PTR_ERR(mtk->sys_clk);  	} -	mtk->ref_clk = optional_clk_get(dev, "ref_ck"); +	mtk->ref_clk = devm_clk_get_optional(dev, "ref_ck");  	if (IS_ERR(mtk->ref_clk))  		return PTR_ERR(mtk->ref_clk); -	mtk->mcu_clk = optional_clk_get(dev, "mcu_ck"); +	mtk->mcu_clk = devm_clk_get_optional(dev, "mcu_ck");  	if (IS_ERR(mtk->mcu_clk))  		return PTR_ERR(mtk->mcu_clk); -	mtk->dma_clk = optional_clk_get(dev, "dma_ck"); +	mtk->dma_clk = devm_clk_get_optional(dev, "dma_ck");  	return PTR_ERR_OR_ZERO(mtk->dma_clk);  } diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 0ac4ec975547..998241f5fce3 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -165,8 +165,6 @@ static int xhci_plat_probe(struct platform_device *pdev)  	struct xhci_hcd		*xhci;  	struct resource         *res;  	struct usb_hcd		*hcd; -	struct clk              *clk; -	struct clk              *reg_clk;  	int			ret;  	int			irq; @@ -235,31 +233,32 @@ static int xhci_plat_probe(struct platform_device *pdev)  	hcd->rsrc_start = res->start;  	hcd->rsrc_len = resource_size(res); +	xhci = hcd_to_xhci(hcd); +  	/*  	 * Not all platforms have clks so it is not an error if the  	 * clock do not exist.  	 */ -	reg_clk = devm_clk_get(&pdev->dev, "reg"); -	if (!IS_ERR(reg_clk)) { -		ret = clk_prepare_enable(reg_clk); -		if (ret) -			goto put_hcd; -	} else if (PTR_ERR(reg_clk) == -EPROBE_DEFER) { -		ret = -EPROBE_DEFER; +	xhci->reg_clk = devm_clk_get_optional(&pdev->dev, "reg"); +	if (IS_ERR(xhci->reg_clk)) { +		ret = PTR_ERR(xhci->reg_clk);  		goto put_hcd;  	} -	clk = devm_clk_get(&pdev->dev, NULL); -	if (!IS_ERR(clk)) { -		ret = clk_prepare_enable(clk); -		if (ret) -			goto disable_reg_clk; -	} else if (PTR_ERR(clk) == -EPROBE_DEFER) { -		ret = -EPROBE_DEFER; +	ret = clk_prepare_enable(xhci->reg_clk); +	if (ret) +		goto put_hcd; + +	xhci->clk = devm_clk_get_optional(&pdev->dev, NULL); +	if (IS_ERR(xhci->clk)) { +		ret = PTR_ERR(xhci->clk);  		goto disable_reg_clk;  	} -	xhci = hcd_to_xhci(hcd); +	ret = clk_prepare_enable(xhci->clk); +	if (ret) +		goto disable_reg_clk; +  	priv_match = of_device_get_match_data(&pdev->dev);  	if (priv_match) {  		struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); @@ -271,8 +270,6 @@ static int xhci_plat_probe(struct platform_device *pdev)  	device_wakeup_enable(hcd->self.controller); -	xhci->clk = clk; -	xhci->reg_clk = reg_clk;  	xhci->main_hcd = hcd;  	xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,  			dev_name(&pdev->dev), hcd); @@ -348,10 +345,10 @@ put_usb3_hcd:  	usb_put_hcd(xhci->shared_hcd);  disable_clk: -	clk_disable_unprepare(clk); +	clk_disable_unprepare(xhci->clk);  disable_reg_clk: -	clk_disable_unprepare(reg_clk); +	clk_disable_unprepare(xhci->reg_clk);  put_hcd:  	usb_put_hcd(hcd); diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index a6e463715779..671bce18782c 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -246,6 +246,7 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd)  	if (!xhci_rcar_wait_for_pll_active(hcd))  		return -ETIMEDOUT; +	xhci->quirks |= XHCI_TRUST_TX_LENGTH;  	return xhci_rcar_download_firmware(hcd);  } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 40fa25c4d041..fed3385aeac0 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1569,18 +1569,19 @@ static void handle_port_status(struct xhci_hcd *xhci,  			  "WARN: xHC returned failed port status event\n");  	port_id = GET_PORT_ID(le32_to_cpu(event->generic.field[0])); -	xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id); -  	max_ports = HCS_MAX_PORTS(xhci->hcs_params1); +  	if ((port_id <= 0) || (port_id > max_ports)) { -		xhci_warn(xhci, "Invalid port id %d\n", port_id); +		xhci_warn(xhci, "Port change event with invalid port ID %d\n", +			  port_id);  		inc_deq(xhci, xhci->event_ring);  		return;  	}  	port = &xhci->hw_ports[port_id - 1];  	if (!port || !port->rhub || port->hcd_portnum == DUPLICATE_ENTRY) { -		xhci_warn(xhci, "Event for invalid port %u\n", port_id); +		xhci_warn(xhci, "Port change event, no port for port ID %u\n", +			  port_id);  		bogus_port_status = true;  		goto cleanup;  	} @@ -1597,6 +1598,9 @@ static void handle_port_status(struct xhci_hcd *xhci,  	hcd_portnum = port->hcd_portnum;  	portsc = readl(port->addr); +	xhci_dbg(xhci, "Port change event, %d-%d, id %d, portsc: 0x%x\n", +		 hcd->self.busnum, hcd_portnum + 1, port_id, portsc); +  	trace_xhci_handle_port_status(hcd_portnum, portsc);  	if (hcd->state == HC_STATE_SUSPENDED) { @@ -1647,10 +1651,13 @@ static void handle_port_status(struct xhci_hcd *xhci,  		}  	} -	if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_U0 && -			DEV_SUPERSPEED_ANY(portsc)) { +	if ((portsc & PORT_PLC) && +	    DEV_SUPERSPEED_ANY(portsc) && +	    ((portsc & PORT_PLS_MASK) == XDEV_U0 || +	     (portsc & PORT_PLS_MASK) == XDEV_U1 || +	     (portsc & PORT_PLS_MASK) == XDEV_U2)) {  		xhci_dbg(xhci, "resume SS port %d finished\n", port_id); -		/* We've just brought the device into U0 through either the +		/* We've just brought the device into U0/1/2 through either the  		 * Resume state after a device remote wakeup, or through the  		 * U3Exit state after a host-initiated resume.  If it's a device  		 * initiated remote wake, don't pass up the link state change, @@ -3272,6 +3279,12 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  			field |= TRB_IOC;  			more_trbs_coming = false;  			td->last_trb = ring->enqueue; + +			if (xhci_urb_suitable_for_idt(urb)) { +				memcpy(&send_addr, urb->transfer_buffer, +				       trb_buff_len); +				field |= TRB_IDT; +			}  		}  		/* Only set interrupt on short packet for IN endpoints */ @@ -3411,6 +3424,12 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  	if (urb->transfer_buffer_length > 0) {  		u32 length_field, remainder; +		if (xhci_urb_suitable_for_idt(urb)) { +			memcpy(&urb->transfer_dma, urb->transfer_buffer, +			       urb->transfer_buffer_length); +			field |= TRB_IDT; +		} +  		remainder = xhci_td_remainder(xhci, 0,  				urb->transfer_buffer_length,  				urb->transfer_buffer_length, diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index efb0cad8710e..294158113d62 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -161,6 +161,7 @@ struct tegra_xusb_soc {  	} ports;  	bool scale_ss_clock; +	bool has_ipfs;  };  struct tegra_xusb { @@ -637,16 +638,18 @@ static irqreturn_t tegra_xusb_mbox_thread(int irq, void *data)  	return IRQ_HANDLED;  } -static void tegra_xusb_ipfs_config(struct tegra_xusb *tegra, -				   struct resource *regs) +static void tegra_xusb_config(struct tegra_xusb *tegra, +			      struct resource *regs)  {  	u32 value; -	value = ipfs_readl(tegra, IPFS_XUSB_HOST_CONFIGURATION_0); -	value |= IPFS_EN_FPCI; -	ipfs_writel(tegra, value, IPFS_XUSB_HOST_CONFIGURATION_0); +	if (tegra->soc->has_ipfs) { +		value = ipfs_readl(tegra, IPFS_XUSB_HOST_CONFIGURATION_0); +		value |= IPFS_EN_FPCI; +		ipfs_writel(tegra, value, IPFS_XUSB_HOST_CONFIGURATION_0); -	usleep_range(10, 20); +		usleep_range(10, 20); +	}  	/* Program BAR0 space */  	value = fpci_readl(tegra, XUSB_CFG_4); @@ -661,13 +664,15 @@ static void tegra_xusb_ipfs_config(struct tegra_xusb *tegra,  	value |= XUSB_IO_SPACE_EN | XUSB_MEM_SPACE_EN | XUSB_BUS_MASTER_EN;  	fpci_writel(tegra, value, XUSB_CFG_1); -	/* Enable interrupt assertion */ -	value = ipfs_readl(tegra, IPFS_XUSB_HOST_INTR_MASK_0); -	value |= IPFS_IP_INT_MASK; -	ipfs_writel(tegra, value, IPFS_XUSB_HOST_INTR_MASK_0); +	if (tegra->soc->has_ipfs) { +		/* Enable interrupt assertion */ +		value = ipfs_readl(tegra, IPFS_XUSB_HOST_INTR_MASK_0); +		value |= IPFS_IP_INT_MASK; +		ipfs_writel(tegra, value, IPFS_XUSB_HOST_INTR_MASK_0); -	/* Set hysteresis */ -	ipfs_writel(tegra, 0x80, IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0); +		/* Set hysteresis */ +		ipfs_writel(tegra, 0x80, IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0); +	}  }  static int tegra_xusb_clk_enable(struct tegra_xusb *tegra) @@ -1015,10 +1020,12 @@ static int tegra_xusb_probe(struct platform_device *pdev)  	if (IS_ERR(tegra->fpci_base))  		return PTR_ERR(tegra->fpci_base); -	res = platform_get_resource(pdev, IORESOURCE_MEM, 2); -	tegra->ipfs_base = devm_ioremap_resource(&pdev->dev, res); -	if (IS_ERR(tegra->ipfs_base)) -		return PTR_ERR(tegra->ipfs_base); +	if (tegra->soc->has_ipfs) { +		res = platform_get_resource(pdev, IORESOURCE_MEM, 2); +		tegra->ipfs_base = devm_ioremap_resource(&pdev->dev, res); +		if (IS_ERR(tegra->ipfs_base)) +			return PTR_ERR(tegra->ipfs_base); +	}  	tegra->xhci_irq = platform_get_irq(pdev, 0);  	if (tegra->xhci_irq < 0) @@ -1208,7 +1215,7 @@ static int tegra_xusb_probe(struct platform_device *pdev)  		goto disable_rpm;  	} -	tegra_xusb_ipfs_config(tegra, regs); +	tegra_xusb_config(tegra, regs);  	err = tegra_xusb_load_firmware(tegra);  	if (err < 0) { @@ -1380,6 +1387,7 @@ static const struct tegra_xusb_soc tegra124_soc = {  		.usb3 = { .offset = 0, .count = 2, },  	},  	.scale_ss_clock = true, +	.has_ipfs = true,  };  MODULE_FIRMWARE("nvidia/tegra124/xusb.bin"); @@ -1411,12 +1419,38 @@ static const struct tegra_xusb_soc tegra210_soc = {  		.usb3 = { .offset = 0, .count = 4, },  	},  	.scale_ss_clock = false, +	.has_ipfs = true,  };  MODULE_FIRMWARE("nvidia/tegra210/xusb.bin"); +static const char * const tegra186_supply_names[] = { +}; + +static const struct tegra_xusb_phy_type tegra186_phy_types[] = { +	{ .name = "usb3", .num = 3, }, +	{ .name = "usb2", .num = 3, }, +	{ .name = "hsic", .num = 1, }, +}; + +static const struct tegra_xusb_soc tegra186_soc = { +	.firmware = "nvidia/tegra186/xusb.bin", +	.supply_names = tegra186_supply_names, +	.num_supplies = ARRAY_SIZE(tegra186_supply_names), +	.phy_types = tegra186_phy_types, +	.num_types = ARRAY_SIZE(tegra186_phy_types), +	.ports = { +		.usb3 = { .offset = 0, .count = 3, }, +		.usb2 = { .offset = 3, .count = 3, }, +		.hsic = { .offset = 6, .count = 1, }, +	}, +	.scale_ss_clock = false, +	.has_ipfs = false, +}; +  static const struct of_device_id tegra_xusb_of_match[] = {  	{ .compatible = "nvidia,tegra124-xusb", .data = &tegra124_soc },  	{ .compatible = "nvidia,tegra210-xusb", .data = &tegra210_soc }, +	{ .compatible = "nvidia,tegra186-xusb", .data = &tegra186_soc },  	{ },  };  MODULE_DEVICE_TABLE(of, tegra_xusb_of_match); diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index 88b427434bd8..052a269d86f2 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h @@ -366,6 +366,11 @@ DEFINE_EVENT(xhci_log_ep_ctx, xhci_handle_cmd_config_ep,  	TP_ARGS(ctx)  ); +DEFINE_EVENT(xhci_log_ep_ctx, xhci_add_endpoint, +	TP_PROTO(struct xhci_ep_ctx *ctx), +	TP_ARGS(ctx) +); +  DECLARE_EVENT_CLASS(xhci_log_slot_ctx,  	TP_PROTO(struct xhci_slot_ctx *ctx),  	TP_ARGS(ctx), @@ -432,6 +437,31 @@ DEFINE_EVENT(xhci_log_slot_ctx, xhci_configure_endpoint,  	TP_ARGS(ctx)  ); +DECLARE_EVENT_CLASS(xhci_log_ctrl_ctx, +	TP_PROTO(struct xhci_input_control_ctx *ctrl_ctx), +	TP_ARGS(ctrl_ctx), +	TP_STRUCT__entry( +		__field(u32, drop) +		__field(u32, add) +	), +	TP_fast_assign( +		__entry->drop = le32_to_cpu(ctrl_ctx->drop_flags); +		__entry->add = le32_to_cpu(ctrl_ctx->add_flags); +	), +	TP_printk("%s", xhci_decode_ctrl_ctx(__entry->drop, __entry->add) +	) +); + +DEFINE_EVENT(xhci_log_ctrl_ctx, xhci_address_ctrl_ctx, +	TP_PROTO(struct xhci_input_control_ctx *ctrl_ctx), +	TP_ARGS(ctrl_ctx) +); + +DEFINE_EVENT(xhci_log_ctrl_ctx, xhci_configure_endpoint_ctrl_ctx, +	TP_PROTO(struct xhci_input_control_ctx *ctrl_ctx), +	TP_ARGS(ctrl_ctx) +); +  DECLARE_EVENT_CLASS(xhci_log_ring,  	TP_PROTO(struct xhci_ring *ring),  	TP_ARGS(ring), diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7fa58c99f126..a9bb796794e3 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -893,7 +893,7 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)  	struct xhci_port **ports;  	int port_index;  	unsigned long flags; -	u32 t1, t2; +	u32 t1, t2, portsc;  	spin_lock_irqsave(&xhci->lock, flags); @@ -902,10 +902,15 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)  	ports = xhci->usb3_rhub.ports;  	while (port_index--) {  		t1 = readl(ports[port_index]->addr); +		portsc = t1;  		t1 = xhci_port_state_to_neutral(t1);  		t2 = t1 & ~PORT_WAKE_BITS; -		if (t1 != t2) +		if (t1 != t2) {  			writel(t2, ports[port_index]->addr); +			xhci_dbg(xhci, "disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n", +				 xhci->usb3_rhub.hcd->self.busnum, +				 port_index + 1, portsc, t2); +		}  	}  	/* disable usb2 ports Wake bits */ @@ -913,12 +918,16 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)  	ports = xhci->usb2_rhub.ports;  	while (port_index--) {  		t1 = readl(ports[port_index]->addr); +		portsc = t1;  		t1 = xhci_port_state_to_neutral(t1);  		t2 = t1 & ~PORT_WAKE_BITS; -		if (t1 != t2) +		if (t1 != t2) {  			writel(t2, ports[port_index]->addr); +			xhci_dbg(xhci, "disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n", +				 xhci->usb2_rhub.hcd->self.busnum, +				 port_index + 1, portsc, t2); +		}  	} -  	spin_unlock_irqrestore(&xhci->lock, flags);  } @@ -1238,6 +1247,21 @@ EXPORT_SYMBOL_GPL(xhci_resume);  /*-------------------------------------------------------------------------*/ +/* + * Bypass the DMA mapping if URB is suitable for Immediate Transfer (IDT), + * we'll copy the actual data into the TRB address register. This is limited to + * transfers up to 8 bytes on output endpoints of any kind with wMaxPacketSize + * >= 8 bytes. If suitable for IDT only one Transfer TRB per TD is allowed. + */ +static int xhci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, +				gfp_t mem_flags) +{ +	if (xhci_urb_suitable_for_idt(urb)) +		return 0; + +	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 @@ -1783,6 +1807,7 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,  	struct xhci_container_ctx *in_ctx;  	unsigned int ep_index;  	struct xhci_input_control_ctx *ctrl_ctx; +	struct xhci_ep_ctx *ep_ctx;  	u32 added_ctxs;  	u32 new_add_flags, new_drop_flags;  	struct xhci_virt_device *virt_dev; @@ -1873,6 +1898,9 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,  	/* Store the usb_device pointer for later use */  	ep->hcpriv = udev; +	ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); +	trace_xhci_add_endpoint(ep_ctx); +  	xhci_debugfs_create_endpoint(xhci, virt_dev, ep_index);  	xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n", @@ -2747,6 +2775,8 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,  	}  	slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx); + +	trace_xhci_configure_endpoint_ctrl_ctx(ctrl_ctx);  	trace_xhci_configure_endpoint(slot_ctx);  	if (!ctx_change) @@ -4012,6 +4042,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,  	trace_xhci_address_ctx(xhci, virt_dev->in_ctx,  				le32_to_cpu(slot_ctx->dev_info) >> 27); +	trace_xhci_address_ctrl_ctx(ctrl_ctx);  	spin_lock_irqsave(&xhci->lock, flags);  	trace_xhci_setup_device(virt_dev);  	ret = xhci_queue_address_device(xhci, command, virt_dev->in_ctx->dma, @@ -5154,6 +5185,7 @@ static const struct hc_driver xhci_hc_driver = {  	/*  	 * managing i/o requests and associated device resources  	 */ +	.map_urb_for_dma =      xhci_map_urb_for_dma,  	.urb_enqueue =		xhci_urb_enqueue,  	.urb_dequeue =		xhci_urb_dequeue,  	.alloc_dev =		xhci_alloc_dev, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 652dc36e3012..a450a99e90eb 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -452,6 +452,14 @@ struct xhci_op_regs {   */  #define XHCI_DEFAULT_BESL	4 +/* + * USB3 specification define a 360ms tPollingLFPSTiemout for USB3 ports + * to complete link training. usually link trainig completes much faster + * so check status 10 times with 36ms sleep in places we need to wait for + * polling to complete. + */ +#define XHCI_PORT_POLLING_LFPS_TIME  36 +  /**   * struct xhci_intr_reg - Interrupt Register Set   * @irq_pending:	IMAN - Interrupt Management Register.  Used to enable @@ -1295,6 +1303,8 @@ enum xhci_setup_dev {  #define TRB_IOC			(1<<5)  /* The buffer pointer contains immediate data */  #define TRB_IDT			(1<<6) +/* TDs smaller than this might use IDT */ +#define TRB_IDT_MAX_SIZE	8  /* Block Event Interrupt */  #define	TRB_BEI			(1<<9) @@ -2141,6 +2151,21 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,  					urb->stream_id);  } +/* + * TODO: As per spec Isochronous IDT transmissions are supported. We bypass + * them anyways as we where unable to find a device that matches the + * constraints. + */ +static inline bool xhci_urb_suitable_for_idt(struct urb *urb) +{ +	if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) && +	    usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE && +	    urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE) +		return true; + +	return false; +} +  static inline char *xhci_slot_state_string(u32 state)  {  	switch (state) { @@ -2376,6 +2401,35 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,  	return str;  } +static inline const char *xhci_decode_ctrl_ctx(unsigned long drop, +					       unsigned long add) +{ +	static char	str[1024]; +	unsigned int	bit; +	int		ret = 0; + +	if (drop) { +		ret = sprintf(str, "Drop:"); +		for_each_set_bit(bit, &drop, 32) +			ret += sprintf(str + ret, " %d%s", +				       bit / 2, +				       bit % 2 ? "in":"out"); +		ret += sprintf(str + ret, ", "); +	} + +	if (add) { +		ret += sprintf(str + ret, "Add:%s%s", +			       (add & SLOT_FLAG) ? " slot":"", +			       (add & EP0_FLAG) ? " ep0":""); +		add &= ~(SLOT_FLAG | EP0_FLAG); +		for_each_set_bit(bit, &add, 32) +			ret += sprintf(str + ret, " %d%s", +				       bit / 2, +				       bit % 2 ? "in":"out"); +	} +	return str; +} +  static inline const char *xhci_decode_slot_context(u32 info, u32 info2,  		u32 tt_info, u32 state)  { |