From 27ac6136bc8a384360a83d5220108b4151c8b5e9 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Fri, 22 Sep 2017 15:03:45 -0700 Subject: [PATCH] ANDROID: GKI: usb: Add support to handle USB SMMU S1 address Update helper APIs to return physical address as well as USB SMMU stage 1 address. Physical address is used to map it to iova for remote processor. S1 address is used by xHC. Get sg table containing one or mode page sized physical address corresponding to S1 address for event ring, xfer ring and xfer buffers using dma_get_sgtable(). Accordingly update QMI response buffer for XHCI event ring, xfer ring memory info and xfer buffer. Change-Id: I6c9ea39d8a87a5bdc5a760d2a1ca85ab3024d985 Signed-off-by: Hemant Kumar Signed-off-by: Mayank Rana (cherry picked from commit 3e3d0ab1829b80c4c8c9b0a2d208ee096247a962) Signed-off-by: Mark Salyzyn Bug: 154042109 --- drivers/usb/core/hcd.c | 16 ++++++------- drivers/usb/core/usb.c | 18 +++++++-------- drivers/usb/host/xhci.c | 51 ++++++++++++++++++++++++++++++++--------- include/linux/usb.h | 8 +++---- include/linux/usb/hcd.h | 17 +++++++------- 5 files changed, 70 insertions(+), 40 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 8e7a846ae688..ebc4a84a2221 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2257,28 +2257,28 @@ 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) +phys_addr_t +usb_hcd_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); if (!HCD_RH_RUNNING(hcd)) return 0; - return hcd->driver->get_sec_event_ring_dma_addr(hcd, intr_num); + return hcd->driver->get_sec_event_ring_phys_addr(hcd, intr_num, dma); } -dma_addr_t -usb_hcd_get_xfer_ring_dma_addr(struct usb_device *udev, - unsigned int intr_num) +phys_addr_t +usb_hcd_get_xfer_ring_phys_addr(struct usb_device *udev, + struct usb_host_endpoint *ep, dma_addr_t *dma) { 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); + return hcd->driver->get_xfer_ring_phys_addr(hcd, udev, ep, dma); } int usb_hcd_get_controller_id(struct usb_device *udev) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 7822b8b44ffd..35f632165c8f 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -842,26 +842,26 @@ 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) +phys_addr_t +usb_get_sec_event_ring_phys_addr(struct usb_device *dev, + unsigned int intr_num, dma_addr_t *dma) { if (dev->state == USB_STATE_NOTATTACHED) return 0; - return usb_hcd_get_sec_event_ring_dma_addr(dev, intr_num); + return usb_hcd_get_sec_event_ring_phys_addr(dev, intr_num, dma); } -EXPORT_SYMBOL_GPL(usb_get_sec_event_ring_dma_addr); +EXPORT_SYMBOL_GPL(usb_get_sec_event_ring_phys_addr); -dma_addr_t usb_get_xfer_ring_dma_addr(struct usb_device *dev, - struct usb_host_endpoint *ep) +phys_addr_t usb_get_xfer_ring_phys_addr(struct usb_device *dev, + struct usb_host_endpoint *ep, dma_addr_t *dma) { if (dev->state == USB_STATE_NOTATTACHED) return 0; - return usb_hcd_get_xfer_ring_dma_addr(dev, ep); + return usb_hcd_get_xfer_ring_phys_addr(dev, ep, dma); } -EXPORT_SYMBOL_GPL(usb_get_xfer_ring_dma_addr); +EXPORT_SYMBOL_GPL(usb_get_xfer_ring_phys_addr); /** * usb_get_controller_id - returns the host controller id. diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f8ea67ac9c84..5929e2b566b4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -5183,10 +5183,13 @@ 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) +static phys_addr_t xhci_get_sec_event_ring_phys_addr(struct usb_hcd *hcd, + unsigned int intr_num, dma_addr_t *dma) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct device *dev = hcd->self.sysdev; + struct sg_table sgt; + phys_addr_t pa; if (intr_num > xhci->max_interrupters) { xhci_err(xhci, "intr num %d > max intrs %d\n", intr_num, @@ -5196,20 +5199,34 @@ dma_addr_t xhci_get_sec_event_ring_dma_addr(struct usb_hcd *hcd, 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; + && 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; } -dma_addr_t xhci_get_xfer_ring_dma_addr(struct usb_hcd *hcd, - struct usb_device *udev, struct usb_host_endpoint *ep) +static phys_addr_t xhci_get_xfer_ring_phys_addr(struct usb_hcd *hcd, + 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 device *dev = hcd->self.sysdev; struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct sg_table sgt; + phys_addr_t pa; ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); if (ret <= 0) { @@ -5221,8 +5238,20 @@ dma_addr_t xhci_get_xfer_ring_dma_addr(struct usb_hcd *hcd, 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; + 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; } @@ -5346,8 +5375,8 @@ 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_sec_event_ring_phys_addr = xhci_get_sec_event_ring_phys_addr, + .get_xfer_ring_phys_addr = xhci_get_xfer_ring_phys_addr, .stop_endpoint = xhci_stop_endpoint, }; diff --git a/include/linux/usb.h b/include/linux/usb.h index 25a8cb676ba2..7e634dc59d6d 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -838,10 +838,10 @@ 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_xfer_ring_dma_addr(struct usb_device *dev, - struct usb_host_endpoint *ep); +extern phys_addr_t usb_get_sec_event_ring_phys_addr( + struct usb_device *dev, unsigned int intr_num, dma_addr_t *dma); +extern phys_addr_t usb_get_xfer_ring_phys_addr(struct usb_device *dev, + struct usb_host_endpoint *ep, dma_addr_t *dma); extern int usb_get_controller_id(struct usb_device *dev); extern int usb_stop_endpoint(struct usb_device *dev, diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 59584fe85c1c..059817cee1d1 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -410,10 +410,11 @@ 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); + phys_addr_t (*get_sec_event_ring_phys_addr)(struct usb_hcd *hcd, + unsigned int intr_num, dma_addr_t *dma); + phys_addr_t (*get_xfer_ring_phys_addr)(struct usb_hcd *hcd, + struct usb_device *udev, struct usb_host_endpoint *ep, + dma_addr_t *dma); int (*get_core_id)(struct usb_hcd *hcd); int (*stop_endpoint)(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); @@ -459,10 +460,10 @@ 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_xfer_ring_dma_addr(struct usb_device *udev, - struct usb_host_endpoint *ep); +extern phys_addr_t usb_hcd_get_sec_event_ring_phys_addr( + struct usb_device *udev, unsigned int intr_num, dma_addr_t *dma); +extern phys_addr_t usb_hcd_get_xfer_ring_phys_addr( + struct usb_device *udev, struct usb_host_endpoint *ep, dma_addr_t *dma); extern int usb_hcd_get_controller_id(struct usb_device *udev); extern int usb_hcd_stop_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep);