Commit 30ceb4ec authored by Linus Torvalds's avatar Linus Torvalds

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
parents 26c019fc 85601f8c
config USB_CHIPIDEA config USB_CHIPIDEA
tristate "ChipIdea Highspeed Dual Role Controller" 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 help
Say Y here if your system has a dual role high speed USB Say Y here if your system has a dual role high speed USB
controller based on ChipIdea silicon IP. Currently, only the controller based on ChipIdea silicon IP. Currently, only the
......
...@@ -131,7 +131,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) ...@@ -131,7 +131,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n", dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n",
ret); ret);
goto err_clk; goto err_phy;
} }
} }
...@@ -143,7 +143,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) ...@@ -143,7 +143,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Can't register ci_hdrc platform device, err=%d\n", "Can't register ci_hdrc platform device, err=%d\n",
ret); ret);
goto err_clk; goto err_phy;
} }
if (data->usbmisc_data) { if (data->usbmisc_data) {
...@@ -164,6 +164,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) ...@@ -164,6 +164,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
disable_device: disable_device:
ci_hdrc_remove_device(data->ci_pdev); ci_hdrc_remove_device(data->ci_pdev);
err_phy:
if (data->phy)
usb_phy_shutdown(data->phy);
err_clk: err_clk:
clk_disable_unprepare(data->clk); clk_disable_unprepare(data->clk);
return ret; return ret;
......
...@@ -605,6 +605,7 @@ static int ci_hdrc_remove(struct platform_device *pdev) ...@@ -605,6 +605,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
dbg_remove_files(ci); dbg_remove_files(ci);
free_irq(ci->irq, ci); free_irq(ci->irq, ci);
ci_role_destroy(ci); ci_role_destroy(ci);
kfree(ci->hw_bank.regmap);
return 0; return 0;
} }
......
...@@ -1600,6 +1600,8 @@ static void destroy_eps(struct ci_hdrc *ci) ...@@ -1600,6 +1600,8 @@ static void destroy_eps(struct ci_hdrc *ci)
for (i = 0; i < ci->hw_ep_max; i++) { for (i = 0; i < ci->hw_ep_max; i++) {
struct ci_hw_ep *hwep = &ci->ci_hw_ep[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); 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, ...@@ -1667,13 +1669,13 @@ static int ci_udc_stop(struct usb_gadget *gadget,
if (ci->platdata->notify_event) if (ci->platdata->notify_event)
ci->platdata->notify_event(ci, ci->platdata->notify_event(ci,
CI_HDRC_CONTROLLER_STOPPED_EVENT); CI_HDRC_CONTROLLER_STOPPED_EVENT);
ci->driver = NULL;
spin_unlock_irqrestore(&ci->lock, flags); spin_unlock_irqrestore(&ci->lock, flags);
_gadget_stop_activity(&ci->gadget); _gadget_stop_activity(&ci->gadget);
spin_lock_irqsave(&ci->lock, flags); spin_lock_irqsave(&ci->lock, flags);
pm_runtime_put(&ci->gadget.dev); pm_runtime_put(&ci->gadget.dev);
} }
ci->driver = NULL;
spin_unlock_irqrestore(&ci->lock, flags); spin_unlock_irqrestore(&ci->lock, flags);
return 0; return 0;
......
...@@ -742,6 +742,22 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, ...@@ -742,6 +742,22 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
if ((index & ~USB_DIR_IN) == 0) if ((index & ~USB_DIR_IN) == 0)
return 0; return 0;
ret = findintfep(ps->dev, index); 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) if (ret >= 0)
ret = checkintf(ps, ret); ret = checkintf(ps, ret);
break; break;
......
...@@ -3426,6 +3426,9 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state) ...@@ -3426,6 +3426,9 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
unsigned long long u2_pel; unsigned long long u2_pel;
int ret; int ret;
if (udev->state != USB_STATE_CONFIGURED)
return 0;
/* Convert SEL and PEL stored in ns to us */ /* Convert SEL and PEL stored in ns to us */
u1_sel = DIV_ROUND_UP(udev->u1_params.sel, 1000); u1_sel = DIV_ROUND_UP(udev->u1_params.sel, 1000);
u1_pel = DIV_ROUND_UP(udev->u1_params.pel, 1000); u1_pel = DIV_ROUND_UP(udev->u1_params.pel, 1000);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#define PCI_VENDOR_ID_SYNOPSYS 0x16c3 #define PCI_VENDOR_ID_SYNOPSYS 0x16c3
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd
#define PCI_DEVICE_ID_INTEL_BYT 0x0f37 #define PCI_DEVICE_ID_INTEL_BYT 0x0f37
#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
struct dwc3_pci { struct dwc3_pci {
struct device *dev; struct device *dev;
...@@ -189,6 +190,7 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = { ...@@ -189,6 +190,7 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), 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_BYT), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
{ } /* Terminating Entry */ { } /* Terminating Entry */
}; };
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table); MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
......
...@@ -1034,37 +1034,19 @@ struct ffs_sb_fill_data { ...@@ -1034,37 +1034,19 @@ struct ffs_sb_fill_data {
struct ffs_file_perms perms; struct ffs_file_perms perms;
umode_t root_mode; umode_t root_mode;
const char *dev_name; const char *dev_name;
union { struct ffs_data *ffs_data;
/* 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;
};
}; };
static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
{ {
struct ffs_sb_fill_data *data = _data; struct ffs_sb_fill_data *data = _data;
struct inode *inode; struct inode *inode;
struct ffs_data *ffs; struct ffs_data *ffs = data->ffs_data;
ENTER(); ENTER();
/* Initialise data */
ffs = ffs_data_new();
if (unlikely(!ffs))
goto Enomem;
ffs->sb = sb; ffs->sb = sb;
ffs->dev_name = kstrdup(data->dev_name, GFP_KERNEL); data->ffs_data = NULL;
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;
sb->s_fs_info = ffs; sb->s_fs_info = ffs;
sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
...@@ -1080,17 +1062,14 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) ...@@ -1080,17 +1062,14 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
&data->perms); &data->perms);
sb->s_root = d_make_root(inode); sb->s_root = d_make_root(inode);
if (unlikely(!sb->s_root)) if (unlikely(!sb->s_root))
goto Enomem; return -ENOMEM;
/* EP0 file */ /* EP0 file */
if (unlikely(!ffs_sb_create_file(sb, "ep0", ffs, if (unlikely(!ffs_sb_create_file(sb, "ep0", ffs,
&ffs_ep0_operations, NULL))) &ffs_ep0_operations, NULL)))
goto Enomem; return -ENOMEM;
return 0; return 0;
Enomem:
return -ENOMEM;
} }
static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts) 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, ...@@ -1193,6 +1172,7 @@ ffs_fs_mount(struct file_system_type *t, int flags,
struct dentry *rv; struct dentry *rv;
int ret; int ret;
void *ffs_dev; void *ffs_dev;
struct ffs_data *ffs;
ENTER(); ENTER();
...@@ -1200,18 +1180,30 @@ ffs_fs_mount(struct file_system_type *t, int flags, ...@@ -1200,18 +1180,30 @@ ffs_fs_mount(struct file_system_type *t, int flags,
if (unlikely(ret < 0)) if (unlikely(ret < 0))
return ERR_PTR(ret); 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); ffs_dev = functionfs_acquire_dev_callback(dev_name);
if (IS_ERR(ffs_dev)) if (IS_ERR(ffs_dev)) {
return 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); rv = mount_nodev(t, flags, &data, ffs_sb_fill);
if (IS_ERR(rv) && data.ffs_data) {
/* data.ffs_data is set by ffs_sb_fill */
if (IS_ERR(rv))
functionfs_release_dev_callback(data.ffs_data); functionfs_release_dev_callback(data.ffs_data);
ffs_data_put(data.ffs_data);
}
return rv; return rv;
} }
......
...@@ -130,7 +130,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, ...@@ -130,7 +130,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
} }
/* Enable USB controller, 83xx or 8536 */ /* 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); setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
/* Don't need to set host mode here. It will be done by tdi_reset() */ /* 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, ...@@ -232,15 +232,9 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
case FSL_USB2_PHY_ULPI: case FSL_USB2_PHY_ULPI:
if (pdata->have_sysif_regs && pdata->controller_ver) { if (pdata->have_sysif_regs && pdata->controller_ver) {
/* controller version 1.6 or above */ /* controller version 1.6 or above */
clrbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
setbits32(non_ehci + FSL_SOC_USB_CTRL, setbits32(non_ehci + FSL_SOC_USB_CTRL,
ULPI_PHY_CLK_SEL); ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN);
/*
* 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);
} }
portsc |= PORT_PTS_ULPI; portsc |= PORT_PTS_ULPI;
break; break;
...@@ -270,8 +264,9 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, ...@@ -270,8 +264,9 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
if (pdata->have_sysif_regs && pdata->controller_ver && if (pdata->have_sysif_regs && pdata->controller_ver &&
(phy_mode == FSL_USB2_PHY_ULPI)) { (phy_mode == FSL_USB2_PHY_ULPI)) {
/* check PHY_CLK_VALID to get phy clk valid */ /* check PHY_CLK_VALID to get phy clk valid */
if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) { 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"); printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
return -EINVAL; return -EINVAL;
} }
......
...@@ -361,7 +361,7 @@ static struct pci_driver ehci_pci_driver = { ...@@ -361,7 +361,7 @@ static struct pci_driver ehci_pci_driver = {
.remove = usb_hcd_pci_remove, .remove = usb_hcd_pci_remove,
.shutdown = usb_hcd_pci_shutdown, .shutdown = usb_hcd_pci_shutdown,
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
.driver = { .driver = {
.pm = &usb_hcd_pci_pm_ops .pm = &usb_hcd_pci_pm_ops
}, },
......
...@@ -824,13 +824,13 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, ...@@ -824,13 +824,13 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
i = DIV_ROUND_UP(wrap_frame( i = DIV_ROUND_UP(wrap_frame(
cur_frame - urb->start_frame), cur_frame - urb->start_frame),
urb->interval); 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 urb->start_frame = wrap_frame(urb->start_frame
+ i * urb->interval); + i * urb->interval);
i = 0; i = 0;
} else if (i >= urb->number_of_packets) {
ret = -EXDEV;
goto alloc_dmem_failed;
} }
} }
} }
......
...@@ -216,31 +216,26 @@ static int ohci_urb_enqueue ( ...@@ -216,31 +216,26 @@ static int ohci_urb_enqueue (
frame &= ~(ed->interval - 1); frame &= ~(ed->interval - 1);
frame |= ed->branch; frame |= ed->branch;
urb->start_frame = frame; urb->start_frame = frame;
ed->last_iso = frame + ed->interval * (size - 1);
} }
} else if (ed->type == PIPE_ISOCHRONOUS) { } else if (ed->type == PIPE_ISOCHRONOUS) {
u16 next = ohci_frame_no(ohci) + 1; u16 next = ohci_frame_no(ohci) + 1;
u16 frame = ed->last_iso + ed->interval; u16 frame = ed->last_iso + ed->interval;
u16 length = ed->interval * (size - 1);
/* Behind the scheduling threshold? */ /* Behind the scheduling threshold? */
if (unlikely(tick_before(frame, next))) { 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) { if (urb->transfer_flags & URB_ISO_ASAP) {
frame += (next - frame + ed->interval - 1) & frame += (next - frame + ed->interval - 1) &
-ed->interval; -ed->interval;
/* /*
* Not ASAP: Use the next slot in the stream. If * Not ASAP: Use the next slot in the stream,
* the entire URB falls before the threshold, fail. * no matter what.
*/ */
} else { } 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 * Some OHCI hardware doesn't handle late TDs
* correctly. After retiring them it proceeds * correctly. After retiring them it proceeds
...@@ -251,9 +246,16 @@ static int ohci_urb_enqueue ( ...@@ -251,9 +246,16 @@ static int ohci_urb_enqueue (
urb_priv->td_cnt = DIV_ROUND_UP( urb_priv->td_cnt = DIV_ROUND_UP(
(u16) (next - frame), (u16) (next - frame),
ed->interval); 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; urb->start_frame = frame;
ed->last_iso = frame + length;
} }
/* fill the TDs and link them to the ed; and /* 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) ...@@ -41,9 +41,13 @@ finish_urb(struct ohci_hcd *ohci, struct urb *urb, int status)
__releases(ohci->lock) __releases(ohci->lock)
__acquires(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); // ASSERT (urb->hcpriv != 0);
restart:
urb_free_priv (ohci, urb->hcpriv); urb_free_priv (ohci, urb->hcpriv);
urb->hcpriv = NULL; urb->hcpriv = NULL;
if (likely(status == -EINPROGRESS)) if (likely(status == -EINPROGRESS))
...@@ -80,6 +84,21 @@ __acquires(ohci->lock) ...@@ -80,6 +84,21 @@ __acquires(ohci->lock)
ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_IE); ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_IE);
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); 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, ...@@ -546,7 +565,6 @@ td_fill (struct ohci_hcd *ohci, u32 info,
td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000); td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000);
*ohci_hwPSWp(ohci, td, 0) = cpu_to_hc16 (ohci, *ohci_hwPSWp(ohci, td, 0) = cpu_to_hc16 (ohci,
(data & 0x0FFF) | 0xE000); (data & 0x0FFF) | 0xE000);
td->ed->last_iso = info & 0xffff;
} else { } else {
td->hwCBP = cpu_to_hc32 (ohci, data); td->hwCBP = cpu_to_hc32 (ohci, data);
} }
...@@ -996,7 +1014,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick) ...@@ -996,7 +1014,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
urb_priv->td_cnt++; urb_priv->td_cnt++;
/* if URB is done, clean up */ /* 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; modified = completed = 1;
finish_urb(ohci, urb, 0); finish_urb(ohci, urb, 0);
} }
...@@ -1086,7 +1104,7 @@ static void takeback_td(struct ohci_hcd *ohci, struct td *td) ...@@ -1086,7 +1104,7 @@ static void takeback_td(struct ohci_hcd *ohci, struct td *td)
urb_priv->td_cnt++; urb_priv->td_cnt++;
/* If all this urb's TDs are done, call complete() */ /* 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); finish_urb(ohci, urb, status);
/* clean schedule: unlink EDs that are no longer busy */ /* clean schedule: unlink EDs that are no longer busy */
......
...@@ -293,7 +293,7 @@ static struct pci_driver uhci_pci_driver = { ...@@ -293,7 +293,7 @@ static struct pci_driver uhci_pci_driver = {
.remove = usb_hcd_pci_remove, .remove = usb_hcd_pci_remove,
.shutdown = uhci_shutdown, .shutdown = uhci_shutdown,
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
.driver = { .driver = {
.pm = &usb_hcd_pci_pm_ops .pm = &usb_hcd_pci_pm_ops
}, },
......
...@@ -1303,7 +1303,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, ...@@ -1303,7 +1303,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
} }
/* Fell behind? */ /* 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 */ /* USB_ISO_ASAP: Round up to the first available slot */
if (urb->transfer_flags & URB_ISO_ASAP) if (urb->transfer_flags & URB_ISO_ASAP)
...@@ -1311,13 +1311,17 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, ...@@ -1311,13 +1311,17 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
-qh->period; -qh->period;
/* /*
* Not ASAP: Use the next slot in the stream. If * Not ASAP: Use the next slot in the stream,
* the entire URB falls before the threshold, fail. * no matter what.
*/ */
else if (!uhci_frame_before_eq(next, else if (!uhci_frame_before_eq(next,
frame + (urb->number_of_packets - 1) * frame + (urb->number_of_packets - 1) *
qh->period)) 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) ...@@ -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) if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
xhci_queue_stop_endpoint(xhci, slot_id, i, suspend); 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); list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend); xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
xhci_ring_cmd_db(xhci); xhci_ring_cmd_db(xhci);
...@@ -552,11 +552,15 @@ void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex) ...@@ -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, * - Mark a port as being done with device resume,
* and ring the endpoint doorbells. * and ring the endpoint doorbells.
* - Stop the Synopsys redriver Compliance Mode polling. * - 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, static u32 xhci_get_port_status(struct usb_hcd *hcd,
struct xhci_bus_state *bus_state, struct xhci_bus_state *bus_state,
__le32 __iomem **port_array, __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); struct xhci_hcd *xhci = hcd_to_xhci(hcd);
u32 status = 0; u32 status = 0;
...@@ -591,21 +595,42 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, ...@@ -591,21 +595,42 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
return 0xffffffff; return 0xffffffff;
if (time_after_eq(jiffies, if (time_after_eq(jiffies,
bus_state->resume_done[wIndex])) { bus_state->resume_done[wIndex])) {
int time_left;
xhci_dbg(xhci, "Resume USB2 port %d\n", xhci_dbg(xhci, "Resume USB2 port %d\n",
wIndex + 1); wIndex + 1);
bus_state->resume_done[wIndex] = 0; bus_state->resume_done[wIndex] = 0;
clear_bit(wIndex, &bus_state->resuming_ports); clear_bit(wIndex, &bus_state->resuming_ports);
set_bit(wIndex, &bus_state->rexit_ports);
xhci_set_link_state(xhci, port_array, wIndex, xhci_set_link_state(xhci, port_array, wIndex,
XDEV_U0); XDEV_U0);
xhci_dbg(xhci, "set port %d resume\n",
wIndex + 1); spin_unlock_irqrestore(&xhci->lock, flags);
slot_id = xhci_find_slot_id_by_port(hcd, xhci, time_left = wait_for_completion_timeout(
wIndex + 1); &bus_state->rexit_done[wIndex],
if (!slot_id) { msecs_to_jiffies(
xhci_dbg(xhci, "slot_id is zero\n"); XHCI_MAX_REXIT_TIMEOUT));
return 0xffffffff; 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->port_c_suspend |= 1 << wIndex;
bus_state->suspended_ports &= ~(1 << wIndex); bus_state->suspended_ports &= ~(1 << wIndex);
} else { } else {
...@@ -728,7 +753,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -728,7 +753,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break; break;
} }
status = xhci_get_port_status(hcd, bus_state, port_array, status = xhci_get_port_status(hcd, bus_state, port_array,
wIndex, temp); wIndex, temp, flags);
if (status == 0xffffffff) if (status == 0xffffffff)
goto error; goto error;
......
...@@ -2428,6 +2428,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) ...@@ -2428,6 +2428,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
for (i = 0; i < USB_MAXCHILDREN; ++i) { for (i = 0; i < USB_MAXCHILDREN; ++i) {
xhci->bus_state[0].resume_done[i] = 0; xhci->bus_state[0].resume_done[i] = 0;
xhci->bus_state[1].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)) if (scratchpad_alloc(xhci, flags))
......
...@@ -351,7 +351,7 @@ static struct pci_driver xhci_pci_driver = { ...@@ -351,7 +351,7 @@ static struct pci_driver xhci_pci_driver = {
/* suspend and resume implemented later */ /* suspend and resume implemented later */
.shutdown = usb_hcd_pci_shutdown, .shutdown = usb_hcd_pci_shutdown,
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
.driver = { .driver = {
.pm = &usb_hcd_pci_pm_ops .pm = &usb_hcd_pci_pm_ops
}, },
......
...@@ -123,6 +123,16 @@ static int enqueue_is_link_trb(struct xhci_ring *ring) ...@@ -123,6 +123,16 @@ static int enqueue_is_link_trb(struct xhci_ring *ring)
return TRB_TYPE_LINK_LE32(link->control); 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 /* 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 * TRB is in a new segment. This does not skip over link TRBs, and it does not
* effect the ring dequeue or enqueue pointers. * effect the ring dequeue or enqueue pointers.
...@@ -859,8 +869,12 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, ...@@ -859,8 +869,12 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
/* Otherwise ring the doorbell(s) to restart queued transfers */ /* Otherwise ring the doorbell(s) to restart queued transfers */
ring_doorbell_for_active_rings(xhci, slot_id, ep_index); 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. * 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, ...@@ -1414,6 +1428,12 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
inc_deq(xhci, xhci->cmd_ring); inc_deq(xhci, xhci->cmd_ring);
return; 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]) switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])
...@@ -1743,6 +1763,19 @@ static void handle_port_status(struct xhci_hcd *xhci, ...@@ -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) if (hcd->speed != HCD_USB3)
xhci_test_and_clear_bit(xhci, port_array, faked_port_index, xhci_test_and_clear_bit(xhci, port_array, faked_port_index,
PORT_PLC); PORT_PLC);
......
...@@ -2598,15 +2598,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, ...@@ -2598,15 +2598,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
if (command) { if (command) {
cmd_completion = command->completion; cmd_completion = command->completion;
cmd_status = &command->status; cmd_status = &command->status;
command->command_trb = xhci->cmd_ring->enqueue; command->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
/* 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;
list_add_tail(&command->cmd_list, &virt_dev->cmd_list); list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
} else { } else {
cmd_completion = &virt_dev->cmd_completion; cmd_completion = &virt_dev->cmd_completion;
...@@ -2614,7 +2606,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, ...@@ -2614,7 +2606,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
} }
init_completion(cmd_completion); init_completion(cmd_completion);
cmd_trb = xhci->cmd_ring->dequeue; cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
if (!ctx_change) if (!ctx_change)
ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma, ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
udev->slot_id, must_succeed); udev->slot_id, must_succeed);
...@@ -3439,14 +3431,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -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 */ /* Attempt to submit the Reset Device command to the command ring */
spin_lock_irqsave(&xhci->lock, flags); spin_lock_irqsave(&xhci->lock, flags);
reset_device_cmd->command_trb = xhci->cmd_ring->enqueue; reset_device_cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
/* 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;
list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list); list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
ret = xhci_queue_reset_device(xhci, slot_id); ret = xhci_queue_reset_device(xhci, slot_id);
...@@ -3650,7 +3635,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -3650,7 +3635,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
union xhci_trb *cmd_trb; union xhci_trb *cmd_trb;
spin_lock_irqsave(&xhci->lock, flags); 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); ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0);
if (ret) { if (ret) {
spin_unlock_irqrestore(&xhci->lock, flags); spin_unlock_irqrestore(&xhci->lock, flags);
...@@ -3785,7 +3770,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -3785,7 +3770,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
slot_ctx->dev_info >> 27); slot_ctx->dev_info >> 27);
spin_lock_irqsave(&xhci->lock, flags); 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, ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
udev->slot_id); udev->slot_id);
if (ret) { if (ret) {
......
...@@ -1412,8 +1412,18 @@ struct xhci_bus_state { ...@@ -1412,8 +1412,18 @@ struct xhci_bus_state {
unsigned long resume_done[USB_MAXCHILDREN]; unsigned long resume_done[USB_MAXCHILDREN];
/* which ports have started to resume */ /* which ports have started to resume */
unsigned long resuming_ports; 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) static inline unsigned int hcd_index(struct usb_hcd *hcd)
{ {
if (hcd->speed == HCD_USB3) if (hcd->speed == HCD_USB3)
...@@ -1840,6 +1850,7 @@ int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, ...@@ -1840,6 +1850,7 @@ int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
union xhci_trb *cmd_trb); union xhci_trb *cmd_trb);
void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
unsigned int ep_index, unsigned int stream_id); unsigned int ep_index, unsigned int stream_id);
union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring);
/* xHCI roothub code */ /* xHCI roothub code */
void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment