Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18e5c7ed authored by Hemant Kumar's avatar Hemant Kumar Committed by Jack Pham
Browse files

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: default avatarHemant Kumar <hemantk@codeaurora.org>
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent d65ac36f
Loading
Loading
Loading
Loading
+83 −0
Original line number Diff line number Diff line
@@ -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",
+18 −1
Original line number Diff line number Diff line
@@ -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 */