diff options
| -rw-r--r-- | drivers/usb/core/hcd.c | 35 | ||||
| -rw-r--r-- | drivers/usb/core/usb.c | 31 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.c | 58 | ||||
| -rw-r--r-- | include/linux/usb.h | 7 | ||||
| -rw-r--r-- | include/linux/usb/hcd.h | 13 |
5 files changed, 144 insertions, 0 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 374e79dccc2c..5cc655908fda 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2226,6 +2226,41 @@ int usb_hcd_sec_event_ring_cleanup(struct usb_device *udev, /*-------------------------------------------------------------------------*/ +dma_addr_t +usb_hcd_get_sec_event_ring_dma_addr(struct usb_device *udev, + unsigned intr_num) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (!HCD_RH_RUNNING(hcd)) + return 0; + + return hcd->driver->get_sec_event_ring_dma_addr(hcd, intr_num); +} + +dma_addr_t +usb_hcd_get_dcba_dma_addr(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (!HCD_RH_RUNNING(hcd)) + return 0; + + return hcd->driver->get_dcba_dma_addr(hcd, udev); +} + +dma_addr_t +usb_hcd_get_xfer_ring_dma_addr(struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (!HCD_RH_RUNNING(hcd)) + return 0; + + return hcd->driver->get_xfer_ring_dma_addr(hcd, udev, ep); +} + #ifdef CONFIG_PM int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 3b14f3919d0a..b43d542e3bd4 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -689,6 +689,37 @@ int usb_sec_event_ring_cleanup(struct usb_device *dev, } EXPORT_SYMBOL(usb_sec_event_ring_cleanup); +dma_addr_t +usb_get_sec_event_ring_dma_addr(struct usb_device *dev, + unsigned intr_num) +{ + if (dev->state == USB_STATE_NOTATTACHED) + return 0; + + return usb_hcd_get_sec_event_ring_dma_addr(dev, intr_num); +} +EXPORT_SYMBOL(usb_get_sec_event_ring_dma_addr); + +dma_addr_t +usb_get_dcba_dma_addr(struct usb_device *dev) +{ + if (dev->state == USB_STATE_NOTATTACHED) + return 0; + + return usb_hcd_get_dcba_dma_addr(dev); +} +EXPORT_SYMBOL(usb_get_dcba_dma_addr); + +dma_addr_t usb_get_xfer_ring_dma_addr(struct usb_device *dev, + struct usb_host_endpoint *ep) +{ + if (dev->state == USB_STATE_NOTATTACHED) + return 0; + + return usb_hcd_get_xfer_ring_dma_addr(dev, ep); +} +EXPORT_SYMBOL(usb_get_xfer_ring_dma_addr); + /*-------------------------------------------------------------------*/ /* * __usb_get_extra_descriptor() finds a descriptor of specific type in the diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8bc1ff067ebe..42f74d55e3bd 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4968,6 +4968,61 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) } EXPORT_SYMBOL_GPL(xhci_gen_setup); +dma_addr_t xhci_get_sec_event_ring_dma_addr(struct usb_hcd *hcd, + unsigned intr_num) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + if (intr_num > xhci->max_interrupters) { + xhci_err(xhci, "intr num %d > max intrs %d\n", intr_num, + xhci->max_interrupters); + return 0; + } + + if (!(xhci->xhc_state & XHCI_STATE_HALTED) && + xhci->sec_event_ring && xhci->sec_event_ring[intr_num] + && xhci->sec_event_ring[intr_num]->first_seg) + return xhci->sec_event_ring[intr_num]->first_seg->dma; + + return 0; +} + +dma_addr_t xhci_get_dcba_dma_addr(struct usb_hcd *hcd, + struct usb_device *udev) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + if (!(xhci->xhc_state & XHCI_STATE_HALTED) && xhci->dcbaa) + return xhci->dcbaa->dev_context_ptrs[udev->slot_id]; + + return 0; +} + +dma_addr_t xhci_get_xfer_ring_dma_addr(struct usb_hcd *hcd, + struct usb_device *udev, struct usb_host_endpoint *ep) +{ + int ret; + unsigned int ep_index; + struct xhci_virt_device *virt_dev; + + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); + if (ret <= 0) { + xhci_err(xhci, "%s: invalid args\n", __func__); + return 0; + } + + virt_dev = xhci->devs[udev->slot_id]; + ep_index = xhci_get_endpoint_index(&ep->desc); + + if (virt_dev->eps[ep_index].ring && + virt_dev->eps[ep_index].ring->first_seg) + return virt_dev->eps[ep_index].ring->first_seg->dma; + + return 0; +} + static const struct hc_driver xhci_hc_driver = { .description = "xhci-hcd", .product_desc = "xHCI Host Controller", @@ -5029,6 +5084,9 @@ static const struct hc_driver xhci_hc_driver = { .find_raw_port_number = xhci_find_raw_port_number, .sec_event_ring_setup = xhci_sec_event_ring_setup, .sec_event_ring_cleanup = xhci_sec_event_ring_cleanup, + .get_sec_event_ring_dma_addr = xhci_get_sec_event_ring_dma_addr, + .get_xfer_ring_dma_addr = xhci_get_xfer_ring_dma_addr, + .get_dcba_dma_addr = xhci_get_dcba_dma_addr, }; void xhci_init_driver(struct hc_driver *drv, diff --git a/include/linux/usb.h b/include/linux/usb.h index a2e367de268d..246945be000c 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -739,6 +739,13 @@ extern int usb_sec_event_ring_setup(struct usb_device *dev, extern int usb_sec_event_ring_cleanup(struct usb_device *dev, unsigned intr_num); +extern dma_addr_t +usb_get_sec_event_ring_dma_addr(struct usb_device *dev, + unsigned intr_num); +extern dma_addr_t usb_get_dcba_dma_addr(struct usb_device *dev); +extern dma_addr_t usb_get_xfer_ring_dma_addr(struct usb_device *dev, + struct usb_host_endpoint *ep); + /* Sets up a group of bulk endpoints to support multiple stream IDs. */ extern int usb_alloc_streams(struct usb_interface *interface, struct usb_host_endpoint **eps, unsigned int num_eps, diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 56c7fba6dcdf..3740366d9fc5 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -398,6 +398,12 @@ struct hc_driver { int (*sec_event_ring_setup)(struct usb_hcd *hcd, unsigned intr_num); int (*sec_event_ring_cleanup)(struct usb_hcd *hcd, unsigned intr_num); + dma_addr_t (*get_sec_event_ring_dma_addr)(struct usb_hcd *hcd, + unsigned intr_num); + dma_addr_t (*get_xfer_ring_dma_addr)(struct usb_hcd *hcd, + struct usb_device *udev, struct usb_host_endpoint *ep); + dma_addr_t (*get_dcba_dma_addr)(struct usb_hcd *hcd, + struct usb_device *udev); }; static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd) @@ -440,6 +446,13 @@ extern int usb_hcd_sec_event_ring_setup(struct usb_device *udev, unsigned intr_num); extern int usb_hcd_sec_event_ring_cleanup(struct usb_device *udev, unsigned intr_num); +extern dma_addr_t +usb_hcd_get_sec_event_ring_dma_addr(struct usb_device *udev, + unsigned intr_num); +extern dma_addr_t usb_hcd_get_dcba_dma_addr(struct usb_device *udev); +extern dma_addr_t +usb_hcd_get_xfer_ring_dma_addr(struct usb_device *udev, + struct usb_host_endpoint *ep); extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, struct device *dev, const char *bus_name); |
