All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage
       [not found] ` <CGME20220304062617epcas2p2084161966aaa66d07f4c25720ec18088@epcas2p2.samsung.com>
@ 2022-03-04  6:23   ` Daehwan Jung
  2022-03-07  9:59     ` Krzysztof Kozlowski
  2022-03-08  5:35     ` kernel test robot
  0 siblings, 2 replies; 19+ messages in thread
From: Daehwan Jung @ 2022-03-04  6:23 UTC (permalink / raw)
  To: Mathias Nyman, Greg Kroah-Hartman
  Cc: open list:USB XHCI DRIVER, open list, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, Daehwan Jung, sc.suh, cpgs,
	cpgsproxy5

Export symbols for xhci hooks usage:
	xhci_ring_free
	- Allow xhci hook to free xhci_ring.

	xhci_get_slot_ctx
	- Allow xhci hook to get slot_ctx from the xhci_container_ctx
	  for getting the slot_ctx information to know which slot is
	  offloading and compare the context in remote subsystem memory
	  if needed.

	xhci_get_ep_ctx
	- Allow xhci hook to get ep_ctx from the xhci_container_ctx for
	  getting the ep_ctx information to know which ep is offloading and
	  comparing the context in remote subsystem memory if needed.

	xhci_handle_event
	- Allow xhci hook to handle the xhci events from the USB
	  controller.

	xhci_update_erst_dequeue
	- If xhci events was handle by xhci hook, it needs to update
	  the erst dequeue pointer to let the USB controller know the
	  events was handled.

	xhci_ring_alloc
	- Allocate a struct xhci_ring.

	xhci_alloc_erst
	xhci_free_erst
	- Allocate and free event ring segment tables.

	xhci_trb_virt_to_dma
	- Used to retrieve the DMA address of a TRB

	xhci_ring_cmd_db
	- Notify the controller when a new command is issued

	xhci_alloc_command
	xhci_free_command
	- Allocate and free a struct xhci_command

	xhci_queue_stop_endpoint
	- Issue a stop endpoint command to the controller

	xhci_segment_free
	- Free a segment struct.

	xhci_link_segments
	- Make the prev segment point to the next segment.

	xhci_initialize_ring_info
	- Initialize a ring struct.

	xhci_check_trb_in_td_math
	- Check TRB math for validation.

	xhci_get_endpoint_address
	- Get endpoint address from endpoint index.

	xhci_address_device
	- Issue an address device command

	xhci_bus_suspend
	xhci_bus_resume
	- Suspend and resume for power scenario

	xhci_remove_stream_mapping
	- Remove stream mapping in stream endpoint

	xhci_remove_segment_mapping
	- Remove segment mapping

Signed-off-by: Daehwan Jung <dh10.jung@samsung.com>
---
 drivers/usb/host/xhci-hub.c  |  2 ++
 drivers/usb/host/xhci-mem.c  | 29 +++++++++++++++++++++--------
 drivers/usb/host/xhci-ring.c |  9 +++++++--
 drivers/usb/host/xhci.c      |  4 +++-
 4 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index df3522dab31b..6c1b8d748d0f 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1809,6 +1809,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(xhci_bus_suspend);
 
 /*
  * Workaround for missing Cold Attach Status (CAS) if device re-plugged in S3.
@@ -1953,6 +1954,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
 	spin_unlock_irqrestore(&xhci->lock, flags);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(xhci_bus_resume);
 
 unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd)
 {
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 0e312066c5c6..e6d56ef91ddb 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -65,7 +65,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,
 	return seg;
 }
 
-static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg)
+void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg)
 {
 	if (seg->trbs) {
 		dma_pool_free(xhci->segment_pool, seg->trbs, seg->dma);
@@ -74,8 +74,9 @@ static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg)
 	kfree(seg->bounce_buf);
 	kfree(seg);
 }
+EXPORT_SYMBOL_GPL(xhci_segment_free);
 
-static void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
+void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
 				struct xhci_segment *first)
 {
 	struct xhci_segment *seg;
@@ -96,9 +97,9 @@ static void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
  * DMA address of the next segment.  The caller needs to set any Link TRB
  * related flags, such as End TRB, Toggle Cycle, and no snoop.
  */
-static void xhci_link_segments(struct xhci_segment *prev,
-			       struct xhci_segment *next,
-			       enum xhci_ring_type type, bool chain_links)
+void xhci_link_segments(struct xhci_segment *prev,
+			struct xhci_segment *next,
+			enum xhci_ring_type type, bool chain_links)
 {
 	u32 val;
 
@@ -118,6 +119,7 @@ static void xhci_link_segments(struct xhci_segment *prev,
 		prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val);
 	}
 }
+EXPORT_SYMBOL_GPL(xhci_link_segments);
 
 /*
  * Link the ring to the new segments.
@@ -206,7 +208,7 @@ static int xhci_insert_segment_mapping(struct radix_tree_root *trb_address_map,
 	return ret;
 }
 
-static void xhci_remove_segment_mapping(struct radix_tree_root *trb_address_map,
+void xhci_remove_segment_mapping(struct radix_tree_root *trb_address_map,
 		struct xhci_segment *seg)
 {
 	unsigned long key;
@@ -215,6 +217,7 @@ static void xhci_remove_segment_mapping(struct radix_tree_root *trb_address_map,
 	if (radix_tree_lookup(trb_address_map, key))
 		radix_tree_delete(trb_address_map, key);
 }
+EXPORT_SYMBOL_GPL(xhci_remove_segment_mapping);
 
 static int xhci_update_stream_segment_mapping(
 		struct radix_tree_root *trb_address_map,
@@ -256,7 +259,7 @@ static int xhci_update_stream_segment_mapping(
 	return ret;
 }
 
-static void xhci_remove_stream_mapping(struct xhci_ring *ring)
+void xhci_remove_stream_mapping(struct xhci_ring *ring)
 {
 	struct xhci_segment *seg;
 
@@ -269,6 +272,7 @@ static void xhci_remove_stream_mapping(struct xhci_ring *ring)
 		seg = seg->next;
 	} while (seg != ring->first_seg);
 }
+EXPORT_SYMBOL_GPL(xhci_remove_stream_mapping);
 
 static int xhci_update_stream_mapping(struct xhci_ring *ring, gfp_t mem_flags)
 {
@@ -292,6 +296,7 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
 
 	kfree(ring);
 }
+EXPORT_SYMBOL_GPL(xhci_ring_free);
 
 void xhci_initialize_ring_info(struct xhci_ring *ring,
 			       unsigned int cycle_state)
@@ -316,6 +321,7 @@ void xhci_initialize_ring_info(struct xhci_ring *ring,
 	 */
 	ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1;
 }
+EXPORT_SYMBOL_GPL(xhci_initialize_ring_info);
 
 /* Allocate segments and link them for a ring */
 static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
@@ -407,6 +413,7 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
 	kfree(ring);
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(xhci_ring_alloc);
 
 void xhci_free_endpoint_ring(struct xhci_hcd *xhci,
 		struct xhci_virt_device *virt_dev,
@@ -519,6 +526,7 @@ struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci,
 	return (struct xhci_slot_ctx *)
 		(ctx->bytes + CTX_SIZE(xhci->hcc_params));
 }
+EXPORT_SYMBOL_GPL(xhci_get_slot_ctx);
 
 struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci,
 				    struct xhci_container_ctx *ctx,
@@ -1755,6 +1763,7 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
 	INIT_LIST_HEAD(&command->cmd_list);
 	return command;
 }
+EXPORT_SYMBOL_GPL(xhci_alloc_command);
 
 struct xhci_command *xhci_alloc_command_with_ctx(struct xhci_hcd *xhci,
 		bool allocate_completion, gfp_t mem_flags)
@@ -1788,6 +1797,7 @@ void xhci_free_command(struct xhci_hcd *xhci,
 	kfree(command->completion);
 	kfree(command);
 }
+EXPORT_SYMBOL_GPL(xhci_free_command);
 
 int xhci_alloc_erst(struct xhci_hcd *xhci,
 		    struct xhci_ring *evt_ring,
@@ -1818,6 +1828,7 @@ int xhci_alloc_erst(struct xhci_hcd *xhci,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(xhci_alloc_erst);
 
 void xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
 {
@@ -1831,6 +1842,7 @@ void xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
 				erst->erst_dma_addr);
 	erst->entries = NULL;
 }
+EXPORT_SYMBOL_GPL(xhci_free_erst);
 
 void xhci_mem_cleanup(struct xhci_hcd *xhci)
 {
@@ -1969,7 +1981,7 @@ static int xhci_test_trb_in_td(struct xhci_hcd *xhci,
 }
 
 /* TRB math checks for xhci_trb_in_td(), using the command and event rings. */
-static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci)
+int xhci_check_trb_in_td_math(struct xhci_hcd *xhci)
 {
 	struct {
 		dma_addr_t		input_dma;
@@ -2089,6 +2101,7 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci)
 	xhci_dbg(xhci, "TRB math tests passed.\n");
 	return 0;
 }
+EXPORT_SYMBOL_GPL(xhci_check_trb_in_td_math);
 
 static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
 {
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index d0b6806275e0..2e99393560e5 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -79,6 +79,7 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg,
 		return 0;
 	return seg->dma + (segment_offset * sizeof(*trb));
 }
+EXPORT_SYMBOL_GPL(xhci_trb_virt_to_dma);
 
 static bool trb_is_noop(union xhci_trb *trb)
 {
@@ -311,6 +312,7 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci)
 	/* Flush PCI posted writes */
 	readl(&xhci->dba->doorbell[0]);
 }
+EXPORT_SYMBOL_GPL(xhci_ring_cmd_db);
 
 static bool xhci_mod_cmd_timer(struct xhci_hcd *xhci, unsigned long delay)
 {
@@ -2965,7 +2967,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
  * Returns >0 for "possibly more events to process" (caller should call again),
  * otherwise 0 if done.  In future, <0 returns should indicate error code.
  */
-static int xhci_handle_event(struct xhci_hcd *xhci)
+int xhci_handle_event(struct xhci_hcd *xhci)
 {
 	union xhci_trb *event;
 	int update_ptrs = 1;
@@ -3034,13 +3036,14 @@ static int xhci_handle_event(struct xhci_hcd *xhci)
 	 */
 	return 1;
 }
+EXPORT_SYMBOL_GPL(xhci_handle_event);
 
 /*
  * Update Event Ring Dequeue Pointer:
  * - When all events have finished
  * - To avoid "Event Ring Full Error" condition
  */
-static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
+void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
 		union xhci_trb *event_ring_deq)
 {
 	u64 temp_64;
@@ -3070,6 +3073,7 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
 	temp_64 |= ERST_EHB;
 	xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
 }
+EXPORT_SYMBOL_GPL(xhci_update_erst_dequeue);
 
 /*
  * xHCI spec says we can get an interrupt, and if the HC has an error condition,
@@ -4420,6 +4424,7 @@ int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, struct xhci_command *cmd,
 	return queue_command(xhci, cmd, 0, 0, 0,
 			trb_slot_id | trb_ep_index | type | trb_suspend, false);
 }
+EXPORT_SYMBOL_GPL(xhci_queue_stop_endpoint);
 
 int xhci_queue_reset_ep(struct xhci_hcd *xhci, struct xhci_command *cmd,
 			int slot_id, unsigned int ep_index,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index dc357cabb265..041a65a6f175 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1449,6 +1449,7 @@ unsigned int xhci_get_endpoint_address(unsigned int ep_index)
 	unsigned int direction = ep_index % 2 ? USB_DIR_OUT : USB_DIR_IN;
 	return direction | number;
 }
+EXPORT_SYMBOL_GPL(xhci_get_endpoint_address);
 
 /* Find the flag for this endpoint (for use in the control context).  Use the
  * endpoint index to create a bitmask.  The slot context is bit 0, endpoint 0 is
@@ -4306,10 +4307,11 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 	return ret;
 }
 
-static int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
+int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
 {
 	return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ADDRESS);
 }
+EXPORT_SYMBOL_GPL(xhci_address_device);
 
 static int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev)
 {
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v1 2/4] usb: host: add xhci hooks for USB offload
       [not found] ` <CGME20220304062617epcas2p4199727918ee662ce09335decba5ad754@epcas2p4.samsung.com>
@ 2022-03-04  6:23   ` Daehwan Jung
  2022-03-08  6:16     ` kernel test robot
  2022-03-08 10:51     ` kernel test robot
  0 siblings, 2 replies; 19+ messages in thread
From: Daehwan Jung @ 2022-03-04  6:23 UTC (permalink / raw)
  To: Mathias Nyman, Greg Kroah-Hartman
  Cc: open list:USB XHCI DRIVER, open list, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, Daehwan Jung, sc.suh, cpgs,
	cpgsproxy5

To enable supporting for USB offload, define "offload" in usb controller
node of device tree. "offload" value can be used to determine which type
of offload was been enabled in the SoC.

For example:

&usbdrd_dwc3 {
	...
	/* support usb offloading, 0: disabled, 1: audio */
	offload = <1>;
	...
};

There are several vendor_ops introduced by this patch:

struct xhci_vendor_ops - function callbacks for vendor specific operations
{
	@vendor_init:
		- called for vendor init process during xhci-plat-hcd
		  probe.
	@vendor_cleanup:
		- called for vendor cleanup process during xhci-plat-hcd
		  remove.
	@is_usb_offload_enabled:
		- called to check if usb offload enabled.
	@queue_irq_work:
		- called to queue vendor specific irq work.
	@alloc_dcbaa:
		- called when allocating vendor specific dcbaa during
		  memory initializtion.
	@free_dcbaa:
		- called to free vendor specific dcbaa when cleanup the
		  memory.
	@alloc_transfer_ring:
		- called when vendor specific transfer ring allocation is required
	@free_transfer_ring:
		- called to free vendor specific transfer ring
	@sync_dev_ctx:
		- called when synchronization for device context is required
}

The xhci hooks with prefix "xhci_vendor_" on the ops in xhci_vendor_ops.
For example, vendor_init ops will be invoked by xhci_vendor_init() hook,
is_usb_offload_enabled ops will be invoked by
xhci_vendor_is_usb_offload_enabled(), and so on.

Signed-off-by: Daehwan Jung <dh10.jung@samsung.com>
---
 drivers/usb/host/xhci-hub.c  |   5 ++
 drivers/usb/host/xhci-mem.c  | 131 +++++++++++++++++++++++++++++++----
 drivers/usb/host/xhci-plat.c |  43 +++++++++++-
 drivers/usb/host/xhci-plat.h |   8 +++
 drivers/usb/host/xhci-ring.c |  13 ++++
 drivers/usb/host/xhci.c      |  94 ++++++++++++++++++++++++-
 drivers/usb/host/xhci.h      |  48 +++++++++++++
 7 files changed, 325 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 6c1b8d748d0f..f7ed19cba8ad 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -535,8 +535,13 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
 	    cmd->status == COMP_COMMAND_RING_STOPPED) {
 		xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n");
 		ret = -ETIME;
+		goto cmd_cleanup;
 	}
 
+	ret = xhci_vendor_sync_dev_ctx(xhci, slot_id);
+	if (ret)
+		xhci_warn(xhci, "Sync device context failed, ret=%d\n", ret);
+
 cmd_cleanup:
 	xhci_free_command(xhci, cmd);
 	return ret;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index e6d56ef91ddb..5defbaf427ed 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -367,6 +367,54 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
 	return 0;
 }
 
+static void xhci_vendor_free_container_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->free_container_ctx)
+		ops->free_container_ctx(xhci, ctx);
+}
+
+static void xhci_vendor_alloc_container_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx,
+					    int type, gfp_t flags)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->alloc_container_ctx)
+		ops->alloc_container_ctx(xhci, ctx, type, flags);
+}
+
+static struct xhci_ring *xhci_vendor_alloc_transfer_ring(struct xhci_hcd *xhci,
+		u32 endpoint_type, enum xhci_ring_type ring_type,
+		unsigned int max_packet, gfp_t mem_flags)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->alloc_transfer_ring)
+		return ops->alloc_transfer_ring(xhci, endpoint_type, ring_type,
+				max_packet, mem_flags);
+	return 0;
+}
+
+void xhci_vendor_free_transfer_ring(struct xhci_hcd *xhci,
+		struct xhci_ring *ring, unsigned int ep_index)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->free_transfer_ring)
+		ops->free_transfer_ring(xhci, ring, ep_index);
+}
+
+bool xhci_vendor_is_usb_offload_enabled(struct xhci_hcd *xhci,
+		struct xhci_virt_device *virt_dev, unsigned int ep_index)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->is_usb_offload_enabled)
+		return ops->is_usb_offload_enabled(xhci, virt_dev, ep_index);
+	return false;
+}
+
 /*
  * Create a new ring with zero or more segments.
  *
@@ -419,7 +467,11 @@ void xhci_free_endpoint_ring(struct xhci_hcd *xhci,
 		struct xhci_virt_device *virt_dev,
 		unsigned int ep_index)
 {
-	xhci_ring_free(xhci, virt_dev->eps[ep_index].ring);
+	if (xhci_vendor_is_usb_offload_enabled(xhci, virt_dev, ep_index))
+		xhci_vendor_free_transfer_ring(xhci, virt_dev->eps[ep_index].ring, ep_index);
+	else
+		xhci_ring_free(xhci, virt_dev->eps[ep_index].ring);
+
 	virt_dev->eps[ep_index].ring = NULL;
 }
 
@@ -478,6 +530,7 @@ struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci,
 {
 	struct xhci_container_ctx *ctx;
 	struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
 
 	if ((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT))
 		return NULL;
@@ -491,7 +544,12 @@ struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci,
 	if (type == XHCI_CTX_TYPE_INPUT)
 		ctx->size += CTX_SIZE(xhci->hcc_params);
 
-	ctx->bytes = dma_pool_zalloc(xhci->device_pool, flags, &ctx->dma);
+	if (xhci_vendor_is_usb_offload_enabled(xhci, NULL, 0) &&
+	    (ops && ops->alloc_container_ctx))
+		xhci_vendor_alloc_container_ctx(xhci, ctx, type, flags);
+	else
+		ctx->bytes = dma_pool_zalloc(xhci->device_pool, flags, &ctx->dma);
+
 	if (!ctx->bytes) {
 		kfree(ctx);
 		return NULL;
@@ -502,9 +560,16 @@ struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci,
 void xhci_free_container_ctx(struct xhci_hcd *xhci,
 			     struct xhci_container_ctx *ctx)
 {
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
 	if (!ctx)
 		return;
-	dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma);
+	if (xhci_vendor_is_usb_offload_enabled(xhci, NULL, 0) &&
+	    (ops && ops->free_container_ctx))
+		xhci_vendor_free_container_ctx(xhci, ctx);
+	else
+		dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma);
+
 	kfree(ctx);
 }
 
@@ -897,7 +962,7 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
 
 	for (i = 0; i < 31; i++) {
 		if (dev->eps[i].ring)
-			xhci_ring_free(xhci, dev->eps[i].ring);
+			xhci_free_endpoint_ring(xhci, dev, i);
 		if (dev->eps[i].stream_info)
 			xhci_free_stream_info(xhci,
 					dev->eps[i].stream_info);
@@ -1495,8 +1560,16 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
 		mult = 0;
 
 	/* Set up the endpoint ring */
-	virt_dev->eps[ep_index].new_ring =
-		xhci_ring_alloc(xhci, 2, 1, ring_type, max_packet, mem_flags);
+	if (xhci_vendor_is_usb_offload_enabled(xhci, virt_dev, ep_index) &&
+	    usb_endpoint_xfer_isoc(&ep->desc)) {
+		virt_dev->eps[ep_index].new_ring =
+			xhci_vendor_alloc_transfer_ring(xhci, endpoint_type, ring_type,
+							max_packet, mem_flags);
+	} else {
+		virt_dev->eps[ep_index].new_ring =
+			xhci_ring_alloc(xhci, 2, 1, ring_type, max_packet, mem_flags);
+	}
+
 	if (!virt_dev->eps[ep_index].new_ring)
 		return -ENOMEM;
 
@@ -1844,6 +1917,24 @@ void xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
 }
 EXPORT_SYMBOL_GPL(xhci_free_erst);
 
+static struct xhci_device_context_array *xhci_vendor_alloc_dcbaa(
+		struct xhci_hcd *xhci, gfp_t flags)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->alloc_dcbaa)
+		return ops->alloc_dcbaa(xhci, flags);
+	return 0;
+}
+
+static void xhci_vendor_free_dcbaa(struct xhci_hcd *xhci)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->free_dcbaa)
+		ops->free_dcbaa(xhci);
+}
+
 void xhci_mem_cleanup(struct xhci_hcd *xhci)
 {
 	struct device	*dev = xhci_to_hcd(xhci)->self.sysdev;
@@ -1898,9 +1989,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 			"Freed medium stream array pool");
 
-	if (xhci->dcbaa)
-		dma_free_coherent(dev, sizeof(*xhci->dcbaa),
-				xhci->dcbaa, xhci->dcbaa->dma);
+	if (xhci_vendor_is_usb_offload_enabled(xhci, NULL, 0)) {
+		xhci_vendor_free_dcbaa(xhci);
+	} else {
+		if (xhci->dcbaa)
+			dma_free_coherent(dev, sizeof(*xhci->dcbaa),
+					xhci->dcbaa, xhci->dcbaa->dma);
+	}
 	xhci->dcbaa = NULL;
 
 	scratchpad_free(xhci);
@@ -2441,15 +2536,21 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 	 * xHCI section 5.4.6 - doorbell array must be
 	 * "physically contiguous and 64-byte (cache line) aligned".
 	 */
-	xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma,
-			flags);
-	if (!xhci->dcbaa)
-		goto fail;
-	xhci->dcbaa->dma = dma;
+	if (xhci_vendor_is_usb_offload_enabled(xhci, NULL, 0)) {
+		xhci->dcbaa = xhci_vendor_alloc_dcbaa(xhci, flags);
+		if (!xhci->dcbaa)
+			goto fail;
+	} else {
+		xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma,
+				flags);
+		if (!xhci->dcbaa)
+			goto fail;
+		xhci->dcbaa->dma = dma;
+	}
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 			"// Device context base array address = 0x%llx (DMA), %p (virt)",
 			(unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
-	xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
+	xhci_write_64(xhci, xhci->dcbaa->dma, &xhci->op_regs->dcbaa_ptr);
 
 	/*
 	 * Initialize the ring segment pool.  The ring must be a contiguous
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index c1edcc9b13ce..21280a6d589e 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -184,6 +184,41 @@ static const struct of_device_id usb_xhci_of_match[] = {
 MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
 #endif
 
+static struct xhci_plat_priv_overwrite xhci_plat_vendor_overwrite;
+
+int xhci_plat_register_vendor_ops(struct xhci_vendor_ops *vendor_ops)
+{
+	if (vendor_ops == NULL)
+		return -EINVAL;
+
+	xhci_plat_vendor_overwrite.vendor_ops = vendor_ops;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xhci_plat_register_vendor_ops);
+
+static int xhci_vendor_init(struct xhci_hcd *xhci)
+{
+	struct xhci_vendor_ops *ops = NULL;
+
+	if (xhci_plat_vendor_overwrite.vendor_ops)
+		ops = xhci->vendor_ops = xhci_plat_vendor_overwrite.vendor_ops;
+
+	if (ops && ops->vendor_init)
+		return ops->vendor_init(xhci);
+	return 0;
+}
+
+static void xhci_vendor_cleanup(struct xhci_hcd *xhci)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->vendor_cleanup)
+		ops->vendor_cleanup(xhci);
+
+	xhci->vendor_ops = NULL;
+}
+
 static int xhci_plat_probe(struct platform_device *pdev)
 {
 	const struct xhci_plat_priv *priv_match;
@@ -339,6 +374,10 @@ static int xhci_plat_probe(struct platform_device *pdev)
 			goto put_usb3_hcd;
 	}
 
+	ret = xhci_vendor_init(xhci);
+	if (ret)
+		goto disable_usb_phy;
+
 	hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
 	xhci->shared_hcd->tpl_support = hcd->tpl_support;
 
@@ -418,8 +457,10 @@ static int xhci_plat_remove(struct platform_device *dev)
 	usb_phy_shutdown(hcd->usb_phy);
 
 	usb_remove_hcd(hcd);
-	usb_put_hcd(shared_hcd);
 
+	xhci_vendor_cleanup(xhci);
+
+	usb_put_hcd(shared_hcd);
 	clk_disable_unprepare(clk);
 	clk_disable_unprepare(reg_clk);
 	usb_put_hcd(hcd);
diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h
index 561d0b7bce09..e726a572321d 100644
--- a/drivers/usb/host/xhci-plat.h
+++ b/drivers/usb/host/xhci-plat.h
@@ -13,6 +13,7 @@
 struct xhci_plat_priv {
 	const char *firmware_name;
 	unsigned long long quirks;
+	struct xhci_vendor_data *vendor_data;
 	int (*plat_setup)(struct usb_hcd *);
 	void (*plat_start)(struct usb_hcd *);
 	int (*init_quirk)(struct usb_hcd *);
@@ -22,4 +23,11 @@ struct xhci_plat_priv {
 
 #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv)
 #define xhci_to_priv(x) ((struct xhci_plat_priv *)(x)->priv)
+
+struct xhci_plat_priv_overwrite {
+	struct xhci_vendor_ops *vendor_ops;
+};
+
+int xhci_plat_register_vendor_ops(struct xhci_vendor_ops *vendor_ops);
+
 #endif	/* _XHCI_PLAT_H */
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 2e99393560e5..e611f8d7d587 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3075,6 +3075,15 @@ void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
 }
 EXPORT_SYMBOL_GPL(xhci_update_erst_dequeue);
 
+static irqreturn_t xhci_vendor_queue_irq_work(struct xhci_hcd *xhci)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->queue_irq_work)
+		return ops->queue_irq_work(xhci);
+	return IRQ_NONE;
+}
+
 /*
  * xHCI spec says we can get an interrupt, and if the HC has an error condition,
  * we might get bad data out of the event ring.  Section 4.10.2.7 has a list of
@@ -3108,6 +3117,10 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
 		goto out;
 	}
 
+	ret = xhci_vendor_queue_irq_work(xhci);
+	if (ret == IRQ_HANDLED)
+		goto out;
+
 	/*
 	 * Clear the op reg interrupt status first,
 	 * so we can receive interrupts from other MSI-X interrupters.
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 041a65a6f175..10d5e20b710d 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1621,6 +1621,11 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
 		return -ENODEV;
 	}
 
+	if (xhci_vendor_usb_offload_skip_urb(xhci, urb)) {
+		xhci_dbg(xhci, "skip urb for usb offload\n");
+		return -EOPNOTSUPP;
+	}
+
 	if (usb_endpoint_xfer_isoc(&urb->ep->desc))
 		num_tds = urb->number_of_packets;
 	else if (usb_endpoint_is_bulk_out(&urb->ep->desc) &&
@@ -2964,6 +2969,14 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 			xhci_finish_resource_reservation(xhci, ctrl_ctx);
 		spin_unlock_irqrestore(&xhci->lock, flags);
 	}
+	if (ret)
+		goto failed;
+
+	ret = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id);
+	if (ret)
+		xhci_warn(xhci, "sync device context failed, ret=%d", ret);
+
+failed:
 	return ret;
 }
 
@@ -3107,7 +3120,11 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
 	for (i = 0; i < 31; i++) {
 		if (virt_dev->eps[i].new_ring) {
 			xhci_debugfs_remove_endpoint(xhci, virt_dev, i);
-			xhci_ring_free(xhci, virt_dev->eps[i].new_ring);
+			if (xhci_vendor_is_usb_offload_enabled(xhci, virt_dev, i))
+				xhci_vendor_free_transfer_ring(xhci, virt_dev->eps[i].new_ring, i);
+			else
+				xhci_ring_free(xhci, virt_dev->eps[i].new_ring);
+
 			virt_dev->eps[i].new_ring = NULL;
 		}
 	}
@@ -3272,6 +3289,13 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
 
 	wait_for_completion(stop_cmd->completion);
 
+	err = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id);
+	if (err) {
+		xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+			  __func__, err);
+		goto cleanup;
+	}
+
 	spin_lock_irqsave(&xhci->lock, flags);
 
 	/* config ep command clears toggle if add and drop ep flags are set */
@@ -3303,6 +3327,11 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
 
 	wait_for_completion(cfg_cmd->completion);
 
+	err = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id);
+	if (err)
+		xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+			  __func__, err);
+
 	xhci_free_command(xhci, cfg_cmd);
 cleanup:
 	xhci_free_command(xhci, stop_cmd);
@@ -3848,6 +3877,13 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd,
 	/* Wait for the Reset Device command to finish */
 	wait_for_completion(reset_device_cmd->completion);
 
+	ret = xhci_vendor_sync_dev_ctx(xhci, slot_id);
+	if (ret) {
+		xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+			  __func__, ret);
+		goto command_cleanup;
+	}
+
 	/* The Reset Device command can't fail, according to the 0.95/0.96 spec,
 	 * unless we tried to reset a slot ID that wasn't enabled,
 	 * or the device wasn't in the addressed or configured state.
@@ -4093,6 +4129,14 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
 		xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
 		goto disable_slot;
 	}
+
+	ret = xhci_vendor_sync_dev_ctx(xhci, slot_id);
+	if (ret) {
+		xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+			  __func__, ret);
+		goto disable_slot;
+	}
+
 	vdev = xhci->devs[slot_id];
 	slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx);
 	trace_xhci_alloc_dev(slot_ctx);
@@ -4223,6 +4267,13 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 	/* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */
 	wait_for_completion(command->completion);
 
+	ret = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id);
+	if (ret) {
+		xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+			  __func__, ret);
+		goto out;
+	}
+
 	/* FIXME: From section 4.3.4: "Software shall be responsible for timing
 	 * the SetAddress() "recovery interval" required by USB and aborting the
 	 * command on a timeout.
@@ -4371,6 +4422,14 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
 		return -ENOMEM;
 	}
 
+	ret = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id);
+	if (ret) {
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+			  __func__, ret);
+		return ret;
+	}
+
 	xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
@@ -4395,6 +4454,30 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
 	return ret;
 }
 
+struct xhci_vendor_ops *xhci_vendor_get_ops(struct xhci_hcd *xhci)
+{
+	return xhci->vendor_ops;
+}
+EXPORT_SYMBOL_GPL(xhci_vendor_get_ops);
+
+int xhci_vendor_sync_dev_ctx(struct xhci_hcd *xhci, unsigned int slot_id)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->sync_dev_ctx)
+		return ops->sync_dev_ctx(xhci, slot_id);
+	return 0;
+}
+
+bool xhci_vendor_usb_offload_skip_urb(struct xhci_hcd *xhci, struct urb *urb)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->usb_offload_skip_urb)
+		return ops->usb_offload_skip_urb(xhci, urb);
+	return false;
+}
+
 #ifdef CONFIG_PM
 
 /* BESL to HIRD Encoding array for USB2 LPM */
@@ -5131,6 +5214,15 @@ static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
 		return -ENOMEM;
 	}
 
+	ret = xhci_vendor_sync_dev_ctx(xhci, hdev->slot_id);
+	if (ret) {
+		xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+			  __func__, ret);
+		xhci_free_command(xhci, config_cmd);
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		return ret;
+	}
+
 	xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx);
 	ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
 	slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 5a75fe563123..2efe8ddaab5f 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1928,6 +1928,7 @@ struct xhci_hcd {
 	struct list_head	regset_list;
 
 	void			*dbc;
+
 	/* platform-specific data -- must come last */
 	unsigned long		priv[] __aligned(sizeof(s64));
 };
@@ -2206,6 +2207,53 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
 					urb->stream_id);
 }
 
+/**
+ * struct xhci_vendor_ops - function callbacks for vendor specific operations
+ * @vendor_init: called for vendor init process
+ * @vendor_cleanup: called for vendor cleanup process
+ * @is_usb_offload_enabled: called to check if usb offload enabled
+ * @queue_irq_work: called to queue vendor specific irq work
+ * @alloc_dcbaa: called when allocating vendor specific dcbaa
+ * @free_dcbaa: called to free vendor specific dcbaa
+ * @alloc_transfer_ring: called when remote transfer ring allocation is required
+ * @free_transfer_ring: called to free vendor specific transfer ring
+ * @sync_dev_ctx: called when synchronization for device context is required
+ * @alloc_container_ctx: called when allocating vendor specific container context
+ * @free_container_ctx: called to free vendor specific container context
+ */
+struct xhci_vendor_ops {
+	int (*vendor_init)(struct xhci_hcd *xhci);
+	void (*vendor_cleanup)(struct xhci_hcd *xhci);
+	bool (*is_usb_offload_enabled)(struct xhci_hcd *xhci,
+				       struct xhci_virt_device *vdev,
+				       unsigned int ep_index);
+	irqreturn_t (*queue_irq_work)(struct xhci_hcd *xhci);
+
+	struct xhci_device_context_array *(*alloc_dcbaa)(struct xhci_hcd *xhci,
+							 gfp_t flags);
+	void (*free_dcbaa)(struct xhci_hcd *xhci);
+
+	struct xhci_ring *(*alloc_transfer_ring)(struct xhci_hcd *xhci,
+			u32 endpoint_type, enum xhci_ring_type ring_type,
+			unsigned int max_packet, gfp_t mem_flags);
+	void (*free_transfer_ring)(struct xhci_hcd *xhci,
+			struct xhci_ring *ring, unsigned int ep_index);
+	int (*sync_dev_ctx)(struct xhci_hcd *xhci, unsigned int slot_id);
+	bool (*usb_offload_skip_urb)(struct xhci_hcd *xhci, struct urb *urb);
+	void (*alloc_container_ctx)(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx,
+				    int type, gfp_t flags);
+	void (*free_container_ctx)(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
+};
+
+struct xhci_vendor_ops *xhci_vendor_get_ops(struct xhci_hcd *xhci);
+
+int xhci_vendor_sync_dev_ctx(struct xhci_hcd *xhci, unsigned int slot_id);
+bool xhci_vendor_usb_offload_skip_urb(struct xhci_hcd *xhci, struct urb *urb);
+void xhci_vendor_free_transfer_ring(struct xhci_hcd *xhci,
+		struct xhci_ring *ring, unsigned int ep_index);
+bool xhci_vendor_is_usb_offload_enabled(struct xhci_hcd *xhci,
+		struct xhci_virt_device *virt_dev, unsigned int ep_index);
+
 /*
  * TODO: As per spec Isochronous IDT transmissions are supported. We bypass
  * them anyways as we where unable to find a device that matches the
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v1 3/4] usb: host: add some to xhci overrides for USB offload
       [not found] ` <CGME20220304062617epcas2p1ccc051a6d931d4151a7c9e2bb545bd47@epcas2p1.samsung.com>
@ 2022-03-04  6:23   ` Daehwan Jung
  0 siblings, 0 replies; 19+ messages in thread
From: Daehwan Jung @ 2022-03-04  6:23 UTC (permalink / raw)
  To: Mathias Nyman, Greg Kroah-Hartman
  Cc: open list:USB XHCI DRIVER, open list, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, Daehwan Jung, sc.suh, cpgs,
	cpgsproxy5

Co-processor needs some information about connected usb device.
It's proper to pass information after usb device gets address when
getting "Set Address" command. It supports vendors to implement it
using xhci overrides. There're several power scenarios depending
on vendors. It gives vendors flexibilty to meet their power requirement.
They can override suspend and resume of root hub.

Signed-off-by: Daehwan Jung <dh10.jung@samsung.com>
---
 drivers/usb/host/xhci.c | 6 ++++++
 drivers/usb/host/xhci.h | 4 ++++
 2 files changed, 10 insertions(+)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 10d5e20b710d..7789bf277c8e 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -5557,6 +5557,12 @@ void xhci_init_driver(struct hc_driver *drv,
 			drv->check_bandwidth = over->check_bandwidth;
 		if (over->reset_bandwidth)
 			drv->reset_bandwidth = over->reset_bandwidth;
+		if (over->address_device)
+			drv->address_device = over->address_device;
+		if (over->bus_suspend)
+			drv->bus_suspend = over->bus_suspend;
+		if (over->bus_resume)
+			drv->bus_resume = over->bus_resume;
 	}
 }
 EXPORT_SYMBOL_GPL(xhci_init_driver);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 2efe8ddaab5f..2c7d0e403424 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1944,6 +1944,9 @@ struct xhci_driver_overrides {
 			     struct usb_host_endpoint *ep);
 	int (*check_bandwidth)(struct usb_hcd *, struct usb_device *);
 	void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
+	int (*address_device)(struct usb_hcd *hcd, struct usb_device *udev);
+	int (*bus_suspend)(struct usb_hcd *hcd);
+	int (*bus_resume)(struct usb_hcd *hcd);
 };
 
 #define	XHCI_CFC_DELAY		10
@@ -2100,6 +2103,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
 		       struct usb_host_endpoint *ep);
 int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
+int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev);
 int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
 int xhci_ext_cap_init(struct xhci_hcd *xhci);
 
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v1 4/4] usb: host: add xhci-exynos module
       [not found] ` <CGME20220304062618epcas2p2e3c73b5c4ed0c9bc0ca0c02aa658d3fb@epcas2p2.samsung.com>
@ 2022-03-04  6:23   ` Daehwan Jung
  2022-03-04  7:37     ` Greg Kroah-Hartman
  2022-03-07 10:07     ` Krzysztof Kozlowski
  0 siblings, 2 replies; 19+ messages in thread
From: Daehwan Jung @ 2022-03-04  6:23 UTC (permalink / raw)
  To: Mathias Nyman, Greg Kroah-Hartman
  Cc: open list:USB XHCI DRIVER, open list, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, Daehwan Jung, sc.suh, cpgs,
	cpgsproxy5

Signed-off-by: Daehwan Jung <dh10.jung@samsung.com>
---
 drivers/usb/host/xhci-exynos.c | 2025 ++++++++++++++++++++++++++++++++
 drivers/usb/host/xhci-exynos.h |  150 +++
 2 files changed, 2175 insertions(+)
 create mode 100644 drivers/usb/host/xhci-exynos.c
 create mode 100644 drivers/usb/host/xhci-exynos.h

diff --git a/drivers/usb/host/xhci-exynos.c b/drivers/usb/host/xhci-exynos.c
new file mode 100644
index 000000000000..3913c48d4b20
--- /dev/null
+++ b/drivers/usb/host/xhci-exynos.c
@@ -0,0 +1,2025 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * xhci-exynos.c - xHCI host controller driver platform Bus Glue for Exynos.
+ *
+ * Copyright (C) 2022 Samsung Electronics Incorporated - http://www.samsung.com
+ * Author: Daehwan Jung <dh10.jung@samsung.com>
+ *
+ * A lot of code borrowed from the Linux xHCI driver.
+ */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/usb/phy.h>
+#include <linux/slab.h>
+#include <linux/phy/phy.h>
+#include <linux/acpi.h>
+#include <linux/usb/of.h>
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+#include "../../../sound/usb/exynos_usb_audio.h"
+#include <linux/types.h>
+#include "xhci-trace.h"
+#endif
+
+#include "../core/hub.h"
+#include "../core/phy.h"
+#include "xhci.h"
+#include "xhci-plat.h"
+#include "xhci-mvebu.h"
+#include "xhci-rcar.h"
+#include "../dwc3/dwc3-exynos.h"
+#include "../dwc3/exynos-otg.h"
+#include "xhci-exynos.h"
+#include <soc/samsung/exynos-cpupm.h>
+
+static struct hc_driver __read_mostly xhci_exynos_hc_driver;
+
+static int xhci_exynos_setup(struct usb_hcd *hcd);
+static int xhci_exynos_start(struct usb_hcd *hcd);
+static int xhci_exynos_bus_suspend(struct usb_hcd *hcd);
+static int xhci_exynos_bus_resume(struct usb_hcd *hcd);
+static int xhci_exynos_wake_lock(struct xhci_hcd_exynos *xhci_exynos,
+				   int is_main_hcd, int is_lock);
+
+static int is_rewa_enabled;
+
+static struct xhci_hcd_exynos *g_xhci_exynos;
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+extern struct usb_xhci_pre_alloc xhci_pre_alloc;
+
+struct xhci_ring *xhci_ring_alloc_uram(struct xhci_hcd *xhci,
+		unsigned int num_segs, unsigned int cycle_state,
+		enum xhci_ring_type type, unsigned int max_packet, gfp_t flags,
+		u32 endpoint_type);
+
+static void *dma_pre_alloc_coherent(struct xhci_hcd *xhci, size_t size,
+			 dma_addr_t *dma_handle, gfp_t gfp)
+{
+	struct usb_xhci_pre_alloc *xhci_alloc = g_xhci_exynos->xhci_alloc;
+	u64 align = size % PAGE_SIZE;
+	u64 b_offset = xhci_alloc->offset;
+
+	if (align)
+		xhci_alloc->offset = xhci_alloc->offset + size + (PAGE_SIZE - align);
+	else
+		xhci_alloc->offset = xhci_alloc->offset + size;
+
+	*dma_handle = xhci_alloc->dma + b_offset;
+
+	return (void *)xhci_alloc->pre_dma_alloc + b_offset;
+}
+
+static void xhci_exynos_usb_offload_enable_event_ring(struct xhci_hcd *xhci)
+{
+	u32 temp;
+	u64 temp_64;
+
+	temp_64 = xhci_read_64(xhci, &g_xhci_exynos->ir_set_audio->erst_dequeue);
+	temp_64 &= ~ERST_PTR_MASK;
+	xhci_info(xhci,	"ERST2 deq = 64'h%0lx", (unsigned long) temp_64);
+
+	xhci_info(xhci, "// [USB Audio] Set the interrupt modulation register");
+	temp = readl(&g_xhci_exynos->ir_set_audio->irq_control);
+	temp &= ~ER_IRQ_INTERVAL_MASK;
+
+	temp |= (u32)160;
+	writel(temp, &g_xhci_exynos->ir_set_audio->irq_control);
+
+	temp = readl(&g_xhci_exynos->ir_set_audio->irq_pending);
+	xhci_info(xhci, "// [USB Audio] Enabling event ring interrupter %p by writing 0x%x to irq_pending",
+			g_xhci_exynos->ir_set_audio, (unsigned int) ER_IRQ_ENABLE(temp));
+	writel(ER_IRQ_ENABLE(temp), &g_xhci_exynos->ir_set_audio->irq_pending);
+}
+
+static void xhci_exynos_usb_offload_store_hw_info(struct xhci_hcd *xhci, struct usb_hcd *hcd,
+						struct usb_device *udev)
+{
+	struct xhci_virt_device *virt_dev;
+	struct xhci_erst_entry *entry = &g_xhci_exynos->erst_audio.entries[0];
+
+	virt_dev = xhci->devs[udev->slot_id];
+
+	g_hwinfo->dcbaa_dma = xhci->dcbaa->dma;
+	g_hwinfo->save_dma = g_xhci_exynos->save_dma;
+	g_hwinfo->cmd_ring = xhci->op_regs->cmd_ring;
+	g_hwinfo->slot_id = udev->slot_id;
+	g_hwinfo->in_dma = g_xhci_exynos->in_dma;
+	g_hwinfo->in_buf = g_xhci_exynos->in_addr;
+	g_hwinfo->out_dma = g_xhci_exynos->out_dma;
+	g_hwinfo->out_buf = g_xhci_exynos->out_addr;
+	g_hwinfo->in_ctx = virt_dev->in_ctx->dma;
+	g_hwinfo->out_ctx = virt_dev->out_ctx->dma;
+	g_hwinfo->erst_addr = entry->seg_addr;
+	g_hwinfo->speed = udev->speed;
+	if (xhci->quirks & XHCI_USE_URAM_FOR_EXYNOS_AUDIO)
+		g_hwinfo->use_uram = true;
+	else
+		g_hwinfo->use_uram = false;
+
+	pr_info("<<< %s\n", __func__);
+}
+static void xhci_exynos_set_hc_event_deq_audio(struct xhci_hcd *xhci)
+{
+	u64 temp;
+	dma_addr_t deq;
+
+	deq = xhci_trb_virt_to_dma(g_xhci_exynos->event_ring_audio->deq_seg,
+			g_xhci_exynos->event_ring_audio->dequeue);
+	if (deq == 0 && !in_interrupt())
+		xhci_warn(xhci, "WARN something wrong with SW event ring "
+				"dequeue ptr.\n");
+	/* Update HC event ring dequeue pointer */
+	temp = xhci_read_64(xhci, &g_xhci_exynos->ir_set_audio->erst_dequeue);
+	temp &= ERST_PTR_MASK;
+	/* Don't clear the EHB bit (which is RW1C) because
+	 * there might be more events to service.
+	 */
+	temp &= ~ERST_EHB;
+	xhci_info(xhci,	"//[%s] Write event ring dequeue pointer = 0x%llx, "
+			"preserving EHB bit", __func__,
+			((u64) deq & (u64) ~ERST_PTR_MASK) | temp);
+	xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
+			&g_xhci_exynos->ir_set_audio->erst_dequeue);
+}
+
+void xhci_exynos_parse_endpoint(struct xhci_hcd *xhci, struct usb_device *udev,
+				struct usb_endpoint_descriptor *desc,
+				struct xhci_container_ctx *ctx)
+{
+	struct usb_endpoint_descriptor *d = desc;
+	int size = 0x100;
+	unsigned int ep_index;
+	struct xhci_ep_ctx *ep_ctx;
+
+	g_hwinfo->rawdesc_length = size;
+	ep_index = xhci_get_endpoint_index(d);
+	ep_ctx = xhci_get_ep_ctx(xhci, ctx, ep_index);
+
+	pr_info("udev = 0x%8x, Ep = 0x%x, desc = 0x%8x, deq = 0x%8x\n",
+			udev, d->bEndpointAddress, d, ep_ctx->deq);
+
+	if (ep_ctx->deq == 0) {
+		pr_info("ep_ctx->deq: 0x%8x has wrong address!!\n", ep_ctx->deq);
+		return;
+	}
+
+	if ((d->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+				USB_ENDPOINT_XFER_ISOC) {
+		if ((d->bmAttributes & USB_ENDPOINT_USAGE_MASK) ==
+					USB_ENDPOINT_USAGE_FEEDBACK) {
+			/* Only Feedback endpoint(Not implict feedback data endpoint) */
+			if (d->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+				g_hwinfo->fb_in_ep =
+					d->bEndpointAddress;
+				pr_info("Feedback IN ISO endpoint #0%x 0x%x\n",
+					d->bEndpointAddress, d->bSynchAddress);
+
+				pr_info("[%s] set fb in deq : %#08llx\n",
+						__func__, ep_ctx->deq);
+				g_hwinfo->fb_old_in_deq = g_hwinfo->fb_in_deq;
+				g_hwinfo->fb_in_deq = ep_ctx->deq;
+			} else {
+				g_hwinfo->fb_out_ep =
+					d->bEndpointAddress;
+				pr_info("Feedback OUT ISO endpoint #0%x 0x%x\n",
+					d->bEndpointAddress, d->bSynchAddress);
+
+				pr_info("[%s] set fb out deq : %#08llx\n",
+						__func__, ep_ctx->deq);
+				g_hwinfo->fb_old_out_deq = g_hwinfo->fb_out_deq;
+				g_hwinfo->fb_out_deq = ep_ctx->deq;
+			}
+		} else {
+			/* Data Stream Endpoint only */
+			if (d->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+				if (d->bEndpointAddress != g_hwinfo->fb_in_ep) {
+					g_hwinfo->in_ep =
+						d->bEndpointAddress;
+					pr_info(" This is IN ISO endpoint #0%x 0x%x\n",
+						d->bEndpointAddress, d->bSynchAddress);
+
+					pr_info("[%s] set in deq : %#08llx\n",
+							__func__, ep_ctx->deq);
+					g_hwinfo->old_in_deq = g_hwinfo->in_deq;
+					g_hwinfo->in_deq = ep_ctx->deq;
+				} else {
+					pr_info("IN ISO endpoint is same with FB #0%x\n",
+						d->bEndpointAddress);
+					pr_info("[%s] set fb in deq : %#08llx\n",
+							__func__, ep_ctx->deq);
+					g_hwinfo->fb_old_in_deq = g_hwinfo->fb_in_deq;
+					g_hwinfo->fb_in_deq = ep_ctx->deq;
+				}
+
+				if ((d->bLength > 7) && (d->bSynchAddress != 0x0)) {
+					g_hwinfo->fb_out_ep =
+						d->bSynchAddress;
+					pr_info("Feedback OUT ISO endpoint #0%x 0x%x\n",
+						d->bEndpointAddress, d->bSynchAddress);
+
+					pr_info("[%s] set fb out deq : %#08llx\n",
+							__func__, ep_ctx->deq);
+					g_hwinfo->fb_old_out_deq = g_hwinfo->fb_out_deq;
+					g_hwinfo->fb_out_deq = ep_ctx->deq;
+				}
+			} else {
+				g_hwinfo->out_ep =
+					d->bEndpointAddress;
+				pr_info(" This is OUT ISO endpoint #0%x 0x%x\n",
+					d->bEndpointAddress, d->bSynchAddress);
+
+				pr_info("[%s] set out deq : %#08llx\n",
+						__func__, ep_ctx->deq);
+				g_hwinfo->old_out_deq = g_hwinfo->out_deq;
+				g_hwinfo->out_deq = ep_ctx->deq;
+				if ((d->bLength > 7) && (d->bSynchAddress != 0x0)) {
+					g_hwinfo->fb_in_ep =
+						d->bSynchAddress;
+					pr_info("Feedback IN ISO endpoint #0%x 0x%x\n",
+						d->bEndpointAddress, d->bSynchAddress);
+
+					pr_info("[%s] set fb in deq : %#08llx\n",
+							__func__, ep_ctx->deq);
+					g_hwinfo->fb_old_in_deq = g_hwinfo->fb_in_deq;
+					g_hwinfo->fb_in_deq = ep_ctx->deq;
+				}
+			}
+		}
+	}
+
+
+}
+int xhci_exynos_address_device(struct usb_hcd *hcd, struct usb_device *udev)
+{
+	struct xhci_hcd *xhci;
+	int ret;
+
+	pr_debug("%s +++", __func__);
+	ret = xhci_address_device(hcd, udev);
+	xhci = hcd_to_xhci(hcd);
+
+	xhci_exynos_usb_offload_store_hw_info(xhci, hcd, udev);
+
+	pr_debug("%s ---", __func__);
+	return ret;
+}
+int xhci_exynos_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+		struct usb_host_endpoint *ep)
+{
+	int ret;
+	struct xhci_hcd *xhci;
+	struct xhci_virt_device *virt_dev;
+
+	pr_debug("%s +++", __func__);
+	ret = xhci_add_endpoint(hcd, udev, ep);
+	if (!ret && udev->slot_id) {
+		xhci = hcd_to_xhci(hcd);
+		virt_dev = xhci->devs[udev->slot_id];
+		xhci_exynos_parse_endpoint(xhci, udev, &ep->desc, virt_dev->out_ctx);
+	}
+	pr_debug("%s ---", __func__);
+	return ret;
+}
+static int xhci_exynos_alloc_event_ring(struct xhci_hcd *xhci, gfp_t flags)
+{
+	dma_addr_t	dma;
+	unsigned int	val;
+	u64		val_64;
+	struct xhci_segment	*seg;
+
+	g_xhci_exynos->ir_set_audio = &xhci->run_regs->ir_set[1];
+	g_xhci_exynos->save_addr = dma_pre_alloc_coherent(xhci,
+			sizeof(PAGE_SIZE), &dma, flags);
+	g_xhci_exynos->save_dma = dma;
+	xhci_info(xhci, "// Save address = 0x%llx (DMA), %p (virt)",
+			(unsigned long long)g_xhci_exynos->save_dma, g_xhci_exynos->save_addr);
+
+	if ((xhci->quirks & XHCI_USE_URAM_FOR_EXYNOS_AUDIO)) {
+		/* for AUDIO erst */
+		g_xhci_exynos->event_ring_audio = xhci_ring_alloc_uram(xhci, ERST_NUM_SEGS,
+				1, TYPE_EVENT, 0, flags, 0);
+		if (!g_xhci_exynos->event_ring_audio)
+			goto fail;
+
+		g_xhci_exynos->erst_audio.entries = ioremap(EXYNOS_URAM_ABOX_ERST_SEG_ADDR,
+				sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS);
+		if (!g_xhci_exynos->erst_audio.entries)
+			goto fail;
+
+		dma = EXYNOS_URAM_ABOX_ERST_SEG_ADDR;
+		xhci_info(xhci, "ABOX audio ERST allocated at 0x%x",
+					EXYNOS_URAM_ABOX_ERST_SEG_ADDR);
+	} else {
+		/* for AUDIO erst */
+		g_xhci_exynos->event_ring_audio = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1,
+					TYPE_EVENT, 0, flags);
+		if (!g_xhci_exynos->event_ring_audio)
+			goto fail;
+		if (xhci_check_trb_in_td_math(xhci) < 0)
+			goto fail;
+		g_xhci_exynos->erst_audio.entries = dma_pre_alloc_coherent(xhci,
+				sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS, &dma,
+				flags);
+		if (!g_xhci_exynos->erst_audio.entries)
+			goto fail;
+	}
+	xhci_info(xhci,	"// Allocated event ring segment table at 0x%llx",
+			(unsigned long long)dma);
+
+	memset(g_xhci_exynos->erst_audio.entries, 0, sizeof(struct xhci_erst_entry) *
+							ERST_NUM_SEGS);
+	g_xhci_exynos->erst_audio.num_entries = ERST_NUM_SEGS;
+	g_xhci_exynos->erst_audio.erst_dma_addr = dma;
+	xhci_info(xhci,	"// Set ERST to 0; private num segs = %i, virt addr = %p, dma addr = 0x%llx",
+			xhci->erst.num_entries,
+			xhci->erst.entries,
+			(unsigned long long)xhci->erst.erst_dma_addr);
+
+	/* set ring base address and size for each segment table entry */
+	for (val = 0, seg = g_xhci_exynos->event_ring_audio->first_seg;
+					val < ERST_NUM_SEGS; val++) {
+		struct xhci_erst_entry *entry = &g_xhci_exynos->erst_audio.entries[val];
+
+		entry->seg_addr = cpu_to_le64(seg->dma);
+		entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT);
+		entry->rsvd = 0;
+		seg = seg->next;
+	}
+
+	/* set ERST count with the number of entries in the segment table */
+	val = readl(&g_xhci_exynos->ir_set_audio->erst_size);
+	val &= ERST_SIZE_MASK;
+	val |= ERST_NUM_SEGS;
+	xhci_info(xhci, "// Write ERST size = %i to ir_set 0 (some bits preserved)",
+			val);
+	writel(val, &g_xhci_exynos->ir_set_audio->erst_size);
+
+	xhci_info(xhci, "// Set ERST entries to point to event ring.");
+	/* set the segment table base address */
+	xhci_info(xhci,	"// Set ERST base address for ir_set 0 = 0x%llx",
+			(unsigned long long)g_xhci_exynos->erst_audio.erst_dma_addr);
+	val_64 = xhci_read_64(xhci, &g_xhci_exynos->ir_set_audio->erst_base);
+	val_64 &= ERST_PTR_MASK;
+	val_64 |= (g_xhci_exynos->erst_audio.erst_dma_addr & (u64) ~ERST_PTR_MASK);
+	xhci_write_64(xhci, val_64, &g_xhci_exynos->ir_set_audio->erst_base);
+
+	/* Set the event ring dequeue address */
+	xhci_exynos_set_hc_event_deq_audio(xhci);
+	xhci_info(xhci,	"// Wrote ERST address to ir_set 1.");
+
+	return 0;
+fail:
+	return -1;
+}
+
+static void xhci_exynos_free_event_ring(struct xhci_hcd *xhci)
+{
+	if (xhci->quirks & XHCI_USE_URAM_FOR_EXYNOS_AUDIO)
+		iounmap(g_xhci_exynos->erst_audio.entries);
+	else
+		g_xhci_exynos->erst_audio.entries = NULL;
+
+	xhci_info(xhci, "%s: Freed ERST for Audio offloading", __func__);
+
+	if (g_xhci_exynos->event_ring_audio)
+		xhci_exynos_ring_free(xhci, g_xhci_exynos->event_ring_audio);
+	g_xhci_exynos->event_ring_audio = NULL;
+	xhci_info(xhci, "%s: Freed event ring for Audio offloading", __func__);
+}
+
+static void xhci_exynos_free_container_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx)
+{
+	/* Ignore dma_pool_free if it is allocated from URAM */
+	if (ctx->dma != EXYNOS_URAM_DEVICE_CTX_ADDR)
+		dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma);
+}
+
+static void xhci_exynos_alloc_container_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx,
+						int type, gfp_t flags)
+{
+	if (type != XHCI_CTX_TYPE_INPUT && g_xhci_exynos->exynos_uram_ctx_alloc == 0 &&
+			xhci->quirks & XHCI_USE_URAM_FOR_EXYNOS_AUDIO) {
+		/* Only first Device Context uses URAM */
+		int i;
+
+		ctx->bytes = ioremap(EXYNOS_URAM_DEVICE_CTX_ADDR, 2112);
+		if (!ctx->bytes)
+			return;
+
+		for (i = 0; i < 2112; i++)
+			ctx->bytes[i] = 0;
+
+		ctx->dma = EXYNOS_URAM_DEVICE_CTX_ADDR;
+		g_xhci_exynos->usb_audio_ctx_addr = ctx->bytes;
+		g_xhci_exynos->exynos_uram_ctx_alloc = 1;
+		xhci_info(xhci, "First device context allocated at URAM(%x)",
+					EXYNOS_URAM_DEVICE_CTX_ADDR);
+	} else {
+		ctx->bytes = dma_pool_zalloc(xhci->device_pool, flags, &ctx->dma);
+		if (!ctx->bytes)
+			return;
+	}
+}
+
+static struct xhci_ring *xhci_exynos_alloc_transfer_ring(struct xhci_hcd *xhci, u32 endpoint_type,
+		enum xhci_ring_type ring_type, unsigned int max_packet, gfp_t mem_flags)
+{
+	if (xhci->quirks & XHCI_USE_URAM_FOR_EXYNOS_AUDIO) {
+		/* If URAM is not allocated, it try to allocate from URAM */
+		if (g_xhci_exynos->exynos_uram_isoc_out_alloc == 0 &&
+						endpoint_type == ISOC_OUT_EP) {
+			xhci_info(xhci, "First ISOC OUT ring is allocated from URAM.\n");
+			return xhci_ring_alloc_uram(xhci, 1, 1, ring_type,
+							max_packet, mem_flags,
+							endpoint_type);
+
+			g_xhci_exynos->exynos_uram_isoc_out_alloc = 1;
+		} else if (g_xhci_exynos->exynos_uram_isoc_in_alloc == 0 &&
+					endpoint_type == ISOC_IN_EP &&
+					EXYNOS_URAM_ISOC_IN_RING_ADDR != 0x0) {
+			xhci_info(xhci, "First ISOC IN ring is allocated from URAM.\n");
+			return xhci_ring_alloc_uram(xhci, 1, 1, ring_type,
+							max_packet, mem_flags,
+							endpoint_type);
+
+			g_xhci_exynos->exynos_uram_isoc_in_alloc = 1;
+		} else {
+			return xhci_ring_alloc(xhci, 2, 1, ring_type,
+							max_packet, mem_flags);
+		}
+
+	} else {
+		return xhci_ring_alloc(xhci, 2, 1, ring_type, max_packet, mem_flags);
+	}
+}
+
+void xhci_exynos_segment_free_skip(struct xhci_hcd *xhci, struct xhci_segment *seg)
+{
+	if (seg->trbs) {
+		/* Check URAM address for memory free */
+		if (seg->dma == EXYNOS_URAM_ABOX_EVT_RING_ADDR) {
+			iounmap(seg->trbs);
+		} else if (seg->dma == EXYNOS_URAM_ISOC_OUT_RING_ADDR) {
+			g_xhci_exynos->exynos_uram_isoc_out_alloc = 0;
+			if (in_interrupt())
+				g_xhci_exynos->usb_audio_isoc_out_addr = (u8 *)seg->trbs;
+			else
+				iounmap(seg->trbs);
+		} else if (seg->dma == EXYNOS_URAM_ISOC_IN_RING_ADDR) {
+			g_xhci_exynos->exynos_uram_isoc_in_alloc = 0;
+			if (in_interrupt())
+				g_xhci_exynos->usb_audio_isoc_in_addr = (u8 *)seg->trbs;
+			else
+				iounmap(seg->trbs);
+		} else
+			dma_pool_free(xhci->segment_pool, seg->trbs, seg->dma);
+
+		seg->trbs = NULL;
+	}
+	kfree(seg->bounce_buf);
+	kfree(seg);
+}
+
+void xhci_exynos_free_segments_for_ring(struct xhci_hcd *xhci,
+				struct xhci_segment *first)
+{
+	struct xhci_segment *seg;
+
+	seg = first->next;
+
+	if (!seg)
+		xhci_err(xhci, "segment is null unexpectedly\n");
+
+	while (seg != first) {
+		struct xhci_segment *next = seg->next;
+
+		xhci_exynos_segment_free_skip(xhci, seg);
+		seg = next;
+	}
+	xhci_exynos_segment_free_skip(xhci, first);
+}
+
+void xhci_exynos_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
+{
+	if (!ring)
+		return;
+
+	//trace_xhci_ring_free(ring);
+
+	if (ring->first_seg) {
+		if (ring->type == TYPE_STREAM)
+			xhci_remove_stream_mapping(ring);
+
+		xhci_exynos_free_segments_for_ring(xhci, ring->first_seg);
+	}
+
+	kfree(ring);
+}
+
+static void xhci_exynos_free_transfer_ring(struct xhci_hcd *xhci,
+		struct xhci_virt_device *virt_dev, unsigned int ep_index)
+{
+	xhci_exynos_ring_free(xhci, virt_dev->eps[ep_index].ring);
+}
+
+static int xhci_exynos_vendor_init(struct xhci_hcd *xhci)
+{
+	return 0;
+
+}
+static void xhci_exynos_vendor_cleanup(struct xhci_hcd *xhci)
+{
+	xhci_exynos_free_event_ring(xhci);
+}
+
+static bool xhci_exynos_is_usb_offload_enabled(struct xhci_hcd *xhci,
+		struct xhci_virt_device *virt_dev, unsigned int ep_index)
+{
+	return true;
+}
+
+static struct xhci_device_context_array *xhci_exynos_alloc_dcbaa(
+		struct xhci_hcd *xhci, gfp_t flags)
+{
+	dma_addr_t dma;
+
+	if (xhci->quirks & XHCI_USE_URAM_FOR_EXYNOS_AUDIO) {
+		int i;
+
+		xhci_info(xhci, "DCBAA is allocated at 0x%x(URAM)",
+						EXYNOS_URAM_DCBAA_ADDR);
+		/* URAM allocation for DCBAA */
+		xhci->dcbaa = ioremap(EXYNOS_URAM_DCBAA_ADDR,
+						sizeof(*xhci->dcbaa));
+		if (!xhci->dcbaa)
+			return NULL;
+		/* Clear DCBAA */
+		for (i = 0; i < MAX_HC_SLOTS; i++)
+			xhci->dcbaa->dev_context_ptrs[i] = 0x0;
+
+		xhci->dcbaa->dma = EXYNOS_URAM_DCBAA_ADDR;
+	} else {
+		xhci->dcbaa = dma_pre_alloc_coherent(xhci, sizeof(*xhci->dcbaa),
+				&dma, flags);
+		if (!xhci->dcbaa)
+			return NULL;
+		memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa));
+		xhci->dcbaa->dma = dma;
+	}
+	return xhci->dcbaa;
+}
+
+static void xhci_exynos_free_dcbaa(struct xhci_hcd *xhci)
+{
+	if (xhci->quirks & XHCI_USE_URAM_FOR_EXYNOS_AUDIO) {
+		iounmap(xhci->dcbaa);
+		if (g_xhci_exynos->usb_audio_ctx_addr != NULL) {
+			iounmap(g_xhci_exynos->usb_audio_ctx_addr);
+			g_xhci_exynos->usb_audio_ctx_addr = NULL;
+		}
+		if (g_xhci_exynos->usb_audio_isoc_out_addr != NULL) {
+			iounmap(g_xhci_exynos->usb_audio_isoc_out_addr);
+			g_xhci_exynos->usb_audio_isoc_out_addr = NULL;
+		}
+		if (g_xhci_exynos->usb_audio_isoc_in_addr != NULL) {
+			iounmap(g_xhci_exynos->usb_audio_isoc_in_addr);
+			g_xhci_exynos->usb_audio_isoc_in_addr = NULL;
+		}
+	} else
+		xhci->dcbaa = NULL;
+}
+
+/* URAM Allocation Functions */
+static struct xhci_segment *xhci_segment_alloc_uram(struct xhci_hcd *xhci,
+					       unsigned int cycle_state,
+					       unsigned int max_packet,
+					       gfp_t flags)
+{
+	struct xhci_segment *seg;
+	dma_addr_t	dma;
+	int		i;
+	struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+
+	seg = kzalloc_node(sizeof(*seg), flags, dev_to_node(dev));
+	if (!seg)
+		return NULL;
+
+	seg->trbs = ioremap(EXYNOS_URAM_ABOX_EVT_RING_ADDR, TRB_SEGMENT_SIZE);
+	if (!seg->trbs)
+		return NULL;
+
+	dma = EXYNOS_URAM_ABOX_EVT_RING_ADDR;
+
+	if (max_packet) {
+		seg->bounce_buf = kzalloc_node(max_packet, flags,
+					dev_to_node(dev));
+		if (!seg->bounce_buf) {
+			dma_pool_free(xhci->segment_pool, seg->trbs, dma);
+			kfree(seg);
+			return NULL;
+		}
+	}
+	/* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */
+	if (cycle_state == 0) {
+		for (i = 0; i < TRBS_PER_SEGMENT; i++)
+			seg->trbs[i].link.control |= cpu_to_le32(TRB_CYCLE);
+	}
+	seg->dma = dma;
+	xhci_info(xhci, "ABOX Event Ring is allocated at 0x%x",
+					EXYNOS_URAM_ABOX_EVT_RING_ADDR);
+	seg->next = NULL;
+
+	return seg;
+}
+
+static struct xhci_segment *xhci_segment_alloc_uram_ep(struct xhci_hcd *xhci,
+					       unsigned int cycle_state,
+					       unsigned int max_packet,
+					       gfp_t flags, int seg_num,
+					       u32 endpoint_type)
+{
+	struct xhci_segment *seg;
+	dma_addr_t	dma;
+	int		i;
+	struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+
+	seg = kzalloc_node(sizeof(*seg), flags, dev_to_node(dev));
+	if (!seg)
+		return NULL;
+
+	if (seg_num != 0) {
+		/* Support just one segment */
+		xhci_err(xhci, "%s : Unexpected SEG NUMBER!\n", __func__);
+		return NULL;
+	}
+
+	if (endpoint_type == ISOC_OUT_EP) {
+		seg->trbs = ioremap(EXYNOS_URAM_ISOC_OUT_RING_ADDR,
+							TRB_SEGMENT_SIZE);
+		if (!seg->trbs)
+			return NULL;
+
+		dma = EXYNOS_URAM_ISOC_OUT_RING_ADDR;
+		xhci_info(xhci, "First ISOC-OUT Ring is allocated at 0x%x", dma);
+	} else if (endpoint_type == ISOC_IN_EP) {
+		seg->trbs = ioremap(EXYNOS_URAM_ISOC_IN_RING_ADDR,
+							TRB_SEGMENT_SIZE);
+		if (!seg->trbs)
+			return NULL;
+
+		dma = EXYNOS_URAM_ISOC_IN_RING_ADDR;
+		xhci_info(xhci, "First ISOC-IN Ring is allocated at 0x%x", dma);
+	} else {
+		xhci_err(xhci, "%s : Unexpected EP Type!\n", __func__);
+		return NULL;
+	}
+
+	for (i = 0; i < 256; i++) {
+		seg->trbs[i].link.segment_ptr = 0;
+		seg->trbs[i].link.intr_target = 0;
+		seg->trbs[i].link.control = 0;
+	}
+
+
+	if (max_packet) {
+		seg->bounce_buf = kzalloc_node(max_packet, flags,
+					dev_to_node(dev));
+		if (!seg->bounce_buf) {
+			dma_pool_free(xhci->segment_pool, seg->trbs, dma);
+			kfree(seg);
+			return NULL;
+		}
+	}
+	/* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */
+	if (cycle_state == 0) {
+		for (i = 0; i < TRBS_PER_SEGMENT; i++)
+			seg->trbs[i].link.control |= cpu_to_le32(TRB_CYCLE);
+	}
+	seg->dma = dma;
+	seg->next = NULL;
+
+	return seg;
+}
+
+static int xhci_alloc_segments_for_ring_uram(struct xhci_hcd *xhci,
+		struct xhci_segment **first, struct xhci_segment **last,
+		unsigned int num_segs, unsigned int cycle_state,
+		enum xhci_ring_type type, unsigned int max_packet, gfp_t flags,
+		u32 endpoint_type)
+{
+	struct xhci_segment *prev;
+	bool chain_links;
+
+	/* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */
+	chain_links = !!(xhci_link_trb_quirk(xhci) ||
+			 (type == TYPE_ISOC &&
+			  (xhci->quirks & XHCI_AMD_0x96_HOST)));
+
+	if (type == TYPE_ISOC) {
+		prev = xhci_segment_alloc_uram_ep(xhci, cycle_state,
+							max_packet, flags, 0,
+							endpoint_type);
+	} else if (type == TYPE_EVENT) {
+		prev = xhci_segment_alloc_uram(xhci, cycle_state, max_packet, flags);
+	} else {
+		xhci_err(xhci, "Unexpected TYPE for URAM allocation!\n");
+		return -ENOMEM;
+	}
+
+	if (!prev)
+		return -ENOMEM;
+	num_segs--;
+
+	*first = prev;
+	while (num_segs > 0) {
+		struct xhci_segment	*next = NULL;
+
+		if (type == TYPE_ISOC) {
+			prev = xhci_segment_alloc_uram_ep(xhci, cycle_state,
+							max_packet, flags, 1,
+							endpoint_type);
+		} else if (type == TYPE_EVENT) {
+			next = xhci_segment_alloc_uram(xhci, cycle_state,
+							max_packet, flags);
+		} else {
+			xhci_err(xhci, "Unexpected TYPE for URAM alloc(multi)!\n");
+			return -ENOMEM;
+		}
+
+		if (!next) {
+			prev = *first;
+			while (prev) {
+				next = prev->next;
+				xhci_segment_free(xhci, prev);
+				prev = next;
+			}
+			return -ENOMEM;
+		}
+		xhci_link_segments(prev, next, type, chain_links);
+
+		prev = next;
+		num_segs--;
+	}
+	xhci_link_segments(prev, *first, type, chain_links);
+	*last = prev;
+
+	return 0;
+}
+
+struct xhci_ring *xhci_ring_alloc_uram(struct xhci_hcd *xhci,
+		unsigned int num_segs, unsigned int cycle_state,
+		enum xhci_ring_type type, unsigned int max_packet, gfp_t flags,
+		u32 endpoint_type)
+{
+	struct xhci_ring	*ring;
+	int ret;
+	struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+
+	ring = kzalloc_node(sizeof(*ring), flags, dev_to_node(dev));
+	if (!ring)
+		return NULL;
+
+	ring->num_segs = num_segs;
+	ring->bounce_buf_len = max_packet;
+	INIT_LIST_HEAD(&ring->td_list);
+	ring->type = type;
+	if (num_segs == 0)
+		return ring;
+
+	ret = xhci_alloc_segments_for_ring_uram(xhci, &ring->first_seg,
+			&ring->last_seg, num_segs, cycle_state, type,
+			max_packet, flags, endpoint_type);
+	if (ret)
+		goto fail;
+
+	/* Only event ring does not use link TRB */
+	if (type != TYPE_EVENT) {
+		/* See section 4.9.2.1 and 6.4.4.1 */
+		ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |=
+			cpu_to_le32(LINK_TOGGLE);
+	}
+	xhci_initialize_ring_info(ring, cycle_state);
+	//trace_xhci_ring_alloc(ring);
+	return ring;
+
+fail:
+	kfree(ring);
+	return NULL;
+}
+#endif
+//#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+
+extern struct usb_xhci_pre_alloc xhci_pre_alloc;
+static const struct xhci_driver_overrides xhci_exynos_overrides __initconst = {
+	.extra_priv_size = sizeof(struct xhci_exynos_priv),
+	.reset = xhci_exynos_setup,
+	.start = xhci_exynos_start,
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	.add_endpoint = xhci_exynos_add_endpoint,
+	.address_device = xhci_exynos_address_device,
+#endif
+	.bus_suspend = xhci_exynos_bus_suspend,
+	.bus_resume = xhci_exynos_bus_resume,
+};
+
+int xhci_exynos_bus_suspend(struct usb_hcd *hcd)
+{
+	struct xhci_exynos_priv *priv = hcd_to_xhci_exynos_priv(hcd);
+	struct xhci_hcd_exynos *xhci_exynos = priv->xhci_exynos;
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+	int ret, main_hcd;
+
+	pr_info("%s, priv = 0x%8x, xhci_exynos = 0x%8x\n",
+		__func__, priv, xhci_exynos);
+
+	if (hcd == xhci->main_hcd)
+		main_hcd = 1;
+	else
+		main_hcd = 0;
+
+	ret = xhci_bus_suspend(hcd);
+
+	xhci_exynos_wake_lock(xhci_exynos, main_hcd, 0);
+
+	return ret;
+}
+
+int xhci_exynos_bus_resume(struct usb_hcd *hcd)
+{
+	struct xhci_exynos_priv *priv = hcd_to_xhci_exynos_priv(hcd);
+	struct xhci_hcd_exynos *xhci_exynos = priv->xhci_exynos;
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+	int ret, main_hcd;
+
+	if (hcd == xhci->main_hcd)
+		main_hcd = 1;
+	else
+		main_hcd = 0;
+
+	pr_info("%s, hcd = 0x%8x\n", __func__, hcd);
+
+	ret = xhci_bus_resume(hcd);
+
+	xhci_exynos_wake_lock(xhci_exynos, main_hcd, 1);
+
+	return ret;
+}
+
+static void xhci_priv_exynos_start(struct usb_hcd *hcd)
+{
+	struct xhci_exynos_priv *priv = hcd_to_xhci_exynos_priv(hcd);
+
+	if (priv->plat_start)
+		priv->plat_start(hcd);
+}
+
+void xhci_exynos_portsc_power_off(void __iomem *portsc, u32 on, u32 prt)
+{
+	struct xhci_hcd_exynos	*xhci_exynos = g_xhci_exynos;
+
+	u32 reg;
+
+	spin_lock(&xhci_exynos->xhcioff_lock);
+
+	pr_info("%s, on=%d portsc_control_priority=%d, prt=%d\n",
+		__func__, on,  xhci_exynos->portsc_control_priority, prt);
+
+	if (xhci_exynos->portsc_control_priority > prt) {
+		spin_unlock(&xhci_exynos->xhcioff_lock);
+		return;
+	}
+
+	xhci_exynos->portsc_control_priority = prt;
+
+	if (on && !xhci_exynos->port_off_done) {
+		pr_info("%s, Do not switch-on port\n", __func__);
+		spin_unlock(&xhci_exynos->xhcioff_lock);
+		return;
+	}
+
+	reg = readl(portsc);
+
+	if (on)
+		reg |= PORT_POWER;
+	else
+		reg &= ~PORT_POWER;
+
+	writel(reg, portsc);
+	reg = readl(portsc);
+
+	pr_info("power %s portsc, reg = 0x%x addr = %8x\n",
+		on ? "on" : "off", reg, (u64)portsc);
+
+	if (on)
+		xhci_exynos->port_off_done = 0;
+	else
+		xhci_exynos->port_off_done = 1;
+
+	spin_unlock(&xhci_exynos->xhcioff_lock);
+}
+
+int xhci_exynos_port_power_set(u32 on, u32 prt)
+{
+	if (!g_xhci_exynos)
+		return -EACCES;
+
+	if (g_xhci_exynos->usb3_portsc) {
+		xhci_exynos_portsc_power_off(g_xhci_exynos->usb3_portsc, on, prt);
+		return 0;
+	}
+
+	pr_info("%s, usb3_portsc is NULL\n", __func__);
+	return -EIO;
+}
+EXPORT_SYMBOL_GPL(xhci_exynos_port_power_set);
+
+static int xhci_exynos_check_port(struct usb_device *dev, bool on)
+{
+	struct usb_device *hdev;
+	struct usb_device *udev = dev;
+	struct device *ddev = &udev->dev;
+	struct xhci_hcd_exynos	*xhci_exynos = g_xhci_exynos;
+	enum usb_port_state pre_state;
+	int usb3_hub_detect = 0;
+	int usb2_detect = 0;
+	int port;
+	int bInterfaceClass = 0;
+
+	if (udev->bus->root_hub == udev) {
+		pr_info("this dev is a root hub\n");
+		goto skip;
+	}
+
+	pre_state = xhci_exynos->port_state;
+
+	/* Find root hub */
+	hdev = udev->parent;
+	if (!hdev)
+		goto skip;
+
+	hdev = dev->bus->root_hub;
+	if (!hdev)
+		goto skip;
+	pr_info("root hub maxchild = %d\n", hdev->maxchild);
+
+	/* check all ports */
+	usb_hub_for_each_child(hdev, port, udev) {
+		dev_dbg(ddev, "%s, class = %d, speed = %d\n",
+			__func__, udev->descriptor.bDeviceClass,
+						udev->speed);
+		dev_dbg(ddev, "udev = 0x%8x, state = %d\n", udev, udev->state);
+		if (udev && udev->state == USB_STATE_CONFIGURED) {
+			if (!dev->config->interface[0])
+				continue;
+
+			bInterfaceClass	= udev->config->interface[0]
+					->cur_altsetting->desc.bInterfaceClass;
+			if (on) {
+				if (bInterfaceClass == USB_CLASS_HID ||
+				    bInterfaceClass == USB_CLASS_AUDIO) {
+					udev->do_remote_wakeup =
+						(udev->config->desc.bmAttributes &
+							USB_CONFIG_ATT_WAKEUP) ? 1 : 0;
+					if (udev->do_remote_wakeup == 1) {
+						device_init_wakeup(ddev, 1);
+						usb_enable_autosuspend(dev);
+					}
+					dev_dbg(ddev, "%s, remote_wakeup = %d\n",
+						__func__, udev->do_remote_wakeup);
+				}
+			}
+			if (bInterfaceClass == USB_CLASS_HUB) {
+				xhci_exynos->port_state = PORT_HUB;
+				usb3_hub_detect = 1;
+				break;
+			} else if (bInterfaceClass == USB_CLASS_BILLBOARD) {
+				xhci_exynos->port_state = PORT_DP;
+				usb3_hub_detect = 1;
+				break;
+			}
+
+			if (udev->speed >= USB_SPEED_SUPER) {
+				xhci_exynos->port_state = PORT_USB3;
+				usb3_hub_detect = 1;
+				break;
+			} else {
+				xhci_exynos->port_state = PORT_USB2;
+				usb2_detect = 1;
+			}
+		} else {
+			pr_info("not configured, state = %d\n", udev->state);
+		}
+	}
+
+	if (!usb3_hub_detect && !usb2_detect)
+		xhci_exynos->port_state = PORT_EMPTY;
+
+	pr_info("%s %s state pre=%d now=%d\n", __func__,
+		on ? "on" : "off", pre_state, xhci_exynos->port_state);
+
+	return xhci_exynos->port_state;
+
+skip:
+	return -EINVAL;
+}
+
+static void xhci_exynos_set_port(struct usb_device *dev, bool on)
+{
+	int port;
+
+	port = xhci_exynos_check_port(dev, on);
+	if (g_xhci_exynos->dp_use == true)
+		port = PORT_DP;
+
+	switch (port) {
+	case PORT_EMPTY:
+		pr_info("Port check empty\n");
+		is_otg_only = 1;
+		if (!g_xhci_exynos->usb3_phy_control) {
+			usb_power_notify_control(0, 1);
+			g_xhci_exynos->usb3_phy_control = true;
+		}
+		xhci_exynos_port_power_set(1, 1);
+		break;
+	case PORT_USB2:
+		pr_info("Port check usb2\n");
+		is_otg_only = 0;
+		xhci_exynos_port_power_set(0, 1);
+		if (g_xhci_exynos->usb3_phy_control) {
+			usb_power_notify_control(0, 0);
+			g_xhci_exynos->usb3_phy_control = false;
+		}
+		break;
+	case PORT_USB3:
+		/* xhci_port_power_set(1, 1); */
+		is_otg_only = 0;
+		pr_info("Port check usb3\n");
+		break;
+	case PORT_HUB:
+		/*xhci_exynos_port_power_set(1, 1);*/
+		pr_info("Port check hub\n");
+		is_otg_only = 0;
+		break;
+	case PORT_DP:
+		/*xhci_exynos_port_power_set(1, 1);*/
+		pr_info("Port check DP\n");
+		is_otg_only = 0;
+		break;
+	default:
+		break;
+	}
+}
+
+int xhci_exynos_inform_dp_use(int use, int lane_cnt)
+{
+	int ret = 0;
+
+	pr_info("[%s] dp use = %d, lane_cnt = %d\n",
+			__func__, use, lane_cnt);
+
+	/*
+	 * otg_connection will be available
+	 * after usb__audio is merged.
+	 * At that time, modify this.
+	 */
+	/*if (!otg_connection || !g_xhci_exynos)*/
+	if (!g_xhci_exynos)
+		return 0;
+
+	if (use == 1) {
+		g_xhci_exynos->dp_use = true;
+#ifdef CONFIG_EXYNOS_USBDRD_PHY30
+		if (g_xhci_exynos->usb3_phy_control == false) {
+			usb_power_notify_control(1, 1);
+			g_xhci_exynos->usb3_phy_control = true;
+		}
+		if (lane_cnt == 4) {
+			exynos_usbdrd_dp_use_notice(lane_cnt);
+			ret = xhci_exynos_port_power_set(0, 2);
+		}
+#endif
+		udelay(1);
+	} else {
+#ifdef CONFIG_EXYNOS_USBDRD_PHY30
+		if (g_xhci_exynos->port_state == PORT_USB2) {
+			if (g_xhci_exynos->usb3_phy_control == true) {
+				usb_power_notify_control(1, 0);
+				g_xhci_exynos->usb3_phy_control = false;
+			}
+		}
+#endif
+		g_xhci_exynos->dp_use = false;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(xhci_exynos_inform_dp_use);
+
+static int xhci_exynos_power_notify(struct notifier_block *self,
+			    unsigned long action, void *dev)
+{
+	switch (action) {
+	case USB_DEVICE_ADD:
+		xhci_exynos_set_port(dev, 1);
+		break;
+	case USB_DEVICE_REMOVE:
+		xhci_exynos_set_port(dev, 0);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block dev_nb = {
+	.notifier_call = xhci_exynos_power_notify,
+};
+
+void xhci_exynos_register_notify(void)
+{
+	is_otg_only = 1;
+	g_xhci_exynos->port_state = PORT_EMPTY;
+	usb_register_notify(&dev_nb);
+}
+
+void xhci_exynos_unregister_notify(void)
+{
+	usb_unregister_notify(&dev_nb);
+}
+
+static int xhci_priv_init_quirk(struct usb_hcd *hcd)
+{
+	struct xhci_exynos_priv *priv = hcd_to_xhci_exynos_priv(hcd);
+
+	if (!priv->init_quirk)
+		return 0;
+
+	return priv->init_quirk(hcd);
+}
+
+static int xhci_priv_suspend_quirk(struct usb_hcd *hcd)
+{
+	struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
+
+	if (!priv->suspend_quirk)
+		return 0;
+
+	return priv->suspend_quirk(hcd);
+}
+
+static int xhci_priv_resume_quirk(struct usb_hcd *hcd)
+{
+	struct xhci_exynos_priv *priv = hcd_to_xhci_exynos_priv(hcd);
+
+	if (!priv->resume_quirk)
+		return 0;
+
+	return priv->resume_quirk(hcd);
+}
+
+static void xhci_exynos_quirks(struct device *dev, struct xhci_hcd *xhci)
+{
+	struct xhci_exynos_priv *priv = xhci_to_exynos_priv(xhci);
+
+	/*
+	 * As of now platform drivers don't provide MSI support so we ensure
+	 * here that the generic code does not try to make a pci_dev from our
+	 * dev struct in order to setup MSI
+	 */
+	xhci->quirks |= XHCI_PLAT | priv->quirks;
+}
+
+/* called during probe() after chip reset completes */
+static int xhci_exynos_setup(struct usb_hcd *hcd)
+{
+	int ret;
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+#endif
+
+	ret = xhci_priv_init_quirk(hcd);
+	if (ret)
+		return ret;
+
+	ret = xhci_gen_setup(hcd, xhci_exynos_quirks);
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	pr_debug("%s: alloc_event_ring!\n", __func__);
+	xhci_exynos_alloc_event_ring(xhci, GFP_KERNEL);
+#endif
+
+	return ret;
+}
+
+static int xhci_exynos_start(struct usb_hcd *hcd)
+{
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	struct xhci_hcd *xhci;
+#endif
+	int ret;
+
+	xhci_priv_exynos_start(hcd);
+	ret = xhci_run(hcd);
+
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	xhci = hcd_to_xhci(hcd);
+	pr_debug("%s: enable_event_ring!\n", __func__);
+	xhci_exynos_usb_offload_enable_event_ring(xhci);
+#endif
+	return ret;
+}
+
+static ssize_t
+xhci_exynos_ss_compliance_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	u32			reg;
+	void __iomem *reg_base;
+
+	reg_base = hcd->regs;
+	reg = readl(reg_base + PORTSC_OFFSET);
+
+	return sysfs_emit(buf, "0x%x\n", reg);
+}
+
+static ssize_t
+xhci_exynos_ss_compliance_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t n)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	int		value;
+	u32			reg;
+	void __iomem *reg_base;
+
+	if (kstrtoint(buf, 10, &value))
+		return -EINVAL;
+
+	reg_base = hcd->regs;
+
+	if (value == 1) {
+		/* PORTSC PLS is set to 10, LWS to 1 */
+		reg = readl(reg_base + PORTSC_OFFSET);
+		reg &= ~((0xF << 5) | (1 << 16));
+		reg |= (10 << 5) | (1 << 16);
+		writel(reg, reg_base + PORTSC_OFFSET);
+		pr_info("SS host compliance enabled portsc 0x%x\n", reg);
+	} else
+		pr_info("Only 1 is allowed for input value\n");
+
+	return n;
+}
+
+static DEVICE_ATTR_RW(xhci_exynos_ss_compliance);
+
+
+static struct attribute *xhci_exynos_attrs[] = {
+	&dev_attr_xhci_exynos_ss_compliance.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(xhci_exynos);
+
+#ifdef CONFIG_OF
+static const struct of_device_id usb_xhci_of_match[] = {
+	{
+		.compatible = "generic-xhci",
+	}, {
+		.compatible = "xhci-platform",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
+#endif
+
+static void xhci_pm_runtime_init(struct device *dev)
+{
+	dev->power.runtime_status = RPM_SUSPENDED;
+	dev->power.idle_notification = false;
+
+	dev->power.disable_depth = 1;
+	atomic_set(&dev->power.usage_count, 0);
+
+	dev->power.runtime_error = 0;
+
+	atomic_set(&dev->power.child_count, 0);
+	pm_suspend_ignore_children(dev, false);
+	dev->power.runtime_auto = true;
+
+	dev->power.request_pending = false;
+	dev->power.request = RPM_REQ_NONE;
+	dev->power.deferred_resume = false;
+	dev->power.accounting_timestamp = jiffies;
+
+	dev->power.timer_expires = 0;
+	init_waitqueue_head(&dev->power.wait_queue);
+}
+
+static struct xhci_plat_priv_overwrite xhci_plat_vendor_overwrite;
+
+int xhci_exynos_register_vendor_ops(struct xhci_vendor_ops *vendor_ops)
+{
+	if (vendor_ops == NULL)
+		return -EINVAL;
+
+	xhci_plat_vendor_overwrite.vendor_ops = vendor_ops;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xhci_exynos_register_vendor_ops);
+
+
+static int xhci_vendor_init(struct xhci_hcd *xhci)
+{
+	struct xhci_vendor_ops *ops = NULL;
+
+	if (xhci_plat_vendor_overwrite.vendor_ops)
+		ops = xhci->vendor_ops = xhci_plat_vendor_overwrite.vendor_ops;
+
+	if (ops && ops->vendor_init)
+		return ops->vendor_init(xhci);
+	return 0;
+}
+
+static void xhci_vendor_cleanup(struct xhci_hcd *xhci)
+{
+	struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+	if (ops && ops->vendor_cleanup)
+		ops->vendor_cleanup(xhci);
+
+	xhci->vendor_ops = NULL;
+}
+
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+static struct xhci_vendor_ops ops = {
+	.vendor_init = xhci_exynos_vendor_init,
+	.vendor_cleanup = xhci_exynos_vendor_cleanup,
+	.is_usb_offload_enabled = xhci_exynos_is_usb_offload_enabled,
+	.alloc_dcbaa = xhci_exynos_alloc_dcbaa,
+	.free_dcbaa = xhci_exynos_free_dcbaa,
+	.alloc_transfer_ring = xhci_exynos_alloc_transfer_ring,
+	.free_transfer_ring = xhci_exynos_free_transfer_ring,
+	.alloc_container_ctx = xhci_exynos_alloc_container_ctx,
+	.free_container_ctx = xhci_exynos_free_container_ctx,
+};
+#endif
+
+int xhci_exynos_wake_lock(struct xhci_hcd_exynos *xhci_exynos,
+				   int is_main_hcd, int is_lock)
+{
+	struct usb_hcd	*hcd = xhci_exynos->hcd;
+	int idle_ip_index;
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+	struct wakeup_source *main_wakelock, *shared_wakelock;
+
+	main_wakelock = xhci_exynos->main_wakelock;
+	shared_wakelock = xhci_exynos->shared_wakelock;
+
+	dev_info(xhci_exynos->dev, "<<< %s - hcd = 0x%8x 0x%8x 0x%8x\n",
+					__func__, hcd, main_wakelock, shared_wakelock);
+
+	if (xhci->xhc_state & XHCI_STATE_REMOVING) {
+		dev_info(xhci_exynos->dev, "%s - Host removing return!\n",
+				__func__);
+		return -ESHUTDOWN;
+	}
+
+	if (is_lock) {
+		if (is_main_hcd) {
+			dev_info(xhci_exynos->dev, "%s: Main HCD WAKE LOCK\n", __func__);
+			__pm_stay_awake(main_wakelock);
+		} else {
+			dev_info(xhci_exynos->dev, "%s: Shared HCD WAKE LOCK\n", __func__);
+			__pm_stay_awake(shared_wakelock);
+		}
+
+		/* Add a routine for disable IDLEIP (IP idle) */
+		dev_info(xhci_exynos->dev, "IDLEIP(SICD) disable.\n");
+		idle_ip_index = get_idle_ip_index();
+		pr_info("%s, usb idle ip = %d\n", __func__, idle_ip_index);
+		exynos_update_ip_idle_status(idle_ip_index, 0);
+	} else {
+		if (is_main_hcd) {
+			dev_info(xhci_exynos->dev, "%s: Main HCD WAKE UNLOCK\n", __func__);
+			__pm_relax(main_wakelock);
+		} else {
+			dev_info(xhci_exynos->dev, "%s: Shared HCD WAKE UNLOCK\n", __func__);
+			__pm_relax(shared_wakelock);
+		}
+
+		if (!main_wakelock->active && !shared_wakelock->active) {
+			xhci_info(xhci, "Try to IDLEIP Enable!!!\n");
+
+			/* Add a routine for enable IDLEIP (IP idle) */
+			dev_info(xhci_exynos->dev, "IDLEIP(SICD) Enable.\n");
+			idle_ip_index = get_idle_ip_index();
+			pr_info("%s, usb idle ip = %d\n", __func__, idle_ip_index);
+			exynos_update_ip_idle_status(idle_ip_index, 1);
+		}
+	}
+
+	return 0;
+}
+static int xhci_exynos_probe(struct platform_device *pdev)
+{
+	struct device		*parent = pdev->dev.parent;
+	const struct hc_driver	*driver;
+	struct device		*sysdev, *tmpdev;
+	struct xhci_hcd		*xhci;
+	struct xhci_hcd_exynos	*xhci_exynos;
+	struct xhci_exynos_priv *priv;
+	struct resource         *res;
+	struct usb_hcd		*hcd;
+	struct usb_device	*hdev;
+	struct usb_hub		*hub;
+	struct usb_port		*port_dev;
+	int			ret;
+	int			irq;
+
+	struct wakeup_source	*main_wakelock, *shared_wakelock;
+	int			value;
+
+	dev_info(&pdev->dev, "XHCI PLAT START\n");
+
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	xhci_exynos_register_vendor_ops(&ops);
+#endif
+	main_wakelock = wakeup_source_register(&pdev->dev, dev_name(&pdev->dev));
+	__pm_stay_awake(main_wakelock);
+
+	/* Initialization shared wakelock for SS HCD */
+	shared_wakelock = wakeup_source_register(&pdev->dev, dev_name(&pdev->dev));
+	__pm_stay_awake(shared_wakelock);
+
+	is_rewa_enabled = 0;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	driver = &xhci_exynos_hc_driver;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	/*
+	 * sysdev must point to a device that is known to the system firmware
+	 * or PCI hardware. We handle these three cases here:
+	 * 1. xhci_plat comes from firmware
+	 * 2. xhci_plat is child of a device from firmware (dwc3-plat)
+	 * 3. xhci_plat is grandchild of a pci device (dwc3-pci)
+	 */
+	for (sysdev = &pdev->dev; sysdev; sysdev = sysdev->parent) {
+		if (is_of_node(sysdev->fwnode) ||
+			is_acpi_device_node(sysdev->fwnode))
+			break;
+#ifdef CONFIG_PCI
+		else if (sysdev->bus == &pci_bus_type)
+			break;
+#endif
+	}
+
+	if (!sysdev)
+		sysdev = &pdev->dev;
+
+	/* Try to set 64-bit DMA first */
+	if (WARN_ON(!sysdev->dma_mask))
+		/* Platform did not initialize dma_mask */
+		ret = dma_coerce_mask_and_coherent(sysdev,
+						   DMA_BIT_MASK(64));
+	else
+		ret = dma_set_mask_and_coherent(sysdev, DMA_BIT_MASK(64));
+
+	/* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
+	if (ret) {
+		ret = dma_set_mask_and_coherent(sysdev, DMA_BIT_MASK(32));
+		if (ret)
+			return ret;
+	}
+
+	xhci_pm_runtime_init(&pdev->dev);
+
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_noresume(&pdev->dev);
+
+	hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,
+			       dev_name(&pdev->dev), NULL);
+	if (!hcd) {
+		ret = -ENOMEM;
+		goto disable_runtime;
+	}
+	hcd->skip_phy_initialization = 1;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hcd->regs)) {
+		ret = PTR_ERR(hcd->regs);
+		goto put_hcd;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	xhci = hcd_to_xhci(hcd);
+
+	g_xhci_exynos = devm_kzalloc(&pdev->dev, sizeof(struct xhci_hcd_exynos), GFP_KERNEL);
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	g_hwinfo = devm_kzalloc(hcd->self.sysdev, sizeof(struct hcd_hw_info), GFP_KERNEL);
+#endif
+
+	ret = xhci_vendor_init(xhci);
+	if (ret)
+		goto put_hcd;
+
+	if (g_xhci_exynos)
+		xhci_exynos = g_xhci_exynos;
+	else
+		goto put_hcd;
+
+	xhci_exynos->dev = &pdev->dev;
+
+	xhci_exynos->hcd = (struct usb_hcd *)platform_get_drvdata(pdev);
+	platform_set_drvdata(pdev, xhci_exynos);
+
+	spin_lock_init(&xhci_exynos->xhcioff_lock);
+
+	xhci_exynos->port_off_done = 0;
+	xhci_exynos->portsc_control_priority = 0;
+	xhci_exynos->usb3_phy_control = true;
+	xhci_exynos->dp_use = 0;
+
+	xhci_exynos->usb3_portsc = hcd->regs + PORTSC_OFFSET;
+	if (xhci_exynos->port_set_delayed) {
+		pr_info("port power set delayed\n");
+		xhci_exynos_portsc_power_off(xhci_exynos->usb3_portsc, 0, 2);
+		xhci_exynos->port_set_delayed = 0;
+	}
+
+	xhci_exynos->main_wakelock = main_wakelock;
+	xhci_exynos->shared_wakelock = shared_wakelock;
+
+	xhci_exynos_register_notify();
+
+	/*
+	 * Not all platforms have clks so it is not an error if the
+	 * clock do not exist.
+	 */
+	xhci->reg_clk = devm_clk_get_optional(&pdev->dev, "reg");
+	if (IS_ERR(xhci->reg_clk)) {
+		ret = PTR_ERR(xhci->reg_clk);
+		goto put_hcd;
+	}
+
+	ret = clk_prepare_enable(xhci->reg_clk);
+	if (ret)
+		goto put_hcd;
+
+	xhci->clk = devm_clk_get_optional(&pdev->dev, NULL);
+	if (IS_ERR(xhci->clk)) {
+		ret = PTR_ERR(xhci->clk);
+		goto disable_reg_clk;
+	}
+
+	ret = clk_prepare_enable(xhci->clk);
+	if (ret)
+		goto disable_reg_clk;
+
+	priv = hcd_to_xhci_exynos_priv(hcd);
+	priv->xhci_exynos = xhci_exynos;
+
+	device_wakeup_enable(hcd->self.controller);
+
+	xhci->main_hcd = hcd;
+	xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,
+			dev_name(&pdev->dev), hcd);
+	if (!xhci->shared_hcd) {
+		ret = -ENOMEM;
+		goto disable_clk;
+	}
+	xhci->shared_hcd->skip_phy_initialization = 1;
+
+	xhci_exynos->shared_hcd = xhci->shared_hcd;
+
+	/* imod_interval is the interrupt moderation value in nanoseconds. */
+	xhci->imod_interval = 40000;
+
+	/* Iterate over all parent nodes for finding quirks */
+	for (tmpdev = &pdev->dev; tmpdev; tmpdev = tmpdev->parent) {
+
+		if (device_property_read_bool(tmpdev, "usb2-lpm-disable"))
+			xhci->quirks |= XHCI_HW_LPM_DISABLE;
+
+		if (device_property_read_bool(tmpdev, "usb3-lpm-capable"))
+			xhci->quirks |= XHCI_LPM_SUPPORT;
+
+		if (device_property_read_bool(tmpdev, "quirk-broken-port-ped"))
+			xhci->quirks |= XHCI_BROKEN_PORT_PED;
+
+		device_property_read_u32(tmpdev, "imod-interval-ns",
+					 &xhci->imod_interval);
+	}
+
+	hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
+	if (IS_ERR(hcd->usb_phy)) {
+		ret = PTR_ERR(hcd->usb_phy);
+		if (ret == -EPROBE_DEFER)
+			goto put_usb3_hcd;
+		hcd->usb_phy = NULL;
+	} else {
+		ret = usb_phy_init(hcd->usb_phy);
+		if (ret)
+			goto put_usb3_hcd;
+	}
+
+	/* Get USB2.0 PHY for main hcd */
+	if (parent) {
+		xhci_exynos->phy_usb2 = devm_phy_get(parent, "usb2-phy");
+		if (IS_ERR_OR_NULL(xhci_exynos->phy_usb2)) {
+			xhci_exynos->phy_usb2 = NULL;
+			dev_err(&pdev->dev,
+				"%s: failed to get phy\n", __func__);
+		}
+	}
+
+	/* Get USB3.0 PHY to tune the PHY */
+	if (parent) {
+		xhci_exynos->phy_usb3 =
+				devm_phy_get(parent, "usb3-phy");
+		if (IS_ERR_OR_NULL(xhci_exynos->phy_usb3)) {
+			xhci_exynos->phy_usb3 = NULL;
+			dev_err(&pdev->dev,
+				"%s: failed to get phy\n", __func__);
+		}
+	}
+
+	ret = of_property_read_u32(parent->of_node, "xhci_l2_support", &value);
+	if (ret == 0 && value == 1)
+		xhci->quirks |= XHCI_L2_SUPPORT;
+	else {
+		dev_err(&pdev->dev,
+			"can't get xhci l2 support, error = %d\n", ret);
+	}
+
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	ret = of_property_read_u32(parent->of_node,
+				"xhci_use_uram_for_audio", &value);
+	if (ret == 0 && value == 1) {
+		/*
+		 * Check URAM address. At least the following address should
+		 * be defined.(Otherwise, URAM feature will be disabled.)
+		 */
+		if (EXYNOS_URAM_DCBAA_ADDR == 0x0 ||
+				EXYNOS_URAM_ABOX_ERST_SEG_ADDR == 0x0 ||
+				EXYNOS_URAM_ABOX_EVT_RING_ADDR == 0x0 ||
+				EXYNOS_URAM_DEVICE_CTX_ADDR == 0x0 ||
+				EXYNOS_URAM_ISOC_OUT_RING_ADDR == 0x0) {
+			dev_info(&pdev->dev,
+				"Some URAM addresses are not defiend!\n");
+			goto skip_uram;
+		}
+
+		dev_info(&pdev->dev, "Support URAM for USB audio.\n");
+		xhci->quirks |= XHCI_USE_URAM_FOR_EXYNOS_AUDIO;
+		/* Initialization Default Value */
+		xhci_exynos->exynos_uram_ctx_alloc = false;
+		xhci_exynos->exynos_uram_isoc_out_alloc = false;
+		xhci_exynos->exynos_uram_isoc_in_alloc = false;
+		xhci_exynos->usb_audio_ctx_addr = NULL;
+		xhci_exynos->usb_audio_isoc_out_addr = NULL;
+		xhci_exynos->usb_audio_isoc_in_addr = NULL;
+	} else {
+		dev_err(&pdev->dev, "URAM is not used.\n");
+	}
+skip_uram:
+
+	xhci_exynos->xhci_alloc = &xhci_pre_alloc;
+
+#endif
+
+	hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
+	xhci->shared_hcd->tpl_support = hcd->tpl_support;
+	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (ret)
+		goto disable_usb_phy;
+
+	/* Set port_dev quirks for reduce port initialize time */
+	hdev = xhci->main_hcd->self.root_hub;
+	hub = usb_get_intfdata(hdev->actconfig->interface[0]);
+	port_dev = hub->ports[0];
+	port_dev->quirks |= USB_PORT_QUIRK_FAST_ENUM;
+
+	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
+		xhci->shared_hcd->can_do_streams = 1;
+
+	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
+	if (ret)
+		goto dealloc_usb2_hcd;
+
+	/* Set port_dev quirks for reduce port initialize time */
+	hdev = xhci->shared_hcd->self.root_hub;
+	hub = usb_get_intfdata(hdev->actconfig->interface[0]);
+	if (hub) {
+		port_dev = hub->ports[0];
+		port_dev->quirks |= USB_PORT_QUIRK_FAST_ENUM;
+	}
+
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	ret = of_property_read_u32(parent->of_node,
+			"usb_audio_offloading", &value);
+	if (ret == 0 && value == 1) {
+		ret = exynos_usb_audio_init(parent, pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "USB Audio INIT fail\n");
+			goto dealloc_usb2_hcd;
+		}
+		dev_info(&pdev->dev, "USB Audio offloading is supported\n");
+	} else
+		dev_err(&pdev->dev, "No usb offloading, err = %d\n", ret);
+
+	xhci_exynos->out_dma = xhci_data.out_data_dma;
+	xhci_exynos->out_addr = xhci_data.out_data_addr;
+	xhci_exynos->in_dma = xhci_data.in_data_dma;
+	xhci_exynos->in_addr = xhci_data.in_data_addr;
+#endif
+
+	device_enable_async_suspend(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
+
+	device_set_wakeup_enable(&xhci->main_hcd->self.root_hub->dev, 1);
+
+#ifdef CONFIG_EXYNOS_USBDRD_PHY30
+	device_set_wakeup_enable(&xhci->shared_hcd->self.root_hub->dev, 1);
+#else
+	device_set_wakeup_enable(&xhci->shared_hcd->self.root_hub->dev, 0);
+#endif
+
+	/*
+	 * Prevent runtime pm from being on as default, users should enable
+	 * runtime pm using power/control in sysfs.
+	 */
+	pm_runtime_forbid(&pdev->dev);
+
+	return 0;
+
+
+dealloc_usb2_hcd:
+	usb_remove_hcd(hcd);
+
+disable_usb_phy:
+	usb_phy_shutdown(hcd->usb_phy);
+
+put_usb3_hcd:
+	usb_put_hcd(xhci->shared_hcd);
+
+disable_clk:
+	clk_disable_unprepare(xhci->clk);
+
+disable_reg_clk:
+	clk_disable_unprepare(xhci->reg_clk);
+
+put_hcd:
+	xhci_exynos_unregister_notify();
+	usb_put_hcd(hcd);
+
+disable_runtime:
+	pm_runtime_put_noidle(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	if (main_wakelock) {
+		wakeup_source_unregister(main_wakelock);
+		pr_err("%s: unregister main_wakelock", __func__);
+	}
+	if (shared_wakelock) {
+		wakeup_source_unregister(shared_wakelock);
+		pr_err("%s: unregister shared_wakelock", __func__);
+	}
+
+	return ret;
+}
+
+static int xhci_exynos_remove(struct platform_device *dev)
+{
+	struct xhci_hcd_exynos *xhci_exynos = platform_get_drvdata(dev);
+	struct usb_hcd	*hcd = xhci_exynos->hcd;
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	struct device	*parent = dev->dev.parent;
+#endif
+	struct clk *clk = xhci->clk;
+	struct clk *reg_clk = xhci->reg_clk;
+	struct usb_hcd *shared_hcd = xhci->shared_hcd;
+	struct usb_device *rhdev = hcd->self.root_hub;
+	struct usb_device *srhdev = shared_hcd->self.root_hub;
+	struct usb_device *udev;
+	int port, need_wait, timeout;
+
+	dev_info(&dev->dev, "XHCI PLAT REMOVE\n");
+
+	pm_runtime_get_sync(&dev->dev);
+	xhci->xhc_state |= XHCI_STATE_REMOVING;
+
+	if (xhci_exynos->port_state == PORT_USB2)
+		usb_power_notify_control(0, 1);
+
+	xhci_exynos_port_power_set(1, 3);
+
+	xhci_exynos->usb3_portsc = NULL;
+	xhci_exynos->port_set_delayed = 0;
+
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	xhci_exynos->xhci_alloc->offset = 0;
+	dev_info(&dev->dev, "WAKE UNLOCK\n");
+#endif
+
+	__pm_relax(xhci_exynos->main_wakelock);
+
+	__pm_relax(xhci_exynos->shared_wakelock);
+
+	xhci_exynos_unregister_notify();
+
+	if (!rhdev || !srhdev)
+		goto remove_hcd;
+
+	/* check all ports */
+	for (timeout = 0; timeout < XHCI_HUB_EVENT_TIMEOUT; timeout++) {
+		need_wait = false;
+		usb_hub_for_each_child(rhdev, port, udev) {
+			if (udev && udev->devnum != -1)
+				need_wait = true;
+		}
+		if (need_wait == false) {
+			usb_hub_for_each_child(srhdev, port, udev) {
+				if (udev && udev->devnum != -1)
+					need_wait = true;
+			}
+		}
+		if (need_wait == true) {
+			usleep_range(20000, 22000);
+			timeout += 20;
+			xhci_info(xhci, "Waiting USB hub disconnect\n");
+		} else {
+			xhci_info(xhci,	"device disconnect all done\n");
+			break;
+		}
+	}
+
+remove_hcd:
+	usb_remove_hcd(shared_hcd);
+	xhci->shared_hcd = NULL;
+	usb_phy_shutdown(hcd->usb_phy);
+	/*
+	 * In usb_remove_hcd, phy_exit is called if phy is not NULL.
+	 * However, in the case that PHY was turn on or off as runtime PM,
+	 * PHY sould not exit at this time. So, to prevent the PHY exit,
+	 * PHY pointer have to be NULL.
+	 */
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	if (parent && xhci_exynos->phy_usb2)
+		xhci_exynos->phy_usb2 = NULL;
+
+	if (parent && xhci_exynos->phy_usb3)
+		xhci_exynos->phy_usb3 = NULL;
+#endif
+	usb_remove_hcd(hcd);
+
+	xhci_vendor_cleanup(xhci);
+	wakeup_source_unregister(xhci_exynos->main_wakelock);
+	wakeup_source_unregister(xhci_exynos->shared_wakelock);
+
+	devm_iounmap(&dev->dev, hcd->regs);
+	usb_put_hcd(shared_hcd);
+
+	clk_disable_unprepare(clk);
+	clk_disable_unprepare(reg_clk);
+	usb_put_hcd(hcd);
+
+	pm_runtime_disable(&dev->dev);
+	pm_runtime_put_noidle(&dev->dev);
+	pm_runtime_set_suspended(&dev->dev);
+
+	return 0;
+}
+
+/*
+static void xhci_exynos_shutdown(struct platform_device *dev)
+{
+	struct xhci_hcd_exynos *xhci_exynos = platform_get_drvdata(dev);
+	struct usb_hcd	*hcd = xhci_exynos->hcd;
+
+	platform_set_drvdata(dev, hcd);
+	usb_hcd_platform_shutdown(dev);
+	platform_set_drvdata(dev, xhci_exynos);
+}
+*/
+extern u32 otg_is_connect(void);
+static int __maybe_unused xhci_exynos_suspend(struct device *dev)
+{
+	struct xhci_hcd_exynos *xhci_exynos = dev_get_drvdata(dev);
+	struct usb_hcd	*hcd = xhci_exynos->hcd;
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	int ret = 0;
+
+	if (otg_is_connect() == 1) { /* If it is OTG_CONNECT_ONLY */
+		ret = xhci_priv_suspend_quirk(hcd);
+		if (ret)
+			return ret;
+		/*
+		 * xhci_suspend() needs `do_wakeup` to know whether host is allowed
+		 * to do wakeup during suspend.
+		 */
+		pr_info("[%s]: xhci_suspend!\n", __func__);
+		ret = xhci_suspend(xhci, device_may_wakeup(dev));
+	} else {  /* Enable HS ReWA */
+		exynos_usbdrd_phy_vendor_set(xhci_exynos->phy_usb2, 1, 0);
+#ifdef CONFIG_EXYNOS_USBDRD_PHY30
+		/* Enable SS ReWA */
+		exynos_usbdrd_phy_vendor_set(xhci_exynos->phy_usb3, 1, 0);
+#endif
+		is_rewa_enabled = 1;
+	}
+	usb_dr_role_control(0);
+
+	return ret;
+}
+
+static int __maybe_unused xhci_exynos_resume(struct device *dev)
+{
+	struct xhci_hcd_exynos *xhci_exynos = dev_get_drvdata(dev);
+	struct usb_hcd	*hcd = xhci_exynos->hcd;
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	int ret;
+
+	ret = xhci_priv_resume_quirk(hcd);
+	if (ret)
+		return ret;
+
+	if (otg_is_connect() == 1) { /* If it is OTG_CONNECT_ONLY */
+		pr_info("[%s]: xhci_resume!\n", __func__);
+		ret = xhci_resume(xhci, 0);
+
+		if (ret)
+			return ret;
+	}
+
+	if (is_rewa_enabled == 1) {
+#ifdef CONFIG_EXYNOS_USBDRD_PHY30
+		/* Disable SS ReWA */
+		exynos_usbdrd_phy_vendor_set(xhci_exynos->phy_usb3, 1, 1);
+#endif
+		/* Disablee HS ReWA */
+		exynos_usbdrd_phy_vendor_set(xhci_exynos->phy_usb2, 1, 1);
+		exynos_usbdrd_phy_vendor_set(xhci_exynos->phy_usb2, 0, 0);
+		is_rewa_enabled = 0;
+	}
+	usb_dr_role_control(1);
+
+	return ret;
+}
+
+static const struct dev_pm_ops xhci_plat_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(xhci_exynos_suspend, xhci_exynos_resume)
+};
+
+static const struct acpi_device_id usb_xhci_acpi_match[] = {
+	/* XHCI-compliant USB Controller */
+	{ "PNP0D10", },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
+
+static struct platform_driver usb_xhci_driver = {
+	.probe	= xhci_exynos_probe,
+	.remove	= xhci_exynos_remove,
+	/* Host is supposed to removed in usb_reboot_noti.
+	 * Thats's why we don't need xhci_exynos_shutdown.
+	 * .shutdown = xhci_exynos_shutdown,
+	 */
+	.driver	= {
+		.name = "xhci-hcd-exynos",
+		.pm = &xhci_plat_pm_ops,
+		.of_match_table = of_match_ptr(usb_xhci_of_match),
+		.acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
+		.dev_groups = xhci_exynos_groups,
+	},
+};
+MODULE_ALIAS("platform:xhci-hcd-exynos");
+
+static int __init xhci_exynos_init(void)
+{
+	xhci_init_driver(&xhci_exynos_hc_driver, &xhci_exynos_overrides);
+	return platform_driver_register(&usb_xhci_driver);
+}
+module_init(xhci_exynos_init);
+
+static void __exit xhci_exynos_exit(void)
+{
+	platform_driver_unregister(&usb_xhci_driver);
+}
+module_exit(xhci_exynos_exit);
+
+MODULE_DESCRIPTION("xHCI Exynos Platform Host Controller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/xhci-exynos.h b/drivers/usb/host/xhci-exynos.h
new file mode 100644
index 000000000000..51a872e19fa5
--- /dev/null
+++ b/drivers/usb/host/xhci-exynos.h
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * xhci-exynos.h - xHCI host controller driver platform Bus Glue for Exynos.
+ *
+ * Copyright (C) 2022 Samsung Electronics Incorporated - http://www.samsung.com
+ * Author: Daehwan Jung <dh10.jung@samsung.com>
+ *
+ * A lot of code borrowed from the Linux xHCI driver.
+ */
+
+#include "xhci.h"
+#include "../dwc3/dwc3-exynos.h"
+
+/*
+ * Sometimes deadlock occurred between hub_event and remove_hcd.
+ * In order to prevent it, waiting for completion of hub_event was added.
+ * This is a timeout (300msec) value for the waiting.
+ */
+#define XHCI_HUB_EVENT_TIMEOUT	(300)
+
+#define XHCI_USE_URAM_FOR_EXYNOS_AUDIO	BIT_ULL(62)
+#define XHCI_L2_SUPPORT			BIT_ULL(63)
+
+#define PORTSC_OFFSET		0x430
+
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+
+/* EXYNOS uram memory map */
+#if defined(CONFIG_SOC_S5E9925)
+#define EXYNOS_URAM_ABOX_EVT_RING_ADDR	0x02a00000
+#define EXYNOS_URAM_ISOC_OUT_RING_ADDR	0x02a01000
+#define EXYNOS_URAM_ISOC_IN_RING_ADDR	0x02a02000
+#define EXYNOS_URAM_DEVICE_CTX_ADDR	0x02a03000
+#define EXYNOS_URAM_DCBAA_ADDR		0x02a03880
+#define EXYNOS_URAM_ABOX_ERST_SEG_ADDR	0x02a03C80
+#elif defined(CONFIG_SOC_S5E8825)
+#define EXYNOS_URAM_ABOX_EVT_RING_ADDR	0x13300000
+#define EXYNOS_URAM_ISOC_OUT_RING_ADDR	0x13301000
+#define EXYNOS_URAM_ISOC_IN_RING_ADDR	0x13302000
+#define EXYNOS_URAM_DEVICE_CTX_ADDR	0x13303000
+#define EXYNOS_URAM_DCBAA_ADDR		0x13303880
+#define EXYNOS_URAM_ABOX_ERST_SEG_ADDR	0x13303C80
+#else
+#error
+#endif
+#endif
+
+enum usb_port_state {
+	PORT_EMPTY = 0,		/* OTG only */
+	PORT_USB2,		/* usb 2.0 device only */
+	PORT_USB3,		/* usb 3.0 device only */
+	PORT_HUB,		/* usb hub single */
+	PORT_DP			/* DP device */
+};
+
+struct xhci_hcd_exynos {
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	struct	xhci_intr_reg __iomem *ir_set_audio;
+#endif
+
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+	struct xhci_ring	*event_ring_audio;
+	struct xhci_erst	erst_audio;
+	dma_addr_t save_dma;
+	void *save_addr;
+	dma_addr_t out_dma;
+	void *out_addr;
+	dma_addr_t in_dma;
+	void *in_addr;
+#endif
+	struct device		*dev;
+	struct usb_hcd		*hcd;
+	struct usb_hcd		*shared_hcd;
+
+	struct wakeup_source *main_wakelock; /* Wakelock for HS HCD */
+	struct wakeup_source *shared_wakelock; /* Wakelock for SS HCD */
+
+	void __iomem		*usb3_portsc;
+	spinlock_t		xhcioff_lock;
+	int			port_off_done;
+	int			port_set_delayed;
+	u32			portsc_control_priority;
+	enum usb_port_state	port_state;
+	int			dp_use;
+	int			usb3_phy_control;
+
+	struct usb_xhci_pre_alloc	*xhci_alloc;
+	struct phy		*phy_usb2;
+	struct phy		*phy_usb3;
+
+	/* This flag is used to check first allocation for URAM */
+	bool			exynos_uram_ctx_alloc;
+	bool			exynos_uram_isoc_out_alloc;
+	bool			exynos_uram_isoc_in_alloc;
+	u8			*usb_audio_ctx_addr;
+	u8			*usb_audio_isoc_out_addr;
+	u8			*usb_audio_isoc_in_addr;
+
+};
+
+struct usb_phy_roothub {
+	struct phy		*phy;
+	struct list_head	list;
+};
+
+struct xhci_exynos_priv {
+	const char *firmware_name;
+	unsigned long long quirks;
+	struct xhci_vendor_data *vendor_data;
+	int (*plat_setup)(struct usb_hcd *hcd);
+	void (*plat_start)(struct usb_hcd *hcd);
+	int (*init_quirk)(struct usb_hcd *hcd);
+	int (*suspend_quirk)(struct usb_hcd *hcd);
+	int (*resume_quirk)(struct usb_hcd *hcd);
+	struct xhci_hcd_exynos *xhci_exynos;
+};
+
+#define hcd_to_xhci_exynos_priv(h) ((struct xhci_exynos_priv *)hcd_to_xhci(h)->priv)
+#define xhci_to_exynos_priv(x) ((struct xhci_exynos_priv *)(x)->priv)
+
+extern int is_otg_only;
+extern int exynos_usbdrd_phy_vendor_set(struct phy *phy, int is_enable,
+					int is_cancel);
+extern int get_idle_ip_index(void);
+
+#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
+int xhci_store_hw_info(struct usb_hcd *hcd, struct usb_device *udev);
+int xhci_set_deq(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx,
+		unsigned int last_ep, struct usb_device *udev);
+extern void xhci_remove_stream_mapping(struct xhci_ring *ring);
+extern struct hcd_hw_info *g_hwinfo;
+extern int xhci_check_trb_in_td_math(struct xhci_hcd *xhci);
+void xhci_exynos_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring);
+extern void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg);
+extern void xhci_link_segments(struct xhci_segment *prev, struct xhci_segment *next,
+		enum xhci_ring_type type, bool chain_links);
+extern void xhci_initialize_ring_info(struct xhci_ring *ring,
+					unsigned int cycle_state);
+#endif
+
+int xhci_hub_check_speed(struct usb_hcd *hcd);
+int xhci_check_usbl2_support(struct usb_hcd *hcd);
+int xhci_wake_lock(struct usb_hcd *hcd, int is_lock);
+void xhci_usb_parse_endpoint(struct usb_device *udev, struct usb_endpoint_descriptor *desc,
+				int size);
+
+extern int exynos_usbdrd_phy_vendor_set(struct phy *phy, int is_enable,
+		int is_cancel);
+extern int exynos_usbdrd_phy_tune(struct phy *phy, int phy_state);
+void usb_power_notify_control(int owner, int on);
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 4/4] usb: host: add xhci-exynos module
  2022-03-04  6:23   ` [PATCH v1 4/4] usb: host: add xhci-exynos module Daehwan Jung
@ 2022-03-04  7:37     ` Greg Kroah-Hartman
  2022-03-07 10:07     ` Krzysztof Kozlowski
  1 sibling, 0 replies; 19+ messages in thread
From: Greg Kroah-Hartman @ 2022-03-04  7:37 UTC (permalink / raw)
  To: Daehwan Jung
  Cc: Mathias Nyman, open list:USB XHCI DRIVER, open list, Howard Yen,
	Jack Pham, Puma Hsu, J . Avila, chihhao . chen, sc.suh, cpgs,
	cpgsproxy5

On Fri, Mar 04, 2022 at 03:23:58PM +0900, Daehwan Jung wrote:
> Signed-off-by: Daehwan Jung <dh10.jung@samsung.com>

I can not take patches without any changelog comments, sorry.

Especially ones that do real things, like this, please describe what
this does properly.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage
  2022-03-04  6:23   ` [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage Daehwan Jung
@ 2022-03-07  9:59     ` Krzysztof Kozlowski
  2022-03-23  2:58       ` Jung Daehwan
  2022-03-08  5:35     ` kernel test robot
  1 sibling, 1 reply; 19+ messages in thread
From: Krzysztof Kozlowski @ 2022-03-07  9:59 UTC (permalink / raw)
  To: Daehwan Jung, Mathias Nyman, Greg Kroah-Hartman
  Cc: open list:USB XHCI DRIVER, open list, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, sc.suh, cpgs, cpgsproxy5

On 04/03/2022 07:23, Daehwan Jung wrote:
> Export symbols for xhci hooks usage:
> 	xhci_ring_free
> 	- Allow xhci hook to free xhci_ring.

Instead of copying-pasting the name of function, please explain why do
you need these symbols exported.

The "Why" is actually one of most important questions, because "what is
this patch doing" we can easily see...

> 
> 	xhci_get_slot_ctx
> 	- Allow xhci hook to get slot_ctx from the xhci_container_ctx
> 	  for getting the slot_ctx information to know which slot is
> 	  offloading and compare the context in remote subsystem memory
> 	  if needed.
> 


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 4/4] usb: host: add xhci-exynos module
  2022-03-04  6:23   ` [PATCH v1 4/4] usb: host: add xhci-exynos module Daehwan Jung
  2022-03-04  7:37     ` Greg Kroah-Hartman
@ 2022-03-07 10:07     ` Krzysztof Kozlowski
  2022-03-07 10:26       ` Jung Daehwan
  1 sibling, 1 reply; 19+ messages in thread
From: Krzysztof Kozlowski @ 2022-03-07 10:07 UTC (permalink / raw)
  To: Daehwan Jung, Mathias Nyman, Greg Kroah-Hartman, Randy Dunlap
  Cc: open list:USB XHCI DRIVER, open list, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, sc.suh, cpgs, cpgsproxy5

On 04/03/2022 07:23, Daehwan Jung wrote:
> Signed-off-by: Daehwan Jung <dh10.jung@samsung.com>

+Cc Randy,
I guess here is the rest of the patches.

> ---
>  drivers/usb/host/xhci-exynos.c | 2025 ++++++++++++++++++++++++++++++++
>  drivers/usb/host/xhci-exynos.h |  150 +++
>  2 files changed, 2175 insertions(+)
>  create mode 100644 drivers/usb/host/xhci-exynos.c
>  create mode 100644 drivers/usb/host/xhci-exynos.h
> 
> diff --git a/drivers/usb/host/xhci-exynos.c b/drivers/usb/host/xhci-exynos.c
> new file mode 100644
> index 000000000000..3913c48d4b20
> --- /dev/null
> +++ b/drivers/usb/host/xhci-exynos.c
> @@ -0,0 +1,2025 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * xhci-exynos.c - xHCI host controller driver platform Bus Glue for Exynos.
> + *
> + * Copyright (C) 2022 Samsung Electronics Incorporated - http://www.samsung.com
> + * Author: Daehwan Jung <dh10.jung@samsung.com>
> + *
> + * A lot of code borrowed from the Linux xHCI driver.

> + */
> +
> +#include <linux/clk.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/usb/phy.h>
> +#include <linux/slab.h>
> +#include <linux/phy/phy.h>
> +#include <linux/acpi.h>
> +#include <linux/usb/of.h>
> +#ifdef CONFIG_SND_EXYNOS_USB_AUDIO

This does not exist.

Please do not add dead code to Linux kernel.

> +#include "../../../sound/usb/exynos_usb_audio.h"
> +#include <linux/types.h>
> +#include "xhci-trace.h"
> +#endif
> +
> +#include "../core/hub.h"
> +#include "../core/phy.h"
> +#include "xhci.h"
> +#include "xhci-plat.h"
> +#include "xhci-mvebu.h"
> +#include "xhci-rcar.h"
> +#include "../dwc3/dwc3-exynos.h"
> +#include "../dwc3/exynos-otg.h"

No, how XHCI is related to dwc3? What if different block provides XHCI,
not DWC3?

> +#include "xhci-exynos.h"
> +#include <soc/samsung/exynos-cpupm.h>

This does not exist and does not even compile.

Please do not send code which does not compile... Also, just in case -
do not send code which compiles but does not work. :)


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 4/4] usb: host: add xhci-exynos module
  2022-03-07 10:07     ` Krzysztof Kozlowski
@ 2022-03-07 10:26       ` Jung Daehwan
  2022-03-07 10:59         ` Krzysztof Kozlowski
  0 siblings, 1 reply; 19+ messages in thread
From: Jung Daehwan @ 2022-03-07 10:26 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Mathias Nyman, Greg Kroah-Hartman, Randy Dunlap,
	open list:USB XHCI DRIVER, open list, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, sc.suh, cpgs, cpgsproxy5

[-- Attachment #1: Type: text/plain, Size: 2600 bytes --]

On Mon, Mar 07, 2022 at 11:07:04AM +0100, Krzysztof Kozlowski wrote:
> On 04/03/2022 07:23, Daehwan Jung wrote:
> > Signed-off-by: Daehwan Jung <dh10.jung@samsung.com>
> 
> +Cc Randy,
> I guess here is the rest of the patches.
> 
> > ---
> >  drivers/usb/host/xhci-exynos.c | 2025 ++++++++++++++++++++++++++++++++
> >  drivers/usb/host/xhci-exynos.h |  150 +++
> >  2 files changed, 2175 insertions(+)
> >  create mode 100644 drivers/usb/host/xhci-exynos.c
> >  create mode 100644 drivers/usb/host/xhci-exynos.h
> > 
> > diff --git a/drivers/usb/host/xhci-exynos.c b/drivers/usb/host/xhci-exynos.c
> > new file mode 100644
> > index 000000000000..3913c48d4b20
> > --- /dev/null
> > +++ b/drivers/usb/host/xhci-exynos.c
> > @@ -0,0 +1,2025 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * xhci-exynos.c - xHCI host controller driver platform Bus Glue for Exynos.
> > + *
> > + * Copyright (C) 2022 Samsung Electronics Incorporated - http://www.samsung.com
> > + * Author: Daehwan Jung <dh10.jung@samsung.com>
> > + *
> > + * A lot of code borrowed from the Linux xHCI driver.
> 
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/module.h>
> > +#include <linux/pci.h>
> > +#include <linux/of.h>
> > +#include <linux/of_device.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/usb/phy.h>
> > +#include <linux/slab.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/acpi.h>
> > +#include <linux/usb/of.h>
> > +#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
> 
> This does not exist.
> 
> Please do not add dead code to Linux kernel.
> 
> > +#include "../../../sound/usb/exynos_usb_audio.h"
> > +#include <linux/types.h>
> > +#include "xhci-trace.h"
> > +#endif
> > +
> > +#include "../core/hub.h"
> > +#include "../core/phy.h"
> > +#include "xhci.h"
> > +#include "xhci-plat.h"
> > +#include "xhci-mvebu.h"
> > +#include "xhci-rcar.h"
> > +#include "../dwc3/dwc3-exynos.h"
> > +#include "../dwc3/exynos-otg.h"
> 
> No, how XHCI is related to dwc3? What if different block provides XHCI,
> not DWC3?
> 
> > +#include "xhci-exynos.h"
> > +#include <soc/samsung/exynos-cpupm.h>
> 
> This does not exist and does not even compile.
> 
> Please do not send code which does not compile... Also, just in case -
> do not send code which compiles but does not work. :)
> 

Hi Krzysztof

I'm sorry to confuse you. But, it's just for reference module to introduce
new feature. That's why I just submitted source code and header without
makefile. It's not going to compiled at all now.

Best Regards,
Jung Deahwan

> 
> Best regards,
> Krzysztof
> 

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 4/4] usb: host: add xhci-exynos module
  2022-03-07 10:26       ` Jung Daehwan
@ 2022-03-07 10:59         ` Krzysztof Kozlowski
  0 siblings, 0 replies; 19+ messages in thread
From: Krzysztof Kozlowski @ 2022-03-07 10:59 UTC (permalink / raw)
  To: Jung Daehwan
  Cc: Mathias Nyman, Greg Kroah-Hartman, Randy Dunlap,
	open list:USB XHCI DRIVER, open list, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, sc.suh, cpgs, cpgsproxy5

On 07/03/2022 11:26, Jung Daehwan wrote:
> On Mon, Mar 07, 2022 at 11:07:04AM +0100, Krzysztof Kozlowski wrote:
>> On 04/03/2022 07:23, Daehwan Jung wrote:
>>> Signed-off-by: Daehwan Jung <dh10.jung@samsung.com>
>>
>> +Cc Randy,
>> I guess here is the rest of the patches.
>>
>>> ---
>>>  drivers/usb/host/xhci-exynos.c | 2025 ++++++++++++++++++++++++++++++++
>>>  drivers/usb/host/xhci-exynos.h |  150 +++
>>>  2 files changed, 2175 insertions(+)
>>>  create mode 100644 drivers/usb/host/xhci-exynos.c
>>>  create mode 100644 drivers/usb/host/xhci-exynos.h
>>>
>>> diff --git a/drivers/usb/host/xhci-exynos.c b/drivers/usb/host/xhci-exynos.c
>>> new file mode 100644
>>> index 000000000000..3913c48d4b20
>>> --- /dev/null
>>> +++ b/drivers/usb/host/xhci-exynos.c
>>> @@ -0,0 +1,2025 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * xhci-exynos.c - xHCI host controller driver platform Bus Glue for Exynos.
>>> + *
>>> + * Copyright (C) 2022 Samsung Electronics Incorporated - http://www.samsung.com
>>> + * Author: Daehwan Jung <dh10.jung@samsung.com>
>>> + *
>>> + * A lot of code borrowed from the Linux xHCI driver.
>>
>>> + */
>>> +
>>> +#include <linux/clk.h>
>>> +#include <linux/dma-mapping.h>
>>> +#include <linux/module.h>
>>> +#include <linux/pci.h>
>>> +#include <linux/of.h>
>>> +#include <linux/of_device.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/usb/phy.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/phy/phy.h>
>>> +#include <linux/acpi.h>
>>> +#include <linux/usb/of.h>
>>> +#ifdef CONFIG_SND_EXYNOS_USB_AUDIO
>>
>> This does not exist.
>>
>> Please do not add dead code to Linux kernel.
>>
>>> +#include "../../../sound/usb/exynos_usb_audio.h"
>>> +#include <linux/types.h>
>>> +#include "xhci-trace.h"
>>> +#endif
>>> +
>>> +#include "../core/hub.h"
>>> +#include "../core/phy.h"
>>> +#include "xhci.h"
>>> +#include "xhci-plat.h"
>>> +#include "xhci-mvebu.h"
>>> +#include "xhci-rcar.h"
>>> +#include "../dwc3/dwc3-exynos.h"
>>> +#include "../dwc3/exynos-otg.h"
>>
>> No, how XHCI is related to dwc3? What if different block provides XHCI,
>> not DWC3?
>>
>>> +#include "xhci-exynos.h"
>>> +#include <soc/samsung/exynos-cpupm.h>
>>
>> This does not exist and does not even compile.
>>
>> Please do not send code which does not compile... Also, just in case -
>> do not send code which compiles but does not work. :)
>>
> 
> Hi Krzysztof
> 
> I'm sorry to confuse you. But, it's just for reference module to introduce
> new feature. That's why I just submitted source code and header without
> makefile. It's not going to compiled at all now.

Thanks for explanation. Such of tree code must be clearly marked in
commit title and subject (e.g. RFC). Additionally this out of tree
module does not solve the problem of lack of users. For all your sound
hooks you need in-tree user.

Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage
  2022-03-04  6:23   ` [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage Daehwan Jung
  2022-03-07  9:59     ` Krzysztof Kozlowski
@ 2022-03-08  5:35     ` kernel test robot
  1 sibling, 0 replies; 19+ messages in thread
From: kernel test robot @ 2022-03-08  5:35 UTC (permalink / raw)
  To: Daehwan Jung, Mathias Nyman, Greg Kroah-Hartman
  Cc: llvm, kbuild-all, linux-usb, linux-kernel, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, Daehwan Jung, sc.suh, cpgs,
	cpgsproxy5

Hi Daehwan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on krzk/for-next]
[also build test WARNING on char-misc/char-misc-testing v5.17-rc7 next-20220307]
[cannot apply to usb/usb-testing]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Daehwan-Jung/usb-host-export-symbols-for-xhci-hooks-usage/20220304-143406
base:   https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git for-next
config: hexagon-randconfig-r045-20220304 (https://download.01.org/0day-ci/archive/20220308/202203081332.nZHV3ZBo-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project d271fc04d5b97b12e6b797c6067d3c96a8d7470e)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/66bd02564cf7e666cf4c47f83965148fa5b90829
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Daehwan-Jung/usb-host-export-symbols-for-xhci-hooks-usage/20220304-143406
        git checkout 66bd02564cf7e666cf4c47f83965148fa5b90829
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/usb/host/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/usb/host/xhci-mem.c:68:6: warning: no previous prototype for function 'xhci_segment_free' [-Wmissing-prototypes]
   void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg)
        ^
   drivers/usb/host/xhci-mem.c:68:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg)
   ^
   static 
   drivers/usb/host/xhci-mem.c:79:6: warning: no previous prototype for function 'xhci_free_segments_for_ring' [-Wmissing-prototypes]
   void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
        ^
   drivers/usb/host/xhci-mem.c:79:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
   ^
   static 
   drivers/usb/host/xhci-mem.c:100:6: warning: no previous prototype for function 'xhci_link_segments' [-Wmissing-prototypes]
   void xhci_link_segments(struct xhci_segment *prev,
        ^
   drivers/usb/host/xhci-mem.c:100:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void xhci_link_segments(struct xhci_segment *prev,
   ^
   static 
>> drivers/usb/host/xhci-mem.c:211:6: warning: no previous prototype for function 'xhci_remove_segment_mapping' [-Wmissing-prototypes]
   void xhci_remove_segment_mapping(struct radix_tree_root *trb_address_map,
        ^
   drivers/usb/host/xhci-mem.c:211:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void xhci_remove_segment_mapping(struct radix_tree_root *trb_address_map,
   ^
   static 
>> drivers/usb/host/xhci-mem.c:262:6: warning: no previous prototype for function 'xhci_remove_stream_mapping' [-Wmissing-prototypes]
   void xhci_remove_stream_mapping(struct xhci_ring *ring)
        ^
   drivers/usb/host/xhci-mem.c:262:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void xhci_remove_stream_mapping(struct xhci_ring *ring)
   ^
   static 
   drivers/usb/host/xhci-mem.c:1984:5: warning: no previous prototype for function 'xhci_check_trb_in_td_math' [-Wmissing-prototypes]
   int xhci_check_trb_in_td_math(struct xhci_hcd *xhci)
       ^
   drivers/usb/host/xhci-mem.c:1984:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int xhci_check_trb_in_td_math(struct xhci_hcd *xhci)
   ^
   static 
   6 warnings generated.


vim +/xhci_remove_segment_mapping +211 drivers/usb/host/xhci-mem.c

   210	
 > 211	void xhci_remove_segment_mapping(struct radix_tree_root *trb_address_map,
   212			struct xhci_segment *seg)
   213	{
   214		unsigned long key;
   215	
   216		key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT);
   217		if (radix_tree_lookup(trb_address_map, key))
   218			radix_tree_delete(trb_address_map, key);
   219	}
   220	EXPORT_SYMBOL_GPL(xhci_remove_segment_mapping);
   221	
   222	static int xhci_update_stream_segment_mapping(
   223			struct radix_tree_root *trb_address_map,
   224			struct xhci_ring *ring,
   225			struct xhci_segment *first_seg,
   226			struct xhci_segment *last_seg,
   227			gfp_t mem_flags)
   228	{
   229		struct xhci_segment *seg;
   230		struct xhci_segment *failed_seg;
   231		int ret;
   232	
   233		if (WARN_ON_ONCE(trb_address_map == NULL))
   234			return 0;
   235	
   236		seg = first_seg;
   237		do {
   238			ret = xhci_insert_segment_mapping(trb_address_map,
   239					ring, seg, mem_flags);
   240			if (ret)
   241				goto remove_streams;
   242			if (seg == last_seg)
   243				return 0;
   244			seg = seg->next;
   245		} while (seg != first_seg);
   246	
   247		return 0;
   248	
   249	remove_streams:
   250		failed_seg = seg;
   251		seg = first_seg;
   252		do {
   253			xhci_remove_segment_mapping(trb_address_map, seg);
   254			if (seg == failed_seg)
   255				return ret;
   256			seg = seg->next;
   257		} while (seg != first_seg);
   258	
   259		return ret;
   260	}
   261	
 > 262	void xhci_remove_stream_mapping(struct xhci_ring *ring)
   263	{
   264		struct xhci_segment *seg;
   265	
   266		if (WARN_ON_ONCE(ring->trb_address_map == NULL))
   267			return;
   268	
   269		seg = ring->first_seg;
   270		do {
   271			xhci_remove_segment_mapping(ring->trb_address_map, seg);
   272			seg = seg->next;
   273		} while (seg != ring->first_seg);
   274	}
   275	EXPORT_SYMBOL_GPL(xhci_remove_stream_mapping);
   276	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 2/4] usb: host: add xhci hooks for USB offload
  2022-03-04  6:23   ` [PATCH v1 2/4] usb: host: add xhci hooks for USB offload Daehwan Jung
@ 2022-03-08  6:16     ` kernel test robot
  2022-03-08 10:51     ` kernel test robot
  1 sibling, 0 replies; 19+ messages in thread
From: kernel test robot @ 2022-03-08  6:16 UTC (permalink / raw)
  To: Daehwan Jung, Mathias Nyman, Greg Kroah-Hartman
  Cc: llvm, kbuild-all, linux-usb, linux-kernel, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, Daehwan Jung, sc.suh, cpgs,
	cpgsproxy5

Hi Daehwan,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on krzk/for-next]
[also build test ERROR on char-misc/char-misc-testing v5.17-rc7]
[cannot apply to usb/usb-testing next-20220307]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Daehwan-Jung/usb-host-export-symbols-for-xhci-hooks-usage/20220304-143406
base:   https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git for-next
config: hexagon-randconfig-r045-20220304 (https://download.01.org/0day-ci/archive/20220308/202203081440.zCZudmlJ-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project d271fc04d5b97b12e6b797c6067d3c96a8d7470e)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/2b6a5d700c2bbb0a3ccfcd6e83a7f7b2ea049db9
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Daehwan-Jung/usb-host-export-symbols-for-xhci-hooks-usage/20220304-143406
        git checkout 2b6a5d700c2bbb0a3ccfcd6e83a7f7b2ea049db9
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/usb/host/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/usb/host/xhci.c:4361:5: warning: no previous prototype for function 'xhci_address_device' [-Wmissing-prototypes]
   int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
       ^
   drivers/usb/host/xhci.c:4361:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
   ^
   static 
>> drivers/usb/host/xhci.c:4459:15: error: no member named 'vendor_ops' in 'struct xhci_hcd'
           return xhci->vendor_ops;
                  ~~~~  ^
   drivers/usb/host/xhci.c:5421:23: warning: shift count >= width of type [-Wshift-count-overflow]
                           !dma_set_mask(dev, DMA_BIT_MASK(64))) {
                           ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
   include/linux/dma-mapping.h:76:54: note: expanded from macro 'DMA_BIT_MASK'
   #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
                                                        ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:52: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                      ^~~~
   drivers/usb/host/xhci.c:5421:23: warning: shift count >= width of type [-Wshift-count-overflow]
                           !dma_set_mask(dev, DMA_BIT_MASK(64))) {
                           ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
   include/linux/dma-mapping.h:76:54: note: expanded from macro 'DMA_BIT_MASK'
   #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
                                                        ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:61: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                               ^~~~
   drivers/usb/host/xhci.c:5421:23: warning: shift count >= width of type [-Wshift-count-overflow]
                           !dma_set_mask(dev, DMA_BIT_MASK(64))) {
                           ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
   include/linux/dma-mapping.h:76:54: note: expanded from macro 'DMA_BIT_MASK'
   #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
                                                        ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:86: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                                       ~~~~~~~~~~~~~~~~~^~~~~
   include/linux/compiler.h:69:3: note: expanded from macro '__trace_if_value'
           (cond) ?                                        \
            ^~~~
   drivers/usb/host/xhci.c:5423:30: warning: shift count >= width of type [-Wshift-count-overflow]
                   dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
                                              ^~~~~~~~~~~~~~~~
   include/linux/dma-mapping.h:76:54: note: expanded from macro 'DMA_BIT_MASK'
   #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
                                                        ^ ~~~
   5 warnings and 1 error generated.
--
>> drivers/usb/host/xhci-plat.c:205:15: error: no member named 'vendor_ops' in 'struct xhci_hcd'
                   ops = xhci->vendor_ops = xhci_plat_vendor_overwrite.vendor_ops;
                         ~~~~  ^
   drivers/usb/host/xhci-plat.c:219:8: error: no member named 'vendor_ops' in 'struct xhci_hcd'
           xhci->vendor_ops = NULL;
           ~~~~  ^
   drivers/usb/host/xhci-plat.c:268:10: warning: shift count >= width of type [-Wshift-count-overflow]
                                                      DMA_BIT_MASK(64));
                                                      ^~~~~~~~~~~~~~~~
   include/linux/dma-mapping.h:76:54: note: expanded from macro 'DMA_BIT_MASK'
   #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
                                                        ^ ~~~
   drivers/usb/host/xhci-plat.c:270:43: warning: shift count >= width of type [-Wshift-count-overflow]
                   ret = dma_set_mask_and_coherent(sysdev, DMA_BIT_MASK(64));
                                                           ^~~~~~~~~~~~~~~~
   include/linux/dma-mapping.h:76:54: note: expanded from macro 'DMA_BIT_MASK'
   #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
                                                        ^ ~~~
   2 warnings and 2 errors generated.


vim +4459 drivers/usb/host/xhci.c

  4456	
  4457	struct xhci_vendor_ops *xhci_vendor_get_ops(struct xhci_hcd *xhci)
  4458	{
> 4459		return xhci->vendor_ops;
  4460	}
  4461	EXPORT_SYMBOL_GPL(xhci_vendor_get_ops);
  4462	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 2/4] usb: host: add xhci hooks for USB offload
  2022-03-04  6:23   ` [PATCH v1 2/4] usb: host: add xhci hooks for USB offload Daehwan Jung
  2022-03-08  6:16     ` kernel test robot
@ 2022-03-08 10:51     ` kernel test robot
  1 sibling, 0 replies; 19+ messages in thread
From: kernel test robot @ 2022-03-08 10:51 UTC (permalink / raw)
  To: Daehwan Jung, Mathias Nyman, Greg Kroah-Hartman
  Cc: kbuild-all, linux-usb, linux-kernel, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, Daehwan Jung, sc.suh, cpgs,
	cpgsproxy5

Hi Daehwan,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on krzk/for-next]
[also build test ERROR on char-misc/char-misc-testing v5.17-rc7]
[cannot apply to usb/usb-testing next-20220308]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Daehwan-Jung/usb-host-export-symbols-for-xhci-hooks-usage/20220304-143406
base:   https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git for-next
config: arm-hisi_defconfig (https://download.01.org/0day-ci/archive/20220308/202203081848.5KEiXYSo-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/2b6a5d700c2bbb0a3ccfcd6e83a7f7b2ea049db9
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Daehwan-Jung/usb-host-export-symbols-for-xhci-hooks-usage/20220304-143406
        git checkout 2b6a5d700c2bbb0a3ccfcd6e83a7f7b2ea049db9
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arm SHELL=/bin/bash drivers/usb/host/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/usb/host/xhci.c:4361:5: warning: no previous prototype for 'xhci_address_device' [-Wmissing-prototypes]
    4361 | int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
         |     ^~~~~~~~~~~~~~~~~~~
   drivers/usb/host/xhci.c: In function 'xhci_vendor_get_ops':
>> drivers/usb/host/xhci.c:4459:20: error: 'struct xhci_hcd' has no member named 'vendor_ops'
    4459 |         return xhci->vendor_ops;
         |                    ^~
   drivers/usb/host/xhci.c:4460:1: error: control reaches end of non-void function [-Werror=return-type]
    4460 | }
         | ^
   cc1: some warnings being treated as errors


vim +4459 drivers/usb/host/xhci.c

  4360	
> 4361	int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
  4362	{
  4363		return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ADDRESS);
  4364	}
  4365	EXPORT_SYMBOL_GPL(xhci_address_device);
  4366	
  4367	static int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev)
  4368	{
  4369		return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ONLY);
  4370	}
  4371	
  4372	/*
  4373	 * Transfer the port index into real index in the HW port status
  4374	 * registers. Caculate offset between the port's PORTSC register
  4375	 * and port status base. Divide the number of per port register
  4376	 * to get the real index. The raw port number bases 1.
  4377	 */
  4378	int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)
  4379	{
  4380		struct xhci_hub *rhub;
  4381	
  4382		rhub = xhci_get_rhub(hcd);
  4383		return rhub->ports[port1 - 1]->hw_portnum + 1;
  4384	}
  4385	
  4386	/*
  4387	 * Issue an Evaluate Context command to change the Maximum Exit Latency in the
  4388	 * slot context.  If that succeeds, store the new MEL in the xhci_virt_device.
  4389	 */
  4390	static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
  4391				struct usb_device *udev, u16 max_exit_latency)
  4392	{
  4393		struct xhci_virt_device *virt_dev;
  4394		struct xhci_command *command;
  4395		struct xhci_input_control_ctx *ctrl_ctx;
  4396		struct xhci_slot_ctx *slot_ctx;
  4397		unsigned long flags;
  4398		int ret;
  4399	
  4400		spin_lock_irqsave(&xhci->lock, flags);
  4401	
  4402		virt_dev = xhci->devs[udev->slot_id];
  4403	
  4404		/*
  4405		 * virt_dev might not exists yet if xHC resumed from hibernate (S4) and
  4406		 * xHC was re-initialized. Exit latency will be set later after
  4407		 * hub_port_finish_reset() is done and xhci->devs[] are re-allocated
  4408		 */
  4409	
  4410		if (!virt_dev || max_exit_latency == virt_dev->current_mel) {
  4411			spin_unlock_irqrestore(&xhci->lock, flags);
  4412			return 0;
  4413		}
  4414	
  4415		/* Attempt to issue an Evaluate Context command to change the MEL. */
  4416		command = xhci->lpm_command;
  4417		ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
  4418		if (!ctrl_ctx) {
  4419			spin_unlock_irqrestore(&xhci->lock, flags);
  4420			xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
  4421					__func__);
  4422			return -ENOMEM;
  4423		}
  4424	
  4425		ret = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id);
  4426		if (ret) {
  4427			spin_unlock_irqrestore(&xhci->lock, flags);
  4428			xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
  4429				  __func__, ret);
  4430			return ret;
  4431		}
  4432	
  4433		xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx);
  4434		spin_unlock_irqrestore(&xhci->lock, flags);
  4435	
  4436		ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
  4437		slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx);
  4438		slot_ctx->dev_info2 &= cpu_to_le32(~((u32) MAX_EXIT));
  4439		slot_ctx->dev_info2 |= cpu_to_le32(max_exit_latency);
  4440		slot_ctx->dev_state = 0;
  4441	
  4442		xhci_dbg_trace(xhci, trace_xhci_dbg_context_change,
  4443				"Set up evaluate context for LPM MEL change.");
  4444	
  4445		/* Issue and wait for the evaluate context command. */
  4446		ret = xhci_configure_endpoint(xhci, udev, command,
  4447				true, true);
  4448	
  4449		if (!ret) {
  4450			spin_lock_irqsave(&xhci->lock, flags);
  4451			virt_dev->current_mel = max_exit_latency;
  4452			spin_unlock_irqrestore(&xhci->lock, flags);
  4453		}
  4454		return ret;
  4455	}
  4456	
  4457	struct xhci_vendor_ops *xhci_vendor_get_ops(struct xhci_hcd *xhci)
  4458	{
> 4459		return xhci->vendor_ops;
  4460	}
  4461	EXPORT_SYMBOL_GPL(xhci_vendor_get_ops);
  4462	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage
  2022-03-07  9:59     ` Krzysztof Kozlowski
@ 2022-03-23  2:58       ` Jung Daehwan
  2022-03-23  9:41         ` Krzysztof Kozlowski
  0 siblings, 1 reply; 19+ messages in thread
From: Jung Daehwan @ 2022-03-23  2:58 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Mathias Nyman, Greg Kroah-Hartman, open list:USB XHCI DRIVER,
	open list, Howard Yen, Jack Pham, Puma Hsu, J . Avila,
	chihhao . chen, sc.suh, cpgs, cpgsproxy5

[-- Attachment #1: Type: text/plain, Size: 2030 bytes --]

On Mon, Mar 07, 2022 at 10:59:06AM +0100, Krzysztof Kozlowski wrote:
> On 04/03/2022 07:23, Daehwan Jung wrote:
> > Export symbols for xhci hooks usage:
> > 	xhci_ring_free
> > 	- Allow xhci hook to free xhci_ring.
> 
> Instead of copying-pasting the name of function, please explain why do
> you need these symbols exported.
> 
> The "Why" is actually one of most important questions, because "what is
> this patch doing" we can easily see...
> 
> > 
> > 	xhci_get_slot_ctx
> > 	- Allow xhci hook to get slot_ctx from the xhci_container_ctx
> > 	  for getting the slot_ctx information to know which slot is
> > 	  offloading and compare the context in remote subsystem memory
> > 	  if needed.
> > 
> 
> 
> Best regards,
> Krzysztof
> 

Hi Krzysztof

xhci_ring_free has been removed from v3..
The reason why I want to export is for managing vendor specific ring.
I want to alloc and free vendor specific ring on specific address.
It's done with xhci hooks.

Below is the patch of v3

Export symbols for xhci hooks usage:
    xhci_get_slot_ctx
    xhci_get_endpoint_address
    - Allow xhci hook to get ep_ctx from the xhci_container_ctx for
      getting the ep_ctx information to know which ep is offloading and
      comparing the context in remote subsystem memory if needed.

    xhci_ring_alloc
    - Allow xhci hook to allocate vendor specific ring.

    xhci_trb_virt_to_dma
    - Used to retrieve the DMA address of vendor specific ring.

    xhci_segment_free
    xhci_link_segments
    - Allow xhci hook to handle vendor specific segment.

    xhci_initialize_ring_info
    - Allow xhci hook to initialize vendor specific ring.

    xhci_check_trb_in_td_math
    - Allow xhci hook to Check TRB math for validation.

    xhci_address_device
    - Allow override to give configuration info to Co-processor.

    xhci_bus_suspend
    xhci_bus_resume
    - Allow override of suspend and resume for power scenario.

    xhci_remove_stream_mapping
    - Allow xhci hook to remove stream mapping.

Best Regards,
Jung Daehwan.

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage
  2022-03-23  2:58       ` Jung Daehwan
@ 2022-03-23  9:41         ` Krzysztof Kozlowski
  2022-03-23 11:43           ` Greg Kroah-Hartman
  2022-03-25  1:28           ` Jung Daehwan
  0 siblings, 2 replies; 19+ messages in thread
From: Krzysztof Kozlowski @ 2022-03-23  9:41 UTC (permalink / raw)
  To: Jung Daehwan
  Cc: Mathias Nyman, Greg Kroah-Hartman, open list:USB XHCI DRIVER,
	open list, Howard Yen, Jack Pham, Puma Hsu, J . Avila,
	chihhao . chen, sc.suh, cpgs, cpgsproxy5

On 23/03/2022 03:58, Jung Daehwan wrote:
> On Mon, Mar 07, 2022 at 10:59:06AM +0100, Krzysztof Kozlowski wrote:
>> On 04/03/2022 07:23, Daehwan Jung wrote:
>>> Export symbols for xhci hooks usage:
>>> 	xhci_ring_free
>>> 	- Allow xhci hook to free xhci_ring.
>>
>> Instead of copying-pasting the name of function, please explain why do
>> you need these symbols exported.
>>
>> The "Why" is actually one of most important questions, because "what is
>> this patch doing" we can easily see...
>>
>>>
>>> 	xhci_get_slot_ctx
>>> 	- Allow xhci hook to get slot_ctx from the xhci_container_ctx
>>> 	  for getting the slot_ctx information to know which slot is
>>> 	  offloading and compare the context in remote subsystem memory
>>> 	  if needed.
>>>
>>
>>
>> Best regards,
>> Krzysztof
>>
> 
> Hi Krzysztof
> 
> xhci_ring_free has been removed from v3..
> The reason why I want to export is for managing vendor specific ring.
> I want to alloc and free vendor specific ring on specific address.
> It's done with xhci hooks.

It's better, but still does not explain why these have to be exported.
Please mention where are these hooks going to be. Where are they
implemented. I actually expect all of these exports to be used in your
patchset.

Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage
  2022-03-23  9:41         ` Krzysztof Kozlowski
@ 2022-03-23 11:43           ` Greg Kroah-Hartman
  2022-03-25  2:07             ` Jung Daehwan
  2022-03-25  1:28           ` Jung Daehwan
  1 sibling, 1 reply; 19+ messages in thread
From: Greg Kroah-Hartman @ 2022-03-23 11:43 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Jung Daehwan, Mathias Nyman,
	open list:USB XHCI DRIVER, open list, Howard Yen, Jack Pham,
	Puma Hsu, J . Avila, chihhao . chen, sc.suh, cpgs, cpgsproxy5

On Wed, Mar 23, 2022 at 10:41:23AM +0100, Krzysztof Kozlowski wrote:
> On 23/03/2022 03:58, Jung Daehwan wrote:
> > On Mon, Mar 07, 2022 at 10:59:06AM +0100, Krzysztof Kozlowski wrote:
> >> On 04/03/2022 07:23, Daehwan Jung wrote:
> >>> Export symbols for xhci hooks usage:
> >>> 	xhci_ring_free
> >>> 	- Allow xhci hook to free xhci_ring.
> >>
> >> Instead of copying-pasting the name of function, please explain why do
> >> you need these symbols exported.
> >>
> >> The "Why" is actually one of most important questions, because "what is
> >> this patch doing" we can easily see...
> >>
> >>>
> >>> 	xhci_get_slot_ctx
> >>> 	- Allow xhci hook to get slot_ctx from the xhci_container_ctx
> >>> 	  for getting the slot_ctx information to know which slot is
> >>> 	  offloading and compare the context in remote subsystem memory
> >>> 	  if needed.
> >>>
> >>
> >>
> >> Best regards,
> >> Krzysztof
> >>
> > 
> > Hi Krzysztof
> > 
> > xhci_ring_free has been removed from v3..
> > The reason why I want to export is for managing vendor specific ring.
> > I want to alloc and free vendor specific ring on specific address.
> > It's done with xhci hooks.
> 
> It's better, but still does not explain why these have to be exported.
> Please mention where are these hooks going to be. Where are they
> implemented. I actually expect all of these exports to be used in your
> patchset.

All exports _HAVE_ to be used by the patchset.  Otherwise it's an
invalid submission.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage
  2022-03-23  9:41         ` Krzysztof Kozlowski
  2022-03-23 11:43           ` Greg Kroah-Hartman
@ 2022-03-25  1:28           ` Jung Daehwan
  2022-03-25 11:36             ` Krzysztof Kozlowski
  1 sibling, 1 reply; 19+ messages in thread
From: Jung Daehwan @ 2022-03-25  1:28 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Mathias Nyman, Greg Kroah-Hartman, open list:USB XHCI DRIVER,
	open list, Howard Yen, Jack Pham, Puma Hsu, J . Avila,
	chihhao . chen, sc.suh, cpgs, cpgsproxy5

[-- Attachment #1: Type: text/plain, Size: 1581 bytes --]

On Wed, Mar 23, 2022 at 10:41:23AM +0100, Krzysztof Kozlowski wrote:
> On 23/03/2022 03:58, Jung Daehwan wrote:
> > On Mon, Mar 07, 2022 at 10:59:06AM +0100, Krzysztof Kozlowski wrote:
> >> On 04/03/2022 07:23, Daehwan Jung wrote:
> >>> Export symbols for xhci hooks usage:
> >>> 	xhci_ring_free
> >>> 	- Allow xhci hook to free xhci_ring.
> >>
> >> Instead of copying-pasting the name of function, please explain why do
> >> you need these symbols exported.
> >>
> >> The "Why" is actually one of most important questions, because "what is
> >> this patch doing" we can easily see...
> >>
> >>>
> >>> 	xhci_get_slot_ctx
> >>> 	- Allow xhci hook to get slot_ctx from the xhci_container_ctx
> >>> 	  for getting the slot_ctx information to know which slot is
> >>> 	  offloading and compare the context in remote subsystem memory
> >>> 	  if needed.
> >>>
> >>
> >>
> >> Best regards,
> >> Krzysztof
> >>
> > 
> > Hi Krzysztof
> > 
> > xhci_ring_free has been removed from v3..
> > The reason why I want to export is for managing vendor specific ring.
> > I want to alloc and free vendor specific ring on specific address.
> > It's done with xhci hooks.
> 
> It's better, but still does not explain why these have to be exported.
> Please mention where are these hooks going to be. Where are they
> implemented. I actually expect all of these exports to be used in your
> patchset.
> 
> Best regards,
> Krzysztof
> 

OK. How about adding call stack like below?

xhci_free_endpoint_ring -> xhci_vendor_free_transfer_ring(xhck hooks
ops) -> xhci_ring_free

Best Regards,
Jung Daehwan

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage
  2022-03-23 11:43           ` Greg Kroah-Hartman
@ 2022-03-25  2:07             ` Jung Daehwan
  0 siblings, 0 replies; 19+ messages in thread
From: Jung Daehwan @ 2022-03-25  2:07 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Krzysztof Kozlowski, Mathias Nyman, open list:USB XHCI DRIVER,
	open list, Howard Yen, Jack Pham, Puma Hsu, J . Avila,
	chihhao . chen, sc.suh, cpgs, cpgsproxy5

[-- Attachment #1: Type: text/plain, Size: 1716 bytes --]

On Wed, Mar 23, 2022 at 12:43:32PM +0100, Greg Kroah-Hartman wrote:
> On Wed, Mar 23, 2022 at 10:41:23AM +0100, Krzysztof Kozlowski wrote:
> > On 23/03/2022 03:58, Jung Daehwan wrote:
> > > On Mon, Mar 07, 2022 at 10:59:06AM +0100, Krzysztof Kozlowski wrote:
> > >> On 04/03/2022 07:23, Daehwan Jung wrote:
> > >>> Export symbols for xhci hooks usage:
> > >>> 	xhci_ring_free
> > >>> 	- Allow xhci hook to free xhci_ring.
> > >>
> > >> Instead of copying-pasting the name of function, please explain why do
> > >> you need these symbols exported.
> > >>
> > >> The "Why" is actually one of most important questions, because "what is
> > >> this patch doing" we can easily see...
> > >>
> > >>>
> > >>> 	xhci_get_slot_ctx
> > >>> 	- Allow xhci hook to get slot_ctx from the xhci_container_ctx
> > >>> 	  for getting the slot_ctx information to know which slot is
> > >>> 	  offloading and compare the context in remote subsystem memory
> > >>> 	  if needed.
> > >>>
> > >>
> > >>
> > >> Best regards,
> > >> Krzysztof
> > >>
> > > 
> > > Hi Krzysztof
> > > 
> > > xhci_ring_free has been removed from v3..
> > > The reason why I want to export is for managing vendor specific ring.
> > > I want to alloc and free vendor specific ring on specific address.
> > > It's done with xhci hooks.
> > 
> > It's better, but still does not explain why these have to be exported.
> > Please mention where are these hooks going to be. Where are they
> > implemented. I actually expect all of these exports to be used in your
> > patchset.
> 
> All exports _HAVE_ to be used by the patchset.  Otherwise it's an
> invalid submission.
> 
> thanks,
> 
> greg k-h
> 

Yes. I removed unneeded exports on v3.

Best Regards,
Jung Daehwan

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage
  2022-03-25  1:28           ` Jung Daehwan
@ 2022-03-25 11:36             ` Krzysztof Kozlowski
  2022-03-29  2:43               ` Jung Daehwan
  0 siblings, 1 reply; 19+ messages in thread
From: Krzysztof Kozlowski @ 2022-03-25 11:36 UTC (permalink / raw)
  To: Jung Daehwan
  Cc: Mathias Nyman, Greg Kroah-Hartman, open list:USB XHCI DRIVER,
	open list, Howard Yen, Jack Pham, Puma Hsu, J . Avila,
	chihhao . chen, sc.suh, cpgs, cpgsproxy5

On 25/03/2022 02:28, Jung Daehwan wrote:
> On Wed, Mar 23, 2022 at 10:41:23AM +0100, Krzysztof Kozlowski wrote:
>> On 23/03/2022 03:58, Jung Daehwan wrote:
>>> On Mon, Mar 07, 2022 at 10:59:06AM +0100, Krzysztof Kozlowski wrote:
>>>> On 04/03/2022 07:23, Daehwan Jung wrote:
>>>>> Export symbols for xhci hooks usage:
>>>>> 	xhci_ring_free
>>>>> 	- Allow xhci hook to free xhci_ring.
>>>>
>>>> Instead of copying-pasting the name of function, please explain why do
>>>> you need these symbols exported.
>>>>
>>>> The "Why" is actually one of most important questions, because "what is
>>>> this patch doing" we can easily see...
>>>>
>>>>>
>>>>> 	xhci_get_slot_ctx
>>>>> 	- Allow xhci hook to get slot_ctx from the xhci_container_ctx
>>>>> 	  for getting the slot_ctx information to know which slot is
>>>>> 	  offloading and compare the context in remote subsystem memory
>>>>> 	  if needed.
>>>>>
>>>>
>>>>
>>>> Best regards,
>>>> Krzysztof
>>>>
>>>
>>> Hi Krzysztof
>>>
>>> xhci_ring_free has been removed from v3..
>>> The reason why I want to export is for managing vendor specific ring.
>>> I want to alloc and free vendor specific ring on specific address.
>>> It's done with xhci hooks.
>>
>> It's better, but still does not explain why these have to be exported.
>> Please mention where are these hooks going to be. Where are they
>> implemented. I actually expect all of these exports to be used in your
>> patchset.
>>
>> Best regards,
>> Krzysztof
>>
> 
> OK. How about adding call stack like below?
> 
> xhci_free_endpoint_ring -> xhci_vendor_free_transfer_ring(xhck hooks
> ops) -> xhci_ring_free

What I would like to see is high level explanation, why do you need
these functions exported. Such call trace does not answer this, because
you do not need to export functions just to call the. You need to export
them for modules, so this means that some modules (which - need names)
will be using these functions. Three or four sentences are usually
enough to explain it.


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage
  2022-03-25 11:36             ` Krzysztof Kozlowski
@ 2022-03-29  2:43               ` Jung Daehwan
  0 siblings, 0 replies; 19+ messages in thread
From: Jung Daehwan @ 2022-03-29  2:43 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Mathias Nyman, Greg Kroah-Hartman, open list:USB XHCI DRIVER,
	open list, Howard Yen, Jack Pham, Puma Hsu, J . Avila,
	chihhao . chen, sc.suh, cpgs, cpgsproxy5

[-- Attachment #1: Type: text/plain, Size: 2283 bytes --]

On Fri, Mar 25, 2022 at 12:36:20PM +0100, Krzysztof Kozlowski wrote:
> On 25/03/2022 02:28, Jung Daehwan wrote:
> > On Wed, Mar 23, 2022 at 10:41:23AM +0100, Krzysztof Kozlowski wrote:
> >> On 23/03/2022 03:58, Jung Daehwan wrote:
> >>> On Mon, Mar 07, 2022 at 10:59:06AM +0100, Krzysztof Kozlowski wrote:
> >>>> On 04/03/2022 07:23, Daehwan Jung wrote:
> >>>>> Export symbols for xhci hooks usage:
> >>>>> 	xhci_ring_free
> >>>>> 	- Allow xhci hook to free xhci_ring.
> >>>>
> >>>> Instead of copying-pasting the name of function, please explain why do
> >>>> you need these symbols exported.
> >>>>
> >>>> The "Why" is actually one of most important questions, because "what is
> >>>> this patch doing" we can easily see...
> >>>>
> >>>>>
> >>>>> 	xhci_get_slot_ctx
> >>>>> 	- Allow xhci hook to get slot_ctx from the xhci_container_ctx
> >>>>> 	  for getting the slot_ctx information to know which slot is
> >>>>> 	  offloading and compare the context in remote subsystem memory
> >>>>> 	  if needed.
> >>>>>
> >>>>
> >>>>
> >>>> Best regards,
> >>>> Krzysztof
> >>>>
> >>>
> >>> Hi Krzysztof
> >>>
> >>> xhci_ring_free has been removed from v3..
> >>> The reason why I want to export is for managing vendor specific ring.
> >>> I want to alloc and free vendor specific ring on specific address.
> >>> It's done with xhci hooks.
> >>
> >> It's better, but still does not explain why these have to be exported.
> >> Please mention where are these hooks going to be. Where are they
> >> implemented. I actually expect all of these exports to be used in your
> >> patchset.
> >>
> >> Best regards,
> >> Krzysztof
> >>
> > 
> > OK. How about adding call stack like below?
> > 
> > xhci_free_endpoint_ring -> xhci_vendor_free_transfer_ring(xhck hooks
> > ops) -> xhci_ring_free
> 
> What I would like to see is high level explanation, why do you need
> these functions exported. Such call trace does not answer this, because
> you do not need to export functions just to call the. You need to export
> them for modules, so this means that some modules (which - need names)
> will be using these functions. Three or four sentences are usually
> enough to explain it.
> 
> 
> Best regards,
> Krzysztof
> 

I got it. I'm going to modify it on next submission.

Best Regards,
Jung Daehwan

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2022-03-29  2:48 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1646375038-72082-1-git-send-email-dh10.jung@samsung.com>
     [not found] ` <CGME20220304062617epcas2p2084161966aaa66d07f4c25720ec18088@epcas2p2.samsung.com>
2022-03-04  6:23   ` [PATCH v1 1/4] usb: host: export symbols for xhci hooks usage Daehwan Jung
2022-03-07  9:59     ` Krzysztof Kozlowski
2022-03-23  2:58       ` Jung Daehwan
2022-03-23  9:41         ` Krzysztof Kozlowski
2022-03-23 11:43           ` Greg Kroah-Hartman
2022-03-25  2:07             ` Jung Daehwan
2022-03-25  1:28           ` Jung Daehwan
2022-03-25 11:36             ` Krzysztof Kozlowski
2022-03-29  2:43               ` Jung Daehwan
2022-03-08  5:35     ` kernel test robot
     [not found] ` <CGME20220304062617epcas2p4199727918ee662ce09335decba5ad754@epcas2p4.samsung.com>
2022-03-04  6:23   ` [PATCH v1 2/4] usb: host: add xhci hooks for USB offload Daehwan Jung
2022-03-08  6:16     ` kernel test robot
2022-03-08 10:51     ` kernel test robot
     [not found] ` <CGME20220304062617epcas2p1ccc051a6d931d4151a7c9e2bb545bd47@epcas2p1.samsung.com>
2022-03-04  6:23   ` [PATCH v1 3/4] usb: host: add some to xhci overrides " Daehwan Jung
     [not found] ` <CGME20220304062618epcas2p2e3c73b5c4ed0c9bc0ca0c02aa658d3fb@epcas2p2.samsung.com>
2022-03-04  6:23   ` [PATCH v1 4/4] usb: host: add xhci-exynos module Daehwan Jung
2022-03-04  7:37     ` Greg Kroah-Hartman
2022-03-07 10:07     ` Krzysztof Kozlowski
2022-03-07 10:26       ` Jung Daehwan
2022-03-07 10:59         ` Krzysztof Kozlowski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.