Skip to content

Commit

Permalink
Merge tag 'usb-3.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
torvalds committed Sep 29, 2013
2 parents 26c019f + 85601f8 commit 30ceb4e
Show file tree
Hide file tree
Showing 21 changed files with 201 additions and 107 deletions.
2 changes: 1 addition & 1 deletion drivers/usb/chipidea/Kconfig
Original file line number Diff line number Diff line change
@@ -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
Expand Down
7 changes: 5 additions & 2 deletions drivers/usb/chipidea/ci_hdrc_imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand All @@ -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) {
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/chipidea/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 3 additions & 1 deletion drivers/usb/chipidea/udc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions drivers/usb/core/devio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/dwc3/dwc3-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
60 changes: 26 additions & 34 deletions drivers/usb/gadget/f_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -1193,25 +1172,38 @@ ffs_fs_mount(struct file_system_type *t, int flags,
struct dentry *rv;
int ret;
void *ffs_dev;
struct ffs_data *ffs;

ENTER();

ret = ffs_fs_parse_opts(&data, opts);
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;
}

Expand Down
17 changes: 6 additions & 11 deletions drivers/usb/host/ehci-fsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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() */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/host/ehci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
Expand Down
8 changes: 4 additions & 4 deletions drivers/usb/host/imx21-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
Expand Down
22 changes: 12 additions & 10 deletions drivers/usb/host/ohci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading

0 comments on commit 30ceb4e

Please sign in to comment.