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

Commit 787b74a4 authored by Hemant Kumar's avatar Hemant Kumar
Browse files

usb: xhci: Add helper APIs to return xhci dma addresses



dma address of secondary event ring, transfer ring and
device context base address are required to pass to
remote entity. Remote entity uses these addresses to
program xhci controller registers.

Change-Id: Ie0756d646a396a11b41b93e886bca9aff636ee5d
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 8d48fb82
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -2257,6 +2257,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 int 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)
+31 −0
Original line number Diff line number Diff line
@@ -845,6 +845,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 int 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
+58 −0
Original line number Diff line number Diff line
@@ -5109,6 +5109,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 int 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",
@@ -5171,6 +5226,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,
+6 −0
Original line number Diff line number Diff line
@@ -831,6 +831,12 @@ extern int usb_sec_event_ring_setup(struct usb_device *dev,
extern int usb_sec_event_ring_cleanup(struct usb_device *dev,
	unsigned int intr_num);

extern dma_addr_t usb_get_sec_event_ring_dma_addr(struct usb_device *dev,
	unsigned int 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,
+11 −0
Original line number Diff line number Diff line
@@ -410,6 +410,12 @@ struct hc_driver {
	int (*sec_event_ring_setup)(struct usb_hcd *hcd, unsigned int intr_num);
	int (*sec_event_ring_cleanup)(struct usb_hcd *hcd,
			unsigned int intr_num);
	dma_addr_t (*get_sec_event_ring_dma_addr)(struct usb_hcd *hcd,
			unsigned int 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)
@@ -452,6 +458,11 @@ extern int usb_hcd_sec_event_ring_setup(struct usb_device *udev,
	unsigned int intr_num);
extern int usb_hcd_sec_event_ring_cleanup(struct usb_device *udev,
	unsigned int intr_num);
extern dma_addr_t usb_hcd_get_sec_event_ring_dma_addr(struct usb_device *udev,
		unsigned int 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);

struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver,
		struct device *sysdev, struct device *dev, const char *bus_name,