diff options
author | Andiry Xu <andiry.xu@amd.com> | 2010-10-14 18:22:45 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 21:22:11 +0400 |
commit | 64927730c66333c9d5987aa72a0e6d44ed91cec7 (patch) | |
tree | edc1da4d69cbd66d9ba1cff75a5738900d2e8cef /drivers/usb | |
parent | ac9dfe9cdda4eb42ecaa9f13b0fee518e0b6518e (diff) | |
download | linux-64927730c66333c9d5987aa72a0e6d44ed91cec7.tar.xz |
USB: xHCI: Add pointer to udev in struct xhci_virt_device
Add a pointer to udev in struct xhci_virt_device. When allocate a new
virt_device, make the pointer point to the corresponding udev.
Modify xhci_check_args(), check if virt_dev->udev matches the target udev,
to make sure command is issued to the right device.
Signed-off-by: Andiry Xu <andiry.xu@amd.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 83 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 1 |
3 files changed, 36 insertions, 49 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 4e51343ddffc..be901808e474 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -778,6 +778,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, init_completion(&dev->cmd_completion); INIT_LIST_HEAD(&dev->cmd_list); + dev->udev = udev; /* Point to output device context in dcbaa. */ xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d5c550ea3e68..0bec04070334 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -607,7 +607,11 @@ unsigned int xhci_last_valid_endpoint(u32 added_ctxs) * returns 0 this is a root hub; returns -EINVAL for NULL pointers. */ int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev, - struct usb_host_endpoint *ep, int check_ep, const char *func) { + struct usb_host_endpoint *ep, int check_ep, bool check_virt_dev, + const char *func) { + struct xhci_hcd *xhci; + struct xhci_virt_device *virt_dev; + if (!hcd || (check_ep && !ep) || !udev) { printk(KERN_DEBUG "xHCI %s called with invalid args\n", func); @@ -618,11 +622,24 @@ int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev, func); return 0; } - if (!udev->slot_id) { - printk(KERN_DEBUG "xHCI %s called with unaddressed device\n", - func); - return -EINVAL; + + if (check_virt_dev) { + xhci = hcd_to_xhci(hcd); + if (!udev->slot_id || !xhci->devs + || !xhci->devs[udev->slot_id]) { + printk(KERN_DEBUG "xHCI %s called with unaddressed " + "device\n", func); + return -EINVAL; + } + + virt_dev = xhci->devs[udev->slot_id]; + if (virt_dev->udev != udev) { + printk(KERN_DEBUG "xHCI %s called with udev and " + "virt_dev does not match\n", func); + return -EINVAL; + } } + return 1; } @@ -704,18 +721,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) struct urb_priv *urb_priv; int size, i; - if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0) + if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, + true, true, __func__) <= 0) return -EINVAL; slot_id = urb->dev->slot_id; ep_index = xhci_get_endpoint_index(&urb->ep->desc); - if (!xhci->devs || !xhci->devs[slot_id]) { - if (!in_interrupt()) - dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n"); - ret = -EINVAL; - goto exit; - } if (!HCD_HW_ACCESSIBLE(hcd)) { if (!in_interrupt()) xhci_dbg(xhci, "urb submitted during PCI suspend\n"); @@ -991,7 +1003,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, u32 new_add_flags, new_drop_flags, new_slot_info; int ret; - ret = xhci_check_args(hcd, udev, ep, 1, __func__); + ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); if (ret <= 0) return ret; xhci = hcd_to_xhci(hcd); @@ -1004,12 +1016,6 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, return 0; } - if (!xhci->devs || !xhci->devs[udev->slot_id]) { - xhci_warn(xhci, "xHCI %s called with unaddressed device\n", - __func__); - return -EINVAL; - } - in_ctx = xhci->devs[udev->slot_id]->in_ctx; out_ctx = xhci->devs[udev->slot_id]->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); @@ -1078,7 +1084,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, u32 new_add_flags, new_drop_flags, new_slot_info; int ret = 0; - ret = xhci_check_args(hcd, udev, ep, 1, __func__); + ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); if (ret <= 0) { /* So we won't queue a reset ep command for a root hub */ ep->hcpriv = NULL; @@ -1098,12 +1104,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, return 0; } - if (!xhci->devs || !xhci->devs[udev->slot_id]) { - xhci_warn(xhci, "xHCI %s called with unaddressed device\n", - __func__); - return -EINVAL; - } - in_ctx = xhci->devs[udev->slot_id]->in_ctx; out_ctx = xhci->devs[udev->slot_id]->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); @@ -1346,16 +1346,11 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_input_control_ctx *ctrl_ctx; struct xhci_slot_ctx *slot_ctx; - ret = xhci_check_args(hcd, udev, NULL, 0, __func__); + ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); if (ret <= 0) return ret; xhci = hcd_to_xhci(hcd); - if (!udev->slot_id || !xhci->devs || !xhci->devs[udev->slot_id]) { - xhci_warn(xhci, "xHCI %s called with unaddressed device\n", - __func__); - return -EINVAL; - } xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev); virt_dev = xhci->devs[udev->slot_id]; @@ -1405,16 +1400,11 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_virt_device *virt_dev; int i, ret; - ret = xhci_check_args(hcd, udev, NULL, 0, __func__); + ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); if (ret <= 0) return; xhci = hcd_to_xhci(hcd); - if (!xhci->devs || !xhci->devs[udev->slot_id]) { - xhci_warn(xhci, "xHCI %s called with unaddressed device\n", - __func__); - return; - } xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev); virt_dev = xhci->devs[udev->slot_id]; /* Free any rings allocated for added endpoints */ @@ -1575,7 +1565,7 @@ static int xhci_check_streams_endpoint(struct xhci_hcd *xhci, if (!ep) return -EINVAL; - ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, __func__); + ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, true, __func__); if (ret <= 0) return -EINVAL; if (ep->ss_ep_comp.bmAttributes == 0) { @@ -1965,17 +1955,12 @@ int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev) int timeleft; int last_freed_endpoint; - ret = xhci_check_args(hcd, udev, NULL, 0, __func__); + ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); if (ret <= 0) return ret; xhci = hcd_to_xhci(hcd); slot_id = udev->slot_id; virt_dev = xhci->devs[slot_id]; - if (!virt_dev) { - xhci_dbg(xhci, "%s called with invalid slot ID %u\n", - __func__, slot_id); - return -EINVAL; - } xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id); /* Allocate the command structure that holds the struct completion. @@ -2077,13 +2062,13 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_virt_device *virt_dev; unsigned long flags; u32 state; - int i; + int i, ret; - if (udev->slot_id == 0) + ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); + if (ret <= 0) return; + virt_dev = xhci->devs[udev->slot_id]; - if (!virt_dev) - return; /* Stop any wayward timer functions (which may grab the lock) */ for (i = 0; i < 31; ++i) { diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 34a60d9f056a..f03f140a7d9a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -731,6 +731,7 @@ struct xhci_virt_ep { }; struct xhci_virt_device { + struct usb_device *udev; /* * Commands to the hardware are passed an "input context" that * tells the hardware what to change in its data structures. |