forked from Minki/linux
USB fixes for 3.12-rc3
Here are a number of USB driver fixes for 3.12-rc3. These are all for host controller issues that have been reported, and there's a fix for an annoying error message that gets printed every time you remove a USB 3 device from the system that's been bugging me for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.21 (GNU/Linux) iEYEABECAAYFAlJIhsIACgkQMUfUDdst+ynPjACgiw9TMpwWtAu/gbRNGJnGthR2 a+8AoJMrVPGqr0g0ypn8d35sHMnbUTAU =AZ3S -----END PGP SIGNATURE----- Merge tag 'usb-3.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg KH: "Here are a number of USB driver fixes for 3.12-rc3. These are all for host controller issues that have been reported, and there's a fix for an annoying error message that gets printed every time you remove a USB 3 device from the system that's been bugging me for a while" * tag 'usb-3.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: usb: dwc3: add support for Merrifield USB: fsl/ehci: fix failure of checking PHY_CLK_VALID during reinitialization USB: Fix breakage in ffs_fs_mount() fsl/usb: Resolve PHY_CLK_VLD instability issue for ULPI phy usb/core/devio.c: Don't reject control message to endpoint with wrong direction bit usb: chipidea: USB_CHIPIDEA should depend on HAS_DMA usb: chipidea: udc: free pending TD at removal procedure usb: chipidea: imx: Add usb_phy_shutdown at probe's error path usb: chipidea: Fix memleak for ci->hw_bank.regmap when removal usb: chipidea: udc: fix the oops after rmmod gadget USB: fix PM config symbol in uhci-hcd, ehci-hcd, and xhci-hcd USB: OHCI: accept very late isochronous URBs USB: UHCI: accept very late isochronous URBs USB: iMX21: accept very late isochronous URBs usbcore: check usb device's state before sending a Set SEL control transfer xhci: Fix race between ep halt and URB cancellation usb: Fix xHCI host issues on remote wakeup. xhci: Ensure a command structure points to the correct trb on the command ring xhci: Fix oops happening after address device timeout
This commit is contained in:
commit
30ceb4ec33
@ -1,6 +1,6 @@
|
||||
config USB_CHIPIDEA
|
||||
tristate "ChipIdea Highspeed Dual Role Controller"
|
||||
depends on (USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)
|
||||
depends on ((USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)) && HAS_DMA
|
||||
help
|
||||
Say Y here if your system has a dual role high speed USB
|
||||
controller based on ChipIdea silicon IP. Currently, only the
|
||||
|
@ -131,7 +131,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n",
|
||||
ret);
|
||||
goto err_clk;
|
||||
goto err_phy;
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev,
|
||||
"Can't register ci_hdrc platform device, err=%d\n",
|
||||
ret);
|
||||
goto err_clk;
|
||||
goto err_phy;
|
||||
}
|
||||
|
||||
if (data->usbmisc_data) {
|
||||
@ -164,6 +164,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
||||
|
||||
disable_device:
|
||||
ci_hdrc_remove_device(data->ci_pdev);
|
||||
err_phy:
|
||||
if (data->phy)
|
||||
usb_phy_shutdown(data->phy);
|
||||
err_clk:
|
||||
clk_disable_unprepare(data->clk);
|
||||
return ret;
|
||||
|
@ -605,6 +605,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
|
||||
dbg_remove_files(ci);
|
||||
free_irq(ci->irq, ci);
|
||||
ci_role_destroy(ci);
|
||||
kfree(ci->hw_bank.regmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1600,6 +1600,8 @@ static void destroy_eps(struct ci_hdrc *ci)
|
||||
for (i = 0; i < ci->hw_ep_max; i++) {
|
||||
struct ci_hw_ep *hwep = &ci->ci_hw_ep[i];
|
||||
|
||||
if (hwep->pending_td)
|
||||
free_pending_td(hwep);
|
||||
dma_pool_free(ci->qh_pool, hwep->qh.ptr, hwep->qh.dma);
|
||||
}
|
||||
}
|
||||
@ -1667,13 +1669,13 @@ static int ci_udc_stop(struct usb_gadget *gadget,
|
||||
if (ci->platdata->notify_event)
|
||||
ci->platdata->notify_event(ci,
|
||||
CI_HDRC_CONTROLLER_STOPPED_EVENT);
|
||||
ci->driver = NULL;
|
||||
spin_unlock_irqrestore(&ci->lock, flags);
|
||||
_gadget_stop_activity(&ci->gadget);
|
||||
spin_lock_irqsave(&ci->lock, flags);
|
||||
pm_runtime_put(&ci->gadget.dev);
|
||||
}
|
||||
|
||||
ci->driver = NULL;
|
||||
spin_unlock_irqrestore(&ci->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
@ -742,6 +742,22 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
|
||||
if ((index & ~USB_DIR_IN) == 0)
|
||||
return 0;
|
||||
ret = findintfep(ps->dev, index);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* Some not fully compliant Win apps seem to get
|
||||
* index wrong and have the endpoint number here
|
||||
* rather than the endpoint address (with the
|
||||
* correct direction). Win does let this through,
|
||||
* so we'll not reject it here but leave it to
|
||||
* the device to not break KVM. But we warn.
|
||||
*/
|
||||
ret = findintfep(ps->dev, index ^ 0x80);
|
||||
if (ret >= 0)
|
||||
dev_info(&ps->dev->dev,
|
||||
"%s: process %i (%s) requesting ep %02x but needs %02x\n",
|
||||
__func__, task_pid_nr(current),
|
||||
current->comm, index, index ^ 0x80);
|
||||
}
|
||||
if (ret >= 0)
|
||||
ret = checkintf(ps, ret);
|
||||
break;
|
||||
|
@ -3426,6 +3426,9 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
|
||||
unsigned long long u2_pel;
|
||||
int ret;
|
||||
|
||||
if (udev->state != USB_STATE_CONFIGURED)
|
||||
return 0;
|
||||
|
||||
/* Convert SEL and PEL stored in ns to us */
|
||||
u1_sel = DIV_ROUND_UP(udev->u1_params.sel, 1000);
|
||||
u1_pel = DIV_ROUND_UP(udev->u1_params.pel, 1000);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#define PCI_VENDOR_ID_SYNOPSYS 0x16c3
|
||||
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd
|
||||
#define PCI_DEVICE_ID_INTEL_BYT 0x0f37
|
||||
#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
|
||||
|
||||
struct dwc3_pci {
|
||||
struct device *dev;
|
||||
@ -189,6 +190,7 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
|
||||
PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
|
||||
},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
|
||||
{ } /* Terminating Entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
|
||||
|
@ -1034,37 +1034,19 @@ struct ffs_sb_fill_data {
|
||||
struct ffs_file_perms perms;
|
||||
umode_t root_mode;
|
||||
const char *dev_name;
|
||||
union {
|
||||
/* set by ffs_fs_mount(), read by ffs_sb_fill() */
|
||||
void *private_data;
|
||||
/* set by ffs_sb_fill(), read by ffs_fs_mount */
|
||||
struct ffs_data *ffs_data;
|
||||
};
|
||||
struct ffs_data *ffs_data;
|
||||
};
|
||||
|
||||
static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
|
||||
{
|
||||
struct ffs_sb_fill_data *data = _data;
|
||||
struct inode *inode;
|
||||
struct ffs_data *ffs;
|
||||
struct ffs_data *ffs = data->ffs_data;
|
||||
|
||||
ENTER();
|
||||
|
||||
/* Initialise data */
|
||||
ffs = ffs_data_new();
|
||||
if (unlikely(!ffs))
|
||||
goto Enomem;
|
||||
|
||||
ffs->sb = sb;
|
||||
ffs->dev_name = kstrdup(data->dev_name, GFP_KERNEL);
|
||||
if (unlikely(!ffs->dev_name))
|
||||
goto Enomem;
|
||||
ffs->file_perms = data->perms;
|
||||
ffs->private_data = data->private_data;
|
||||
|
||||
/* used by the caller of this function */
|
||||
data->ffs_data = ffs;
|
||||
|
||||
data->ffs_data = NULL;
|
||||
sb->s_fs_info = ffs;
|
||||
sb->s_blocksize = PAGE_CACHE_SIZE;
|
||||
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
|
||||
@ -1080,17 +1062,14 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
|
||||
&data->perms);
|
||||
sb->s_root = d_make_root(inode);
|
||||
if (unlikely(!sb->s_root))
|
||||
goto Enomem;
|
||||
return -ENOMEM;
|
||||
|
||||
/* EP0 file */
|
||||
if (unlikely(!ffs_sb_create_file(sb, "ep0", ffs,
|
||||
&ffs_ep0_operations, NULL)))
|
||||
goto Enomem;
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
|
||||
Enomem:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
|
||||
@ -1193,6 +1172,7 @@ ffs_fs_mount(struct file_system_type *t, int flags,
|
||||
struct dentry *rv;
|
||||
int ret;
|
||||
void *ffs_dev;
|
||||
struct ffs_data *ffs;
|
||||
|
||||
ENTER();
|
||||
|
||||
@ -1200,18 +1180,30 @@ ffs_fs_mount(struct file_system_type *t, int flags,
|
||||
if (unlikely(ret < 0))
|
||||
return ERR_PTR(ret);
|
||||
|
||||
ffs = ffs_data_new();
|
||||
if (unlikely(!ffs))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
ffs->file_perms = data.perms;
|
||||
|
||||
ffs->dev_name = kstrdup(dev_name, GFP_KERNEL);
|
||||
if (unlikely(!ffs->dev_name)) {
|
||||
ffs_data_put(ffs);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ffs_dev = functionfs_acquire_dev_callback(dev_name);
|
||||
if (IS_ERR(ffs_dev))
|
||||
return ffs_dev;
|
||||
if (IS_ERR(ffs_dev)) {
|
||||
ffs_data_put(ffs);
|
||||
return ERR_CAST(ffs_dev);
|
||||
}
|
||||
ffs->private_data = ffs_dev;
|
||||
data.ffs_data = ffs;
|
||||
|
||||
data.dev_name = dev_name;
|
||||
data.private_data = ffs_dev;
|
||||
rv = mount_nodev(t, flags, &data, ffs_sb_fill);
|
||||
|
||||
/* data.ffs_data is set by ffs_sb_fill */
|
||||
if (IS_ERR(rv))
|
||||
if (IS_ERR(rv) && data.ffs_data) {
|
||||
functionfs_release_dev_callback(data.ffs_data);
|
||||
|
||||
ffs_data_put(data.ffs_data);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
|
||||
}
|
||||
|
||||
/* Enable USB controller, 83xx or 8536 */
|
||||
if (pdata->have_sysif_regs)
|
||||
if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6)
|
||||
setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
|
||||
|
||||
/* Don't need to set host mode here. It will be done by tdi_reset() */
|
||||
@ -232,15 +232,9 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
|
||||
case FSL_USB2_PHY_ULPI:
|
||||
if (pdata->have_sysif_regs && pdata->controller_ver) {
|
||||
/* controller version 1.6 or above */
|
||||
clrbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
|
||||
setbits32(non_ehci + FSL_SOC_USB_CTRL,
|
||||
ULPI_PHY_CLK_SEL);
|
||||
/*
|
||||
* Due to controller issue of PHY_CLK_VALID in ULPI
|
||||
* mode, we set USB_CTRL_USB_EN before checking
|
||||
* PHY_CLK_VALID, otherwise PHY_CLK_VALID doesn't work.
|
||||
*/
|
||||
clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
|
||||
UTMI_PHY_EN, USB_CTRL_USB_EN);
|
||||
ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN);
|
||||
}
|
||||
portsc |= PORT_PTS_ULPI;
|
||||
break;
|
||||
@ -270,8 +264,9 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
|
||||
if (pdata->have_sysif_regs && pdata->controller_ver &&
|
||||
(phy_mode == FSL_USB2_PHY_ULPI)) {
|
||||
/* check PHY_CLK_VALID to get phy clk valid */
|
||||
if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
|
||||
PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) {
|
||||
if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
|
||||
PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0) ||
|
||||
in_be32(non_ehci + FSL_SOC_USB_PRICTRL))) {
|
||||
printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -361,7 +361,7 @@ static struct pci_driver ehci_pci_driver = {
|
||||
.remove = usb_hcd_pci_remove,
|
||||
.shutdown = usb_hcd_pci_shutdown,
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#ifdef CONFIG_PM
|
||||
.driver = {
|
||||
.pm = &usb_hcd_pci_pm_ops
|
||||
},
|
||||
|
@ -824,13 +824,13 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
|
||||
i = DIV_ROUND_UP(wrap_frame(
|
||||
cur_frame - urb->start_frame),
|
||||
urb->interval);
|
||||
if (urb->transfer_flags & URB_ISO_ASAP) {
|
||||
|
||||
/* Treat underruns as if URB_ISO_ASAP was set */
|
||||
if ((urb->transfer_flags & URB_ISO_ASAP) ||
|
||||
i >= urb->number_of_packets) {
|
||||
urb->start_frame = wrap_frame(urb->start_frame
|
||||
+ i * urb->interval);
|
||||
i = 0;
|
||||
} else if (i >= urb->number_of_packets) {
|
||||
ret = -EXDEV;
|
||||
goto alloc_dmem_failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,31 +216,26 @@ static int ohci_urb_enqueue (
|
||||
frame &= ~(ed->interval - 1);
|
||||
frame |= ed->branch;
|
||||
urb->start_frame = frame;
|
||||
ed->last_iso = frame + ed->interval * (size - 1);
|
||||
}
|
||||
} else if (ed->type == PIPE_ISOCHRONOUS) {
|
||||
u16 next = ohci_frame_no(ohci) + 1;
|
||||
u16 frame = ed->last_iso + ed->interval;
|
||||
u16 length = ed->interval * (size - 1);
|
||||
|
||||
/* Behind the scheduling threshold? */
|
||||
if (unlikely(tick_before(frame, next))) {
|
||||
|
||||
/* USB_ISO_ASAP: Round up to the first available slot */
|
||||
/* URB_ISO_ASAP: Round up to the first available slot */
|
||||
if (urb->transfer_flags & URB_ISO_ASAP) {
|
||||
frame += (next - frame + ed->interval - 1) &
|
||||
-ed->interval;
|
||||
|
||||
/*
|
||||
* Not ASAP: Use the next slot in the stream. If
|
||||
* the entire URB falls before the threshold, fail.
|
||||
* Not ASAP: Use the next slot in the stream,
|
||||
* no matter what.
|
||||
*/
|
||||
} else {
|
||||
if (tick_before(frame + ed->interval *
|
||||
(urb->number_of_packets - 1), next)) {
|
||||
retval = -EXDEV;
|
||||
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some OHCI hardware doesn't handle late TDs
|
||||
* correctly. After retiring them it proceeds
|
||||
@ -251,9 +246,16 @@ static int ohci_urb_enqueue (
|
||||
urb_priv->td_cnt = DIV_ROUND_UP(
|
||||
(u16) (next - frame),
|
||||
ed->interval);
|
||||
if (urb_priv->td_cnt >= urb_priv->length) {
|
||||
++urb_priv->td_cnt; /* Mark it */
|
||||
ohci_dbg(ohci, "iso underrun %p (%u+%u < %u)\n",
|
||||
urb, frame, length,
|
||||
next);
|
||||
}
|
||||
}
|
||||
}
|
||||
urb->start_frame = frame;
|
||||
ed->last_iso = frame + length;
|
||||
}
|
||||
|
||||
/* fill the TDs and link them to the ed; and
|
||||
|
@ -41,9 +41,13 @@ finish_urb(struct ohci_hcd *ohci, struct urb *urb, int status)
|
||||
__releases(ohci->lock)
|
||||
__acquires(ohci->lock)
|
||||
{
|
||||
struct device *dev = ohci_to_hcd(ohci)->self.controller;
|
||||
struct device *dev = ohci_to_hcd(ohci)->self.controller;
|
||||
struct usb_host_endpoint *ep = urb->ep;
|
||||
struct urb_priv *urb_priv;
|
||||
|
||||
// ASSERT (urb->hcpriv != 0);
|
||||
|
||||
restart:
|
||||
urb_free_priv (ohci, urb->hcpriv);
|
||||
urb->hcpriv = NULL;
|
||||
if (likely(status == -EINPROGRESS))
|
||||
@ -80,6 +84,21 @@ __acquires(ohci->lock)
|
||||
ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_IE);
|
||||
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
|
||||
}
|
||||
|
||||
/*
|
||||
* An isochronous URB that is sumitted too late won't have any TDs
|
||||
* (marked by the fact that the td_cnt value is larger than the
|
||||
* actual number of TDs). If the next URB on this endpoint is like
|
||||
* that, give it back now.
|
||||
*/
|
||||
if (!list_empty(&ep->urb_list)) {
|
||||
urb = list_first_entry(&ep->urb_list, struct urb, urb_list);
|
||||
urb_priv = urb->hcpriv;
|
||||
if (urb_priv->td_cnt > urb_priv->length) {
|
||||
status = 0;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -546,7 +565,6 @@ td_fill (struct ohci_hcd *ohci, u32 info,
|
||||
td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000);
|
||||
*ohci_hwPSWp(ohci, td, 0) = cpu_to_hc16 (ohci,
|
||||
(data & 0x0FFF) | 0xE000);
|
||||
td->ed->last_iso = info & 0xffff;
|
||||
} else {
|
||||
td->hwCBP = cpu_to_hc32 (ohci, data);
|
||||
}
|
||||
@ -996,7 +1014,7 @@ rescan_this:
|
||||
urb_priv->td_cnt++;
|
||||
|
||||
/* if URB is done, clean up */
|
||||
if (urb_priv->td_cnt == urb_priv->length) {
|
||||
if (urb_priv->td_cnt >= urb_priv->length) {
|
||||
modified = completed = 1;
|
||||
finish_urb(ohci, urb, 0);
|
||||
}
|
||||
@ -1086,7 +1104,7 @@ static void takeback_td(struct ohci_hcd *ohci, struct td *td)
|
||||
urb_priv->td_cnt++;
|
||||
|
||||
/* If all this urb's TDs are done, call complete() */
|
||||
if (urb_priv->td_cnt == urb_priv->length)
|
||||
if (urb_priv->td_cnt >= urb_priv->length)
|
||||
finish_urb(ohci, urb, status);
|
||||
|
||||
/* clean schedule: unlink EDs that are no longer busy */
|
||||
|
@ -293,7 +293,7 @@ static struct pci_driver uhci_pci_driver = {
|
||||
.remove = usb_hcd_pci_remove,
|
||||
.shutdown = uhci_shutdown,
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#ifdef CONFIG_PM
|
||||
.driver = {
|
||||
.pm = &usb_hcd_pci_pm_ops
|
||||
},
|
||||
|
@ -1303,7 +1303,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
|
||||
}
|
||||
|
||||
/* Fell behind? */
|
||||
if (uhci_frame_before_eq(frame, next)) {
|
||||
if (!uhci_frame_before_eq(next, frame)) {
|
||||
|
||||
/* USB_ISO_ASAP: Round up to the first available slot */
|
||||
if (urb->transfer_flags & URB_ISO_ASAP)
|
||||
@ -1311,13 +1311,17 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
|
||||
-qh->period;
|
||||
|
||||
/*
|
||||
* Not ASAP: Use the next slot in the stream. If
|
||||
* the entire URB falls before the threshold, fail.
|
||||
* Not ASAP: Use the next slot in the stream,
|
||||
* no matter what.
|
||||
*/
|
||||
else if (!uhci_frame_before_eq(next,
|
||||
frame + (urb->number_of_packets - 1) *
|
||||
qh->period))
|
||||
return -EXDEV;
|
||||
dev_dbg(uhci_dev(uhci), "iso underrun %p (%u+%u < %u)\n",
|
||||
urb, frame,
|
||||
(urb->number_of_packets - 1) *
|
||||
qh->period,
|
||||
next);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,7 +287,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
|
||||
if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
|
||||
xhci_queue_stop_endpoint(xhci, slot_id, i, suspend);
|
||||
}
|
||||
cmd->command_trb = xhci->cmd_ring->enqueue;
|
||||
cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
|
||||
list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
|
||||
xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
|
||||
xhci_ring_cmd_db(xhci);
|
||||
@ -552,11 +552,15 @@ void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex)
|
||||
* - Mark a port as being done with device resume,
|
||||
* and ring the endpoint doorbells.
|
||||
* - Stop the Synopsys redriver Compliance Mode polling.
|
||||
* - Drop and reacquire the xHCI lock, in order to wait for port resume.
|
||||
*/
|
||||
static u32 xhci_get_port_status(struct usb_hcd *hcd,
|
||||
struct xhci_bus_state *bus_state,
|
||||
__le32 __iomem **port_array,
|
||||
u16 wIndex, u32 raw_port_status)
|
||||
u16 wIndex, u32 raw_port_status,
|
||||
unsigned long flags)
|
||||
__releases(&xhci->lock)
|
||||
__acquires(&xhci->lock)
|
||||
{
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
u32 status = 0;
|
||||
@ -591,21 +595,42 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
|
||||
return 0xffffffff;
|
||||
if (time_after_eq(jiffies,
|
||||
bus_state->resume_done[wIndex])) {
|
||||
int time_left;
|
||||
|
||||
xhci_dbg(xhci, "Resume USB2 port %d\n",
|
||||
wIndex + 1);
|
||||
bus_state->resume_done[wIndex] = 0;
|
||||
clear_bit(wIndex, &bus_state->resuming_ports);
|
||||
|
||||
set_bit(wIndex, &bus_state->rexit_ports);
|
||||
xhci_set_link_state(xhci, port_array, wIndex,
|
||||
XDEV_U0);
|
||||
xhci_dbg(xhci, "set port %d resume\n",
|
||||
wIndex + 1);
|
||||
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
|
||||
wIndex + 1);
|
||||
if (!slot_id) {
|
||||
xhci_dbg(xhci, "slot_id is zero\n");
|
||||
return 0xffffffff;
|
||||
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
time_left = wait_for_completion_timeout(
|
||||
&bus_state->rexit_done[wIndex],
|
||||
msecs_to_jiffies(
|
||||
XHCI_MAX_REXIT_TIMEOUT));
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
||||
if (time_left) {
|
||||
slot_id = xhci_find_slot_id_by_port(hcd,
|
||||
xhci, wIndex + 1);
|
||||
if (!slot_id) {
|
||||
xhci_dbg(xhci, "slot_id is zero\n");
|
||||
return 0xffffffff;
|
||||
}
|
||||
xhci_ring_device(xhci, slot_id);
|
||||
} else {
|
||||
int port_status = xhci_readl(xhci,
|
||||
port_array[wIndex]);
|
||||
xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n",
|
||||
XHCI_MAX_REXIT_TIMEOUT,
|
||||
port_status);
|
||||
status |= USB_PORT_STAT_SUSPEND;
|
||||
clear_bit(wIndex, &bus_state->rexit_ports);
|
||||
}
|
||||
xhci_ring_device(xhci, slot_id);
|
||||
|
||||
bus_state->port_c_suspend |= 1 << wIndex;
|
||||
bus_state->suspended_ports &= ~(1 << wIndex);
|
||||
} else {
|
||||
@ -728,7 +753,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
||||
break;
|
||||
}
|
||||
status = xhci_get_port_status(hcd, bus_state, port_array,
|
||||
wIndex, temp);
|
||||
wIndex, temp, flags);
|
||||
if (status == 0xffffffff)
|
||||
goto error;
|
||||
|
||||
|
@ -2428,6 +2428,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
||||
for (i = 0; i < USB_MAXCHILDREN; ++i) {
|
||||
xhci->bus_state[0].resume_done[i] = 0;
|
||||
xhci->bus_state[1].resume_done[i] = 0;
|
||||
/* Only the USB 2.0 completions will ever be used. */
|
||||
init_completion(&xhci->bus_state[1].rexit_done[i]);
|
||||
}
|
||||
|
||||
if (scratchpad_alloc(xhci, flags))
|
||||
|
@ -351,7 +351,7 @@ static struct pci_driver xhci_pci_driver = {
|
||||
/* suspend and resume implemented later */
|
||||
|
||||
.shutdown = usb_hcd_pci_shutdown,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#ifdef CONFIG_PM
|
||||
.driver = {
|
||||
.pm = &usb_hcd_pci_pm_ops
|
||||
},
|
||||
|
@ -123,6 +123,16 @@ static int enqueue_is_link_trb(struct xhci_ring *ring)
|
||||
return TRB_TYPE_LINK_LE32(link->control);
|
||||
}
|
||||
|
||||
union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring)
|
||||
{
|
||||
/* Enqueue pointer can be left pointing to the link TRB,
|
||||
* we must handle that
|
||||
*/
|
||||
if (TRB_TYPE_LINK_LE32(ring->enqueue->link.control))
|
||||
return ring->enq_seg->next->trbs;
|
||||
return ring->enqueue;
|
||||
}
|
||||
|
||||
/* Updates trb to point to the next TRB in the ring, and updates seg if the next
|
||||
* TRB is in a new segment. This does not skip over link TRBs, and it does not
|
||||
* effect the ring dequeue or enqueue pointers.
|
||||
@ -859,8 +869,12 @@ remove_finished_td:
|
||||
/* Otherwise ring the doorbell(s) to restart queued transfers */
|
||||
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
|
||||
}
|
||||
ep->stopped_td = NULL;
|
||||
ep->stopped_trb = NULL;
|
||||
|
||||
/* Clear stopped_td and stopped_trb if endpoint is not halted */
|
||||
if (!(ep->ep_state & EP_HALTED)) {
|
||||
ep->stopped_td = NULL;
|
||||
ep->stopped_trb = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop the lock and complete the URBs in the cancelled TD list.
|
||||
@ -1414,6 +1428,12 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
|
||||
inc_deq(xhci, xhci->cmd_ring);
|
||||
return;
|
||||
}
|
||||
/* There is no command to handle if we get a stop event when the
|
||||
* command ring is empty, event->cmd_trb points to the next
|
||||
* unset command
|
||||
*/
|
||||
if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])
|
||||
@ -1743,6 +1763,19 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if xhci-hub.c is waiting on RExit to U0 transition (or
|
||||
* RExit to a disconnect state). If so, let the the driver know it's
|
||||
* out of the RExit state.
|
||||
*/
|
||||
if (!DEV_SUPERSPEED(temp) &&
|
||||
test_and_clear_bit(faked_port_index,
|
||||
&bus_state->rexit_ports)) {
|
||||
complete(&bus_state->rexit_done[faked_port_index]);
|
||||
bogus_port_status = true;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (hcd->speed != HCD_USB3)
|
||||
xhci_test_and_clear_bit(xhci, port_array, faked_port_index,
|
||||
PORT_PLC);
|
||||
|
@ -2598,15 +2598,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
||||
if (command) {
|
||||
cmd_completion = command->completion;
|
||||
cmd_status = &command->status;
|
||||
command->command_trb = xhci->cmd_ring->enqueue;
|
||||
|
||||
/* Enqueue pointer can be left pointing to the link TRB,
|
||||
* we must handle that
|
||||
*/
|
||||
if (TRB_TYPE_LINK_LE32(command->command_trb->link.control))
|
||||
command->command_trb =
|
||||
xhci->cmd_ring->enq_seg->next->trbs;
|
||||
|
||||
command->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
|
||||
list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
|
||||
} else {
|
||||
cmd_completion = &virt_dev->cmd_completion;
|
||||
@ -2614,7 +2606,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
||||
}
|
||||
init_completion(cmd_completion);
|
||||
|
||||
cmd_trb = xhci->cmd_ring->dequeue;
|
||||
cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
|
||||
if (!ctx_change)
|
||||
ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
|
||||
udev->slot_id, must_succeed);
|
||||
@ -3439,14 +3431,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
|
||||
/* Attempt to submit the Reset Device command to the command ring */
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
reset_device_cmd->command_trb = xhci->cmd_ring->enqueue;
|
||||
|
||||
/* Enqueue pointer can be left pointing to the link TRB,
|
||||
* we must handle that
|
||||
*/
|
||||
if (TRB_TYPE_LINK_LE32(reset_device_cmd->command_trb->link.control))
|
||||
reset_device_cmd->command_trb =
|
||||
xhci->cmd_ring->enq_seg->next->trbs;
|
||||
reset_device_cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
|
||||
|
||||
list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
|
||||
ret = xhci_queue_reset_device(xhci, slot_id);
|
||||
@ -3650,7 +3635,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
union xhci_trb *cmd_trb;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
cmd_trb = xhci->cmd_ring->dequeue;
|
||||
cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
|
||||
ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0);
|
||||
if (ret) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
@ -3785,7 +3770,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
slot_ctx->dev_info >> 27);
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
cmd_trb = xhci->cmd_ring->dequeue;
|
||||
cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
|
||||
ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
|
||||
udev->slot_id);
|
||||
if (ret) {
|
||||
|
@ -1412,8 +1412,18 @@ struct xhci_bus_state {
|
||||
unsigned long resume_done[USB_MAXCHILDREN];
|
||||
/* which ports have started to resume */
|
||||
unsigned long resuming_ports;
|
||||
/* Which ports are waiting on RExit to U0 transition. */
|
||||
unsigned long rexit_ports;
|
||||
struct completion rexit_done[USB_MAXCHILDREN];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* It can take up to 20 ms to transition from RExit to U0 on the
|
||||
* Intel Lynx Point LP xHCI host.
|
||||
*/
|
||||
#define XHCI_MAX_REXIT_TIMEOUT (20 * 1000)
|
||||
|
||||
static inline unsigned int hcd_index(struct usb_hcd *hcd)
|
||||
{
|
||||
if (hcd->speed == HCD_USB3)
|
||||
@ -1840,6 +1850,7 @@ int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
|
||||
union xhci_trb *cmd_trb);
|
||||
void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
|
||||
unsigned int ep_index, unsigned int stream_id);
|
||||
union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring);
|
||||
|
||||
/* xHCI roothub code */
|
||||
void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
|
||||
|
Loading…
Reference in New Issue
Block a user