diff options
Diffstat (limited to 'drivers/usb/host')
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 23 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-pci.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/ehci.h | 1 | ||||
| -rw-r--r-- | drivers/usb/host/xen-hcd.c | 65 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-hub.c | 2 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-mtk-sch.c | 90 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-mtk.h | 2 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-pci.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 1 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-tegra.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.c | 11 | 
11 files changed, 81 insertions, 126 deletions
| diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 3d82e0b853be..684164fa9716 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1103,6 +1103,26 @@ static void ehci_remove_device(struct usb_hcd *hcd, struct usb_device *udev)  #ifdef	CONFIG_PM +/* Clear wakeup signal locked in zhaoxin platform when device plug in. */ +static void ehci_zx_wakeup_clear(struct ehci_hcd *ehci) +{ +	u32 __iomem	*reg = &ehci->regs->port_status[4]; +	u32 		t1 = ehci_readl(ehci, reg); + +	t1 &= (u32)~0xf0000; +	t1 |= PORT_TEST_FORCE; +	ehci_writel(ehci, t1, reg); +	t1 = ehci_readl(ehci, reg); +	msleep(1); +	t1 &= (u32)~0xf0000; +	ehci_writel(ehci, t1, reg); +	ehci_readl(ehci, reg); +	msleep(1); +	t1 = ehci_readl(ehci, reg); +	ehci_writel(ehci, t1 | PORT_CSC, reg); +	ehci_readl(ehci, reg); +} +  /* suspend/resume, section 4.3 */  /* These routines handle the generic parts of controller suspend/resume */ @@ -1154,6 +1174,9 @@ int ehci_resume(struct usb_hcd *hcd, bool force_reset)  	if (ehci->shutdown)  		return 0;		/* Controller is dead */ +	if (ehci->zx_wakeup_clear_needed) +		ehci_zx_wakeup_clear(ehci); +  	/*  	 * If CF is still set and reset isn't forced  	 * then we maintained suspend power. diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 638f03b89739..9937c5a7efc2 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -231,6 +231,10 @@ static int ehci_pci_setup(struct usb_hcd *hcd)  			ehci->is_aspeed = 1;  		}  		break; +	case PCI_VENDOR_ID_ZHAOXIN: +		if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x90) +			ehci->zx_wakeup_clear_needed = 1; +		break;  	}  	/* optional debug port, normally in the first BAR */ diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index fdd073cc053b..ad3f13a3eaf1 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -220,6 +220,7 @@ struct ehci_hcd {			/* one per controller */  	unsigned		imx28_write_fix:1; /* For Freescale i.MX28 */  	unsigned		spurious_oc:1;  	unsigned		is_aspeed:1; +	unsigned		zx_wakeup_clear_needed:1;  	/* required for usb32 quirk */  	#define OHCI_CTRL_HCFS          (3 << 6) diff --git a/drivers/usb/host/xen-hcd.c b/drivers/usb/host/xen-hcd.c index 3e487baf8422..de1b09158318 100644 --- a/drivers/usb/host/xen-hcd.c +++ b/drivers/usb/host/xen-hcd.c @@ -87,8 +87,6 @@ struct xenhcd_info {  	bool error;  }; -#define GRANT_INVALID_REF 0 -  #define XENHCD_RING_JIFFIES (HZ/200)  #define XENHCD_SCAN_JIFFIES 1 @@ -1100,19 +1098,10 @@ static void xenhcd_destroy_rings(struct xenhcd_info *info)  		unbind_from_irqhandler(info->irq, info);  	info->irq = 0; -	if (info->urb_ring_ref != GRANT_INVALID_REF) { -		gnttab_end_foreign_access(info->urb_ring_ref, -					  (unsigned long)info->urb_ring.sring); -		info->urb_ring_ref = GRANT_INVALID_REF; -	} -	info->urb_ring.sring = NULL; - -	if (info->conn_ring_ref != GRANT_INVALID_REF) { -		gnttab_end_foreign_access(info->conn_ring_ref, -					  (unsigned long)info->conn_ring.sring); -		info->conn_ring_ref = GRANT_INVALID_REF; -	} -	info->conn_ring.sring = NULL; +	xenbus_teardown_ring((void **)&info->urb_ring.sring, 1, +			     &info->urb_ring_ref); +	xenbus_teardown_ring((void **)&info->conn_ring.sring, 1, +			     &info->conn_ring_ref);  }  static int xenhcd_setup_rings(struct xenbus_device *dev, @@ -1120,46 +1109,24 @@ static int xenhcd_setup_rings(struct xenbus_device *dev,  {  	struct xenusb_urb_sring *urb_sring;  	struct xenusb_conn_sring *conn_sring; -	grant_ref_t gref;  	int err; -	info->urb_ring_ref = GRANT_INVALID_REF; -	info->conn_ring_ref = GRANT_INVALID_REF; - -	urb_sring = (struct xenusb_urb_sring *)get_zeroed_page( -							GFP_NOIO | __GFP_HIGH); -	if (!urb_sring) { -		xenbus_dev_fatal(dev, -ENOMEM, "allocating urb ring"); -		return -ENOMEM; -	} -	SHARED_RING_INIT(urb_sring); -	FRONT_RING_INIT(&info->urb_ring, urb_sring, PAGE_SIZE); - -	err = xenbus_grant_ring(dev, urb_sring, 1, &gref); -	if (err < 0) { -		free_page((unsigned long)urb_sring); -		info->urb_ring.sring = NULL; -		goto fail; -	} -	info->urb_ring_ref = gref; - -	conn_sring = (struct xenusb_conn_sring *)get_zeroed_page( -							GFP_NOIO | __GFP_HIGH); -	if (!conn_sring) { -		xenbus_dev_fatal(dev, -ENOMEM, "allocating conn ring"); -		err = -ENOMEM; -		goto fail; +	info->conn_ring_ref = INVALID_GRANT_REF; +	err = xenbus_setup_ring(dev, GFP_NOIO | __GFP_HIGH, +				(void **)&urb_sring, 1, &info->urb_ring_ref); +	if (err) { +		xenbus_dev_fatal(dev, err, "allocating urb ring"); +		return err;  	} -	SHARED_RING_INIT(conn_sring); -	FRONT_RING_INIT(&info->conn_ring, conn_sring, PAGE_SIZE); +	XEN_FRONT_RING_INIT(&info->urb_ring, urb_sring, PAGE_SIZE); -	err = xenbus_grant_ring(dev, conn_sring, 1, &gref); -	if (err < 0) { -		free_page((unsigned long)conn_sring); -		info->conn_ring.sring = NULL; +	err = xenbus_setup_ring(dev, GFP_NOIO | __GFP_HIGH, +				(void **)&conn_sring, 1, &info->conn_ring_ref); +	if (err) { +		xenbus_dev_fatal(dev, err, "allocating conn ring");  		goto fail;  	} -	info->conn_ring_ref = gref; +	XEN_FRONT_RING_INIT(&info->conn_ring, conn_sring, PAGE_SIZE);  	err = xenbus_alloc_evtchn(dev, &info->evtchn);  	if (err) { diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 1e7dc130c39a..f65f1ba2b592 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1434,7 +1434,7 @@ 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))) +								 msecs_to_jiffies(500)))  					xhci_dbg(xhci, "missing U0 port change event for port %d-%d\n",  						 hcd->self.busnum, wIndex + 1);  				spin_lock_irqsave(&xhci->lock, flags); diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c index f3139ce7b0a9..06a6b19acaae 100644 --- a/drivers/usb/host/xhci-mtk-sch.c +++ b/drivers/usb/host/xhci-mtk-sch.c @@ -19,11 +19,6 @@  #define HS_BW_BOUNDARY	6144  /* usb2 spec section11.18.1: at most 188 FS bytes per microframe */  #define FS_PAYLOAD_MAX 188 -/* - * max number of microframes for split transfer, - * for fs isoc in : 1 ss + 1 idle + 7 cs - */ -#define TT_MICROFRAMES_MAX 9  #define DBG_BUF_EN	64 @@ -242,28 +237,17 @@ static void drop_tt(struct usb_device *udev)  static struct mu3h_sch_ep_info *  create_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev, -	      struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx) +	      struct usb_host_endpoint *ep)  {  	struct mu3h_sch_ep_info *sch_ep;  	struct mu3h_sch_bw_info *bw_info;  	struct mu3h_sch_tt *tt = NULL; -	u32 len_bw_budget_table;  	bw_info = get_bw_info(mtk, udev, ep);  	if (!bw_info)  		return ERR_PTR(-ENODEV); -	if (is_fs_or_ls(udev->speed)) -		len_bw_budget_table = TT_MICROFRAMES_MAX; -	else if ((udev->speed >= USB_SPEED_SUPER) -			&& usb_endpoint_xfer_isoc(&ep->desc)) -		len_bw_budget_table = get_esit(ep_ctx); -	else -		len_bw_budget_table = 1; - -	sch_ep = kzalloc(struct_size(sch_ep, bw_budget_table, -				     len_bw_budget_table), -			 GFP_KERNEL); +	sch_ep = kzalloc(sizeof(*sch_ep), GFP_KERNEL);  	if (!sch_ep)  		return ERR_PTR(-ENOMEM); @@ -295,8 +279,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,  	u32 mult;  	u32 esit_pkts;  	u32 max_esit_payload; -	u32 *bwb_table = sch_ep->bw_budget_table; -	int i;  	ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));  	maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); @@ -332,7 +314,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,  		 */  		sch_ep->pkts = max_burst + 1;  		sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; -		bwb_table[0] = sch_ep->bw_cost_per_microframe;  	} else if (sch_ep->speed >= USB_SPEED_SUPER) {  		/* usb3_r1 spec section4.4.7 & 4.4.8 */  		sch_ep->cs_count = 0; @@ -349,7 +330,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,  		if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {  			sch_ep->pkts = esit_pkts;  			sch_ep->num_budget_microframes = 1; -			bwb_table[0] = maxpkt * sch_ep->pkts;  		}  		if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) { @@ -366,15 +346,8 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,  				DIV_ROUND_UP(esit_pkts, sch_ep->pkts);  			sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1); -			sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; - -			for (i = 0; i < sch_ep->num_budget_microframes - 1; i++) -				bwb_table[i] = sch_ep->bw_cost_per_microframe; - -			/* last one <= bw_cost_per_microframe */ -			bwb_table[i] = maxpkt * esit_pkts -				       - i * sch_ep->bw_cost_per_microframe;  		} +		sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;  	} else if (is_fs_or_ls(sch_ep->speed)) {  		sch_ep->pkts = 1; /* at most one packet for each microframe */ @@ -384,28 +357,7 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,  		 */  		sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX);  		sch_ep->num_budget_microframes = sch_ep->cs_count; -		sch_ep->bw_cost_per_microframe = -			(maxpkt < FS_PAYLOAD_MAX) ? maxpkt : FS_PAYLOAD_MAX; - -		/* init budget table */ -		if (ep_type == ISOC_OUT_EP) { -			for (i = 0; i < sch_ep->num_budget_microframes; i++) -				bwb_table[i] =	sch_ep->bw_cost_per_microframe; -		} else if (ep_type == INT_OUT_EP) { -			/* only first one consumes bandwidth, others as zero */ -			bwb_table[0] = sch_ep->bw_cost_per_microframe; -		} else { /* INT_IN_EP or ISOC_IN_EP */ -			bwb_table[0] = 0; /* start split */ -			bwb_table[1] = 0; /* idle */ -			/* -			 * due to cs_count will be updated according to cs -			 * position, assign all remainder budget array -			 * elements as @bw_cost_per_microframe, but only first -			 * @num_budget_microframes elements will be used later -			 */ -			for (i = 2; i < TT_MICROFRAMES_MAX; i++) -				bwb_table[i] =	sch_ep->bw_cost_per_microframe; -		} +		sch_ep->bw_cost_per_microframe = min_t(u32, maxpkt, FS_PAYLOAD_MAX);  	}  } @@ -422,7 +374,7 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,  		for (j = 0; j < sch_ep->num_budget_microframes; j++) {  			k = XHCI_MTK_BW_INDEX(base + j); -			bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j]; +			bw = sch_bw->bus_bw[k] + sch_ep->bw_cost_per_microframe;  			if (bw > max_bw)  				max_bw = bw;  		} @@ -433,18 +385,16 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,  static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,  	struct mu3h_sch_ep_info *sch_ep, bool used)  { +	int bw_updated;  	u32 base; -	int i, j, k; +	int i, j; + +	bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1);  	for (i = 0; i < sch_ep->num_esit; i++) {  		base = sch_ep->offset + i * sch_ep->esit; -		for (j = 0; j < sch_ep->num_budget_microframes; j++) { -			k = XHCI_MTK_BW_INDEX(base + j); -			if (used) -				sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j]; -			else -				sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j]; -		} +		for (j = 0; j < sch_ep->num_budget_microframes; j++) +			sch_bw->bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated;  	}  } @@ -464,7 +414,7 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)  		 */  		for (j = 0; j < sch_ep->num_budget_microframes; j++) {  			k = XHCI_MTK_BW_INDEX(base + j); -			tmp = tt->fs_bus_bw[k] + sch_ep->bw_budget_table[j]; +			tmp = tt->fs_bus_bw[k] + sch_ep->bw_cost_per_microframe;  			if (tmp > FS_PAYLOAD_MAX)  				return -ESCH_BW_OVERFLOW;  		} @@ -538,19 +488,17 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)  static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)  {  	struct mu3h_sch_tt *tt = sch_ep->sch_tt; +	int bw_updated;  	u32 base; -	int i, j, k; +	int i, j; + +	bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1);  	for (i = 0; i < sch_ep->num_esit; i++) {  		base = sch_ep->offset + i * sch_ep->esit; -		for (j = 0; j < sch_ep->num_budget_microframes; j++) { -			k = XHCI_MTK_BW_INDEX(base + j); -			if (used) -				tt->fs_bus_bw[k] += sch_ep->bw_budget_table[j]; -			else -				tt->fs_bus_bw[k] -= sch_ep->bw_budget_table[j]; -		} +		for (j = 0; j < sch_ep->num_budget_microframes; j++) +			tt->fs_bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated;  	}  	if (used) @@ -710,7 +658,7 @@ static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,  	xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed)); -	sch_ep = create_sch_ep(mtk, udev, ep, ep_ctx); +	sch_ep = create_sch_ep(mtk, udev, ep);  	if (IS_ERR_OR_NULL(sch_ep))  		return -ENOMEM; diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h index ffd4b493b4ba..1174a510dd38 100644 --- a/drivers/usb/host/xhci-mtk.h +++ b/drivers/usb/host/xhci-mtk.h @@ -83,7 +83,6 @@ struct mu3h_sch_bw_info {   *		times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets   *		according to @pkts and @repeat. normal mode is used by   *		default - * @bw_budget_table: table to record bandwidth budget per microframe   */  struct mu3h_sch_ep_info {  	u32 esit; @@ -109,7 +108,6 @@ struct mu3h_sch_ep_info {  	u32 pkts;  	u32 cs_count;  	u32 burst_mode; -	u32 bw_budget_table[];  };  #define MU3C_U3_PORT_MAX 4 diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 5c351970cdf1..d7e0e6ebf080 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -59,6 +59,7 @@  #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI		0x9a13  #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI		0x1138  #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI		0x461e +#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI	0x51ed  #define PCI_DEVICE_ID_AMD_RENOIR_XHCI			0x1639  #define PCI_DEVICE_ID_AMD_PROMONTORYA_4			0x43b9 @@ -266,7 +267,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)  	     pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI ||  	     pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI ||  	     pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI || -	     pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI)) +	     pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI || +	     pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI))  		xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;  	if (pdev->vendor == PCI_VENDOR_ID_ETRON && diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index d0b6806275e0..f9707997969d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3141,6 +3141,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)  		if (event_loop++ < TRBS_PER_SEGMENT / 2)  			continue;  		xhci_update_erst_dequeue(xhci, event_ring_deq); +		event_ring_deq = xhci->event_ring->dequeue;  		/* ring is half-full, force isoc trbs to interrupt more often */  		if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN) diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index c8af2cd2216d..996958a6565c 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -1034,13 +1034,13 @@ static int tegra_xusb_unpowergate_partitions(struct tegra_xusb *tegra)  	int rc;  	if (tegra->use_genpd) { -		rc = pm_runtime_get_sync(tegra->genpd_dev_ss); +		rc = pm_runtime_resume_and_get(tegra->genpd_dev_ss);  		if (rc < 0) {  			dev_err(dev, "failed to enable XUSB SS partition\n");  			return rc;  		} -		rc = pm_runtime_get_sync(tegra->genpd_dev_host); +		rc = pm_runtime_resume_and_get(tegra->genpd_dev_host);  		if (rc < 0) {  			dev_err(dev, "failed to enable XUSB Host partition\n");  			pm_runtime_put_sync(tegra->genpd_dev_ss); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 642610c78f58..25b87e99b4dd 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -781,6 +781,17 @@ void xhci_shutdown(struct usb_hcd *hcd)  	if (xhci->quirks & XHCI_SPURIOUS_REBOOT)  		usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev)); +	/* Don't poll the roothubs after shutdown. */ +	xhci_dbg(xhci, "%s: stopping usb%d port polling.\n", +			__func__, hcd->self.busnum); +	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); +	del_timer_sync(&hcd->rh_timer); + +	if (xhci->shared_hcd) { +		clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); +		del_timer_sync(&xhci->shared_hcd->rh_timer); +	} +  	spin_lock_irq(&xhci->lock);  	xhci_halt(xhci);  	/* Workaround for spurious wakeups at shutdown with HSW */ |