From b8f0783b2e593511be641ff6970e46a12b6dd67d Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Tue, 7 May 2019 19:21:52 +0530 Subject: [PATCH] dwc3-msm: Map IPA GSI channel doorbell register for different UDC core Currently GSI endpoint usb_request pointer is allocated only once during boot time and it used by dwc3 driver for mapping doorbell register address with USB endpoint request only once. During composition switch or connect/disconnect scenarios same USB endpoint is being re-enabled and does not create mapping again. On some platforms multiple UDC cores can work in device mode. In case of binding the UDC with primary controller first and then disconnect the primary and bind UDC to secondary controller. Driver does not re-mapping the doorbell address with current UDC core and USB GSI wrapper is trying to access previously mapped GSI DBL address with previous core resulting into smmu fault. Fix this issue by adding re-mapping of doorbell using dwc->sysdev node to map the doorbell register with correct UDC. Change-Id: I327126148c2311884aee2aa99bb59b7add06e302 Signed-off-by: Chandana Kishori Chiluveru Signed-off-by: Mayank Rana --- drivers/usb/dwc3/dwc3-msm.c | 9 +++++++++ include/linux/usb/dwc3-msm.h | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 488f081c54ea..6b0f1d0bebc7 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -1264,11 +1264,20 @@ static void gsi_store_ringbase_dbl_info(struct usb_ep *ep, lower_32_bits(dwc3_trb_dma_offset(dep, &dep->trb_pool[0])), upper_32_bits(dwc3_trb_dma_offset(dep, &dep->trb_pool[0]))); + if (request->mapped_db_reg_phs_addr_lsb && + dwc->sysdev != request->dev) { + dma_unmap_resource(request->dev, + request->mapped_db_reg_phs_addr_lsb, + PAGE_SIZE, DMA_BIDIRECTIONAL, 0); + request->mapped_db_reg_phs_addr_lsb = 0; + } + if (!request->mapped_db_reg_phs_addr_lsb) { request->mapped_db_reg_phs_addr_lsb = dma_map_resource(dwc->sysdev, (phys_addr_t)request->db_reg_phs_addr_lsb, PAGE_SIZE, DMA_BIDIRECTIONAL, 0); + request->dev = dwc->sysdev; if (dma_mapping_error(dwc->sysdev, request->mapped_db_reg_phs_addr_lsb)) dev_err(mdwc->dev, "mapping error for db_reg_phs_addr_lsb\n"); diff --git a/include/linux/usb/dwc3-msm.h b/include/linux/usb/dwc3-msm.h index ca75d27903c8..5cb818ce4809 100644 --- a/include/linux/usb/dwc3-msm.h +++ b/include/linux/usb/dwc3-msm.h @@ -68,6 +68,9 @@ enum gsi_ep_op { * @mapped_db_reg_phs_addr_lsb: doorbell LSB IOVA address mapped with IOMMU * @db_reg_phs_addr_msb: IPA channel doorbell register's physical address MSB * @ep_intr_num: Interrupter number for EP. + * @sgt_trb_xfer_ring: USB TRB ring related sgtable entries + * @sgt_data_buff: Data buffer related sgtable entries + * @dev: pointer to the DMA-capable dwc device */ struct usb_gsi_request { void *buf_base_addr; @@ -80,6 +83,7 @@ struct usb_gsi_request { u8 ep_intr_num; struct sg_table sgt_trb_xfer_ring; struct sg_table sgt_data_buff; + struct device *dev; }; /*