diff options
Diffstat (limited to 'drivers/usb/host')
| -rw-r--r-- | drivers/usb/host/xhci-hub.c | 1 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-mtk-sch.c | 2 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-pci.c | 11 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 22 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.c | 26 | 
5 files changed, 40 insertions, 22 deletions
| diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index af946c42b6f0..df3522dab31b 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -717,6 +717,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci,  			continue;  		retval = xhci_disable_slot(xhci, i); +		xhci_free_virt_device(xhci, i);  		if (retval)  			xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n",  				 i, retval); diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c index 1edef7527c11..edbfa82c6565 100644 --- a/drivers/usb/host/xhci-mtk-sch.c +++ b/drivers/usb/host/xhci-mtk-sch.c @@ -781,7 +781,7 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)  	ret = xhci_check_bandwidth(hcd, udev);  	if (!ret) -		INIT_LIST_HEAD(&mtk->bw_ep_chk_list); +		list_del_init(&mtk->bw_ep_chk_list);  	return ret;  } diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 92adf6107864..5c351970cdf1 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -71,6 +71,8 @@  #define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4		0x161e  #define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5		0x15d6  #define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6		0x15d7 +#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7		0x161c +#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8		0x161f  #define PCI_DEVICE_ID_ASMEDIA_1042_XHCI			0x1042  #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI		0x1142 @@ -121,7 +123,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)  	/* Look for vendor-specific quirks */  	if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&  			(pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK || -			 pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1100 ||  			 pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) {  		if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&  				pdev->revision == 0x0) { @@ -156,6 +157,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)  			pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1009)  		xhci->quirks |= XHCI_BROKEN_STREAMS; +	if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && +			pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1100) +		xhci->quirks |= XHCI_TRUST_TX_LENGTH; +  	if (pdev->vendor == PCI_VENDOR_ID_NEC)  		xhci->quirks |= XHCI_NEC_HOST; @@ -330,7 +335,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)  	    pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 ||  	    pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 ||  	    pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 || -	    pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6)) +	    pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 || +	    pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 || +	    pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8))  		xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;  	if (xhci->quirks & XHCI_RESET_ON_RESUME) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 311597bba80e..d0b6806275e0 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -366,7 +366,9 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,  /* Must be called with xhci->lock held, releases and aquires lock back */  static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)  { -	u32 temp_32; +	struct xhci_segment *new_seg	= xhci->cmd_ring->deq_seg; +	union xhci_trb *new_deq		= xhci->cmd_ring->dequeue; +	u64 crcr;  	int ret;  	xhci_dbg(xhci, "Abort command ring\n"); @@ -375,13 +377,18 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)  	/*  	 * The control bits like command stop, abort are located in lower -	 * dword of the command ring control register. Limit the write -	 * to the lower dword to avoid corrupting the command ring pointer -	 * in case if the command ring is stopped by the time upper dword -	 * is written. +	 * dword of the command ring control register. +	 * Some controllers require all 64 bits to be written to abort the ring. +	 * Make sure the upper dword is valid, pointing to the next command, +	 * avoiding corrupting the command ring pointer in case the command ring +	 * is stopped by the time the upper dword is written.  	 */ -	temp_32 = readl(&xhci->op_regs->cmd_ring); -	writel(temp_32 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring); +	next_trb(xhci, NULL, &new_seg, &new_deq); +	if (trb_is_link(new_deq)) +		next_trb(xhci, NULL, &new_seg, &new_deq); + +	crcr = xhci_trb_virt_to_dma(new_seg, new_deq); +	xhci_write_64(xhci, crcr | CMD_RING_ABORT, &xhci->op_regs->cmd_ring);  	/* Section 4.6.1.2 of xHCI 1.0 spec says software should also time the  	 * completion of the Command Abort operation. If CRR is not negated in 5 @@ -1518,7 +1525,6 @@ static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id)  	if (xhci->quirks & XHCI_EP_LIMIT_QUIRK)  		/* Delete default control endpoint resources */  		xhci_free_device_endpoint_resources(xhci, virt_dev, true); -	xhci_free_virt_device(xhci, slot_id);  }  static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 902f410874e8..f5b1bcc875de 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3934,7 +3934,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)  	struct xhci_slot_ctx *slot_ctx;  	int i, ret; -#ifndef CONFIG_USB_DEFAULT_PERSIST  	/*  	 * We called pm_runtime_get_noresume when the device was attached.  	 * Decrement the counter here to allow controller to runtime suspend @@ -3942,7 +3941,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)  	 */  	if (xhci->quirks & XHCI_RESET_ON_RESUME)  		pm_runtime_put_noidle(hcd->self.controller); -#endif  	ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);  	/* If the host is halted due to driver unload, we still need to free the @@ -3961,9 +3959,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)  		del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);  	}  	virt_dev->udev = NULL; -	ret = xhci_disable_slot(xhci, udev->slot_id); -	if (ret) -		xhci_free_virt_device(xhci, udev->slot_id); +	xhci_disable_slot(xhci, udev->slot_id); +	xhci_free_virt_device(xhci, udev->slot_id);  }  int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) @@ -3973,7 +3970,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)  	u32 state;  	int ret = 0; -	command = xhci_alloc_command(xhci, false, GFP_KERNEL); +	command = xhci_alloc_command(xhci, true, GFP_KERNEL);  	if (!command)  		return -ENOMEM; @@ -3998,6 +3995,15 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)  	}  	xhci_ring_cmd_db(xhci);  	spin_unlock_irqrestore(&xhci->lock, flags); + +	wait_for_completion(command->completion); + +	if (command->status != COMP_SUCCESS) +		xhci_warn(xhci, "Unsuccessful disable slot %u command, status %d\n", +			  slot_id, command->status); + +	xhci_free_command(xhci, command); +  	return ret;  } @@ -4094,23 +4100,20 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)  	xhci_debugfs_create_slot(xhci, slot_id); -#ifndef CONFIG_USB_DEFAULT_PERSIST  	/*  	 * If resetting upon resume, we can't put the controller into runtime  	 * suspend if there is a device attached.  	 */  	if (xhci->quirks & XHCI_RESET_ON_RESUME)  		pm_runtime_get_noresume(hcd->self.controller); -#endif  	/* Is this a LS or FS device under a HS hub? */  	/* Hub or peripherial? */  	return 1;  disable_slot: -	ret = xhci_disable_slot(xhci, udev->slot_id); -	if (ret) -		xhci_free_virt_device(xhci, udev->slot_id); +	xhci_disable_slot(xhci, udev->slot_id); +	xhci_free_virt_device(xhci, udev->slot_id);  	return 0;  } @@ -4240,6 +4243,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,  		mutex_unlock(&xhci->mutex);  		ret = xhci_disable_slot(xhci, udev->slot_id); +		xhci_free_virt_device(xhci, udev->slot_id);  		if (!ret)  			xhci_alloc_dev(hcd, udev);  		kfree(command->completion); |