mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 06:09:23 -04:00
usb: xhci: Add helper APIs to return xhci dma addresses
Add APIs to get physical and mapped DMA addresses of
secondary event ring, transfer ring and device context
base addresses which are required to pass to remote entity.
The remote entity uses these addresses to in order to
program the xHC from its context.
This commit also squashes in the following change:
usb: Add support to handle USB SMMU S1 address
Change-Id: Ie0756d646a396a11b41b93e886bca9aff636ee5d
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Signed-off-by: Jack Pham <jackp@codeaurora.org>
This commit is contained in:
parent
d65ac36f1f
commit
18e5c7eddd
2 changed files with 101 additions and 1 deletions
|
|
@ -5300,6 +5300,89 @@ static void xhci_clear_tt_buffer_complete(struct usb_hcd *hcd,
|
|||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
}
|
||||
|
||||
phys_addr_t xhci_get_sec_event_ring_phys_addr(struct usb_device *udev,
|
||||
unsigned int intr_num, dma_addr_t *dma)
|
||||
{
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
struct device *dev = hcd->self.sysdev;
|
||||
struct sg_table sgt;
|
||||
phys_addr_t pa;
|
||||
|
||||
if (udev->state == USB_STATE_NOTATTACHED || !HCD_RH_RUNNING(hcd))
|
||||
return 0;
|
||||
|
||||
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) {
|
||||
|
||||
dma_get_sgtable(dev, &sgt,
|
||||
xhci->sec_event_ring[intr_num]->first_seg->trbs,
|
||||
xhci->sec_event_ring[intr_num]->first_seg->dma,
|
||||
TRB_SEGMENT_SIZE);
|
||||
|
||||
*dma = xhci->sec_event_ring[intr_num]->first_seg->dma;
|
||||
|
||||
pa = page_to_phys(sg_page(sgt.sgl));
|
||||
sg_free_table(&sgt);
|
||||
|
||||
return pa;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(xhci_get_sec_event_ring_phys_addr);
|
||||
|
||||
phys_addr_t xhci_get_xfer_ring_phys_addr(struct usb_device *udev,
|
||||
struct usb_host_endpoint *ep, dma_addr_t *dma)
|
||||
{
|
||||
int ret;
|
||||
unsigned int ep_index;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct device *dev = hcd->self.sysdev;
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
struct sg_table sgt;
|
||||
phys_addr_t pa;
|
||||
|
||||
if (udev->state == USB_STATE_NOTATTACHED || !HCD_RH_RUNNING(hcd))
|
||||
return 0;
|
||||
|
||||
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) {
|
||||
|
||||
dma_get_sgtable(dev, &sgt,
|
||||
virt_dev->eps[ep_index].ring->first_seg->trbs,
|
||||
virt_dev->eps[ep_index].ring->first_seg->dma,
|
||||
TRB_SEGMENT_SIZE);
|
||||
|
||||
*dma = virt_dev->eps[ep_index].ring->first_seg->dma;
|
||||
|
||||
pa = page_to_phys(sg_page(sgt.sgl));
|
||||
sg_free_table(&sgt);
|
||||
|
||||
return pa;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(xhci_get_xfer_ring_phys_addr);
|
||||
|
||||
static const struct hc_driver xhci_hc_driver = {
|
||||
.description = "xhci-hcd",
|
||||
.product_desc = "xHCI Host Controller",
|
||||
|
|
|
|||
|
|
@ -8,11 +8,15 @@
|
|||
#ifndef __LINUX_XHCI_SEC_H
|
||||
#define __LINUX_XHCI_SEC_H
|
||||
|
||||
struct usb_device;
|
||||
#include <linux/usb.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_XHCI_HCD)
|
||||
int xhci_sec_event_ring_setup(struct usb_device *udev, unsigned int intr_num);
|
||||
int xhci_sec_event_ring_cleanup(struct usb_device *udev, unsigned int intr_num);
|
||||
phys_addr_t xhci_get_sec_event_ring_phys_addr(struct usb_device *udev,
|
||||
unsigned int intr_num, dma_addr_t *dma);
|
||||
phys_addr_t xhci_get_xfer_ring_phys_addr(struct usb_device *udev,
|
||||
struct usb_host_endpoint *ep, dma_addr_t *dma);
|
||||
#else
|
||||
static inline int xhci_sec_event_ring_setup(struct usb_device *udev,
|
||||
unsigned int intr_num);
|
||||
|
|
@ -25,6 +29,19 @@ static inline int xhci_sec_event_ring_cleanup(struct usb_device *udev,
|
|||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline phys_addr_t xhci_get_sec_event_ring_phys_addr(
|
||||
struct usb_device *udev, unsigned int intr_num,
|
||||
dma_addr_t *dma)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline phys_addr_t xhci_get_xfer_ring_phys_addr(struct usb_device *udev,
|
||||
struct usb_host_endpoint *ep, dma_addr_t *dma)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_XHCI_SEC_H */
|
||||
|
|
|
|||
Loading…
Reference in a new issue