From patchwork Tue Apr 26 09:18:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jung Daehwan X-Patchwork-Id: 12826767 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CBB6FC433EF for ; Tue, 26 Apr 2022 09:59:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348131AbiDZKCM (ORCPT ); Tue, 26 Apr 2022 06:02:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44418 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229504AbiDZKBg (ORCPT ); Tue, 26 Apr 2022 06:01:36 -0400 Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D0ACF35DC0 for ; Tue, 26 Apr 2022 02:20:29 -0700 (PDT) Received: from epcas2p3.samsung.com (unknown [182.195.41.55]) by mailout3.samsung.com (KnoxPortal) with ESMTP id 20220426092027epoutp035518106665b755a0bafe2115c2aa89e8~pZ8Nr_7oB0038600386epoutp03C for ; Tue, 26 Apr 2022 09:20:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout3.samsung.com 20220426092027epoutp035518106665b755a0bafe2115c2aa89e8~pZ8Nr_7oB0038600386epoutp03C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1650964827; bh=DI2N6MsptAZ4w52slbF9YkZmkY2W7qAobVVKObxqoNc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=T5k6WjDWjVhDIRnM2LlkJXPXimFlOh1AtkORteZEI6Vhd5tWsiE0fd+Fu1984vHZB ZDhXOrdUUVBgOwOAQTiSl8k/s9lIbz0ZXyVd1ccAKziYvvvbkv+xCq9CNqq3lluOmp oEr6UExexJuCwWbM7obis7OgGtfDxdVAHuV3+Z80= Received: from epsnrtp4.localdomain (unknown [182.195.42.165]) by epcas2p1.samsung.com (KnoxPortal) with ESMTP id 20220426092026epcas2p1aeb4085e7e2547ea348e2d48c2ba60cd~pZ8NKHSbA0597205972epcas2p1a; Tue, 26 Apr 2022 09:20:26 +0000 (GMT) Received: from epsmges2p1.samsung.com (unknown [182.195.36.101]) by epsnrtp4.localdomain (Postfix) with ESMTP id 4KnbvX39q9z4x9Pw; Tue, 26 Apr 2022 09:20:24 +0000 (GMT) Received: from epcas2p4.samsung.com ( [182.195.41.56]) by epsmges2p1.samsung.com (Symantec Messaging Gateway) with SMTP id EE.66.10069.559B7626; Tue, 26 Apr 2022 18:20:21 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p4.samsung.com (KnoxPortal) with ESMTPA id 20220426092021epcas2p4071f2b7621558a015579131990486a3c~pZ8H-nEOp2651026510epcas2p4J; Tue, 26 Apr 2022 09:20:21 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220426092021epsmtrp2ac3c98bf2d962a417468d62c9eb4898a~pZ8H9lh2G1198711987epsmtrp24; Tue, 26 Apr 2022 09:20:21 +0000 (GMT) X-AuditID: b6c32a45-a8fff70000002755-04-6267b9555afb Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id B1.63.08853.559B7626; Tue, 26 Apr 2022 18:20:21 +0900 (KST) Received: from ubuntu.dsn.sec.samsung.com (unknown [10.229.95.128]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220426092021epsmtip2086b1f93ba272f8f41a97a90f2952f97~pZ8HxTjEy2691826918epsmtip2a; Tue, 26 Apr 2022 09:20:21 +0000 (GMT) From: Daehwan Jung To: Mathias Nyman , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org (open list:USB XHCI DRIVER), linux-kernel@vger.kernel.org (open list), Howard Yen , Jack Pham , Puma Hsu , "J . Avila" , Daehwan Jung , sc.suh@samsung.com, Krzysztof Kozlowski Subject: [PATCH v4 1/5] usb: host: export symbols for xhci-exynos to use xhci hooks Date: Tue, 26 Apr 2022 18:18:44 +0900 Message-Id: <1650964728-175347-2-git-send-email-dh10.jung@samsung.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1650964728-175347-1-git-send-email-dh10.jung@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrCKsWRmVeSWpSXmKPExsWy7bCmhW7ozvQkgxeT9S3uLJjGZPHkyCJ2 i+bF69ksrv95z2jR/vwCm8XGtz+YLC7vmsNmsWhZK7NF86YprBYz1ypbdN29wejA7TGroZfN 43JfL5PHgk2lHov3vGTy2D93DbtH35ZVjB6fN8kFsEdl22SkJqakFimk5iXnp2TmpdsqeQfH O8ebmhkY6hpaWpgrKeQl5qbaKrn4BOi6ZeYAnaikUJaYUwoUCkgsLlbSt7Mpyi8tSVXIyC8u sVVKLUjJKTAv0CtOzC0uzUvXy0stsTI0MDAyBSpMyM54eOkZW8EZq4qtndsZGxinGHQxcnJI CJhIPNy0gr2LkYtDSGAHo8T1mX9ZQRJCAp8YJe5clINIfGOU2HDwJxtMx76v/SwQib2MEuc7 upghOn4wSvyaXNfFyMHBJqAl8X0hI0hYRCBOYmnnJSaQemaBJ0wSO97dYgJJCAuEShz41g3W yyKgKnHy5hVGkF5eATeJQ/ezIXbJSdw81wlWwingLvGiZxHYpRICH9kllu/dwg5R5CKxofMp 1HHCEq+Ow8SlJD6/2wsVL5bY9amVCaK5gVGi8cEJZoiEscSsZ+1gi5kFNCXW79IHMSUElCWO 3GIBqWAW4JPoOPyXHSLMK9HRJgTRqCwx/fIEVghbUuLg63PMECUeEttmCEICZBajRO+GogmM crMQxi9gZFzFKJZaUJybnlpsVGAIj63k/NxNjODkp+W6g3Hy2w96hxiZOBgPMUpwMCuJ8E5V TUsS4k1JrKxKLcqPLyrNSS0+xGgKDLmJzFKiyfnA9JtXEm9oYmlgYmZmaG5kamCuJM7rlbIh UUggPbEkNTs1tSC1CKaPiYNTqoHJ3mLV3JBDjMEFn9RKznEsfV0V0Hvv30PmDoUcZdZbx64s lU+9VGFfaVs4qcqmc9WtZyvvGXRM+bjT771/gOqpB65X4/cZVB/R3RLzy3A9t6WCu26exxfJ v363Vi681x5tqFsidK9/Hf8kk1KvE4vSTt/yM5RvOe91zmX55jUcnxZWFN2c80cp5aNJ0M9f /JJOQRJNXaf//BaquRl4mm/q1oUX2qVZT4q0WuzdzrHpd+nLJcZHCgpebwvUtkz+FJdWpXb3 82Zr09L/7EJt6pf9JxycsLxGWLqnMlogYkvYziuTY65n6jstPxa3jPmQkXtR8Wb2thNLVp+b Vy0j93jRFscHXx/eTlcJv2x3pPm0EktxRqKhFnNRcSIA2IBxAgcEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrILMWRmVeSWpSXmKPExsWy7bCSvG7ozvQkgwdPeCzuLJjGZPHkyCJ2 i+bF69ksrv95z2jR/vwCm8XGtz+YLC7vmsNmsWhZK7NF86YprBYz1ypbdN29wejA7TGroZfN 43JfL5PHgk2lHov3vGTy2D93DbtH35ZVjB6fN8kFsEdx2aSk5mSWpRbp2yVwZTy89Iyt4IxV xdbO7YwNjFMMuhg5OSQETCT2fe1n6WLk4hAS2M0ose/gRRaIhKTE0rk32CFsYYn7LUdYIYq+ MUq86f3G1sXIwcEmoCXxfSEjSI2IQJzEist7wHqZBd4wSVzdnQRiCwsES+zffggsziKgKnHy 5hVGkFZeATeJQ/ezIcbLSdw818kMYnMKuEu86FkEtlYIqGTyiutMExj5FjAyrGKUTC0ozk3P LTYsMMxLLdcrTswtLs1L10vOz93ECA5VLc0djNtXfdA7xMjEwXiIUYKDWUmEd6pqWpIQb0pi ZVVqUX58UWlOavEhRmkOFiVx3gtdJ+OFBNITS1KzU1MLUotgskwcnFINTPObvqX6rHwXH7ap eH5DY/CTpREfXS7psMzwzJFY/Vp9rvOpvyxhi7PafVZ4HDij9u2nwgrppRNmiSe+OyqaFHni 5tTMCFUR8+mlU4I3ak6SrOdZq3Fr1+V+Lb/gny9+XxQ90mwc8jRa77WnRf42vke7bqbFysh4 BYZpW0f72F/KcfPf/ff3eq87XlwVd/uy5atv/36/1i3sgej8VS/d797V5j3PnmA6ucB+5QOF 1MhbDIdjS1eultCvPcxta7q2iWMmt+zzy9M9pzE66yu6edxrLp8fIqPJyRsgKbNfeqPqSuW8 ialRTzc4ztYwvVYYsHxT7uoPW3gr1ASaF8Rzf7JZmTHj2rG9ejc1PodMVmIpzkg01GIuKk4E AOfpD8zEAgAA X-CMS-MailID: 20220426092021epcas2p4071f2b7621558a015579131990486a3c X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220426092021epcas2p4071f2b7621558a015579131990486a3c References: <1650964728-175347-1-git-send-email-dh10.jung@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org 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. Vendors could alloc additional event ring. xhci_trb_virt_to_dma - Used to retrieve the DMA address of vendor specific ring. Vendors could get dequeue address of event ring. xhci_segment_free xhci_link_segments - Allow xhci hook to handle vendor specific segment. Vendors could directly free or link segments of vendor specific ring. 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. Vendors could check trb when allocating vendor specific ring. 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 to xhci hook to remove stream mapping. Vendors need to do it when free-ing vendor specific ring if it's stream type. Signed-off-by: Daehwan Jung Signed-off-by: Jack Pham Signed-off-by: Howard Yen Reported-by: kernel test robot --- drivers/usb/host/xhci-hub.c | 2 ++ drivers/usb/host/xhci-mem.c | 19 +++++++++++++------ drivers/usb/host/xhci-ring.c | 1 + drivers/usb/host/xhci.c | 4 +++- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index f65f1ba2b592..841617952ac7 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1812,6 +1812,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. @@ -1956,6 +1957,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 bbb27ee2c6a3..82b9f90c0f27 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,6 +74,7 @@ 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, struct xhci_segment *first) @@ -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. @@ -256,7 +258,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 +271,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) { @@ -316,6 +319,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 +411,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, @@ -518,6 +523,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, @@ -1965,7 +1971,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; @@ -2085,6 +2091,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 f9707997969d..652b37cd9c5e 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) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 25b87e99b4dd..c06e8b21b724 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1468,6 +1468,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 @@ -4324,10 +4325,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) { From patchwork Tue Apr 26 09:18:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jung Daehwan X-Patchwork-Id: 12826768 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 67CC1C433F5 for ; Tue, 26 Apr 2022 09:59:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347383AbiDZKCO (ORCPT ); Tue, 26 Apr 2022 06:02:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43604 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236341AbiDZKBh (ORCPT ); Tue, 26 Apr 2022 06:01:37 -0400 Received: from mailout2.samsung.com (mailout2.samsung.com [203.254.224.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 96EBF18B32 for ; Tue, 26 Apr 2022 02:20:31 -0700 (PDT) Received: from epcas2p4.samsung.com (unknown [182.195.41.56]) by mailout2.samsung.com (KnoxPortal) with ESMTP id 20220426092026epoutp02946b22ed4fadf95c53825c0aabafe69d~pZ8NEyNAm2874828748epoutp02N for ; Tue, 26 Apr 2022 09:20:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.samsung.com 20220426092026epoutp02946b22ed4fadf95c53825c0aabafe69d~pZ8NEyNAm2874828748epoutp02N DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1650964826; bh=QLW15knO9rwiXKhwWsTsUO3ELVF4noCe0tcRzd8KjrA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qgUSVFxKeI+IiNdTSxqgybOvrxlFTL1VBg/8eKxC4p5Oq/LrALY2q1h9DN13WQrDF Z5rvfBFHLVlhnjrO70wlEl5R4cNAxuXm4ovMFqSWEXL2hYotBd8OAkIs0Ephldfqyg j4FpLEyk4d76BIvh0+2IYaTe97IA0Zj+QzuKi42w= Received: from epsnrtp4.localdomain (unknown [182.195.42.165]) by epcas2p3.samsung.com (KnoxPortal) with ESMTP id 20220426092025epcas2p3629818fbc6850f0fa672b96803c17ed7~pZ8MWQZgs1080210802epcas2p3k; Tue, 26 Apr 2022 09:20:25 +0000 (GMT) Received: from epsmges2p2.samsung.com (unknown [182.195.36.97]) by epsnrtp4.localdomain (Postfix) with ESMTP id 4KnbvV55W6z4x9QF; Tue, 26 Apr 2022 09:20:22 +0000 (GMT) Received: from epcas2p3.samsung.com ( [182.195.41.55]) by epsmges2p2.samsung.com (Symantec Messaging Gateway) with SMTP id 2F.30.09764.659B7626; Tue, 26 Apr 2022 18:20:22 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas2p1.samsung.com (KnoxPortal) with ESMTPA id 20220426092021epcas2p1a8d41039d9b3226f4e00f7d4bded833a~pZ8IgrMZi0481304813epcas2p1Y; Tue, 26 Apr 2022 09:20:21 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20220426092021epsmtrp1fe92e7a2fcdb42abc0ef7d430b061758~pZ8If15MU2050020500epsmtrp1t; Tue, 26 Apr 2022 09:20:21 +0000 (GMT) X-AuditID: b6c32a46-f8bff70000002624-e3-6267b956f846 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id 0B.74.08924.559B7626; Tue, 26 Apr 2022 18:20:21 +0900 (KST) Received: from ubuntu.dsn.sec.samsung.com (unknown [10.229.95.128]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220426092021epsmtip2c991d3745adb34afea409cc9e41b5ee3~pZ8IVZ_EN2691826918epsmtip2d; Tue, 26 Apr 2022 09:20:21 +0000 (GMT) From: Daehwan Jung To: Mathias Nyman , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org (open list:USB XHCI DRIVER), linux-kernel@vger.kernel.org (open list), Howard Yen , Jack Pham , Puma Hsu , "J . Avila" , Daehwan Jung , sc.suh@samsung.com, Krzysztof Kozlowski Subject: [PATCH v4 2/5] usb: host: add xhci hooks for xhci-exynos Date: Tue, 26 Apr 2022 18:18:45 +0900 Message-Id: <1650964728-175347-3-git-send-email-dh10.jung@samsung.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1650964728-175347-1-git-send-email-dh10.jung@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrJKsWRmVeSWpSXmKPExsWy7bCmuW7YzvQkgxOL1C3uLJjGZPHkyCJ2 i+bF69ksrv95z2jR/vwCm8XGtz+YLC7vmsNmsWhZK7NF86YprBYz1ypbdN29wejA7TGroZfN 43JfL5PHgk2lHov3vGTy2D93DbtH35ZVjB6fN8kFsEdl22SkJqakFimk5iXnp2TmpdsqeQfH O8ebmhkY6hpaWpgrKeQl5qbaKrn4BOi6ZeYAnaikUJaYUwoUCkgsLlbSt7Mpyi8tSVXIyC8u sVVKLUjJKTAv0CtOzC0uzUvXy0stsTI0MDAyBSpMyM44s2gne0H3IsaKt60v2RoYr7cxdjFy ckgImEg07njGBmILCexglNh7RqyLkQvI/sQo8ezSAVYI5zOjxO8zj+A63rT2skB07GKUWPux AKLoB6PE62kvgDo4ONgEtCS+LwSrFxGIk1jaeYkJpIZZ4AmTxI53t5hAEsICjhLf31wFG8Qi oCpx+fY9ZhCbV8BN4u/6LcwQy+Qkbp7rBLM5BdwlXvQsYgcZJCHwkV1iyes/bBBFLhKLz7VC 2cISr45vYYewpSRe9rdB2cUSuz61MkE0NzBKND44AbXBWGLWs3ZGkKuZBTQl1u/SBzElBJQl jtwCu41ZgE+i4/Bfdogwr0RHmxBEo7LE9MsTWCFsSYmDr89BDfSQaHrxjRESJrMYJXa1fWOa wCg3C2HBAkbGVYxiqQXFuempxUYFRvAoS87P3cQIToNabjsYp7z9oHeIkYmD8RCjBAezkgjv VNW0JCHelMTKqtSi/Pii0pzU4kOMpsDAm8gsJZqcD0zEeSXxhiaWBiZmZobmRqYG5krivF4p GxKFBNITS1KzU1MLUotg+pg4OKUamLw1Pja219dZuNwpmaYm6pr2KevsrK0Kon/5ucV2sLsd PLAyyeranKmXXZNn/uB4mHnumee3jBTHHpMLJnMSBSuXnl59oGZ9l0HIki+/A/OnevcsjCzs 3ui9eRHfVJ71IvmfpC/z/L1R+O9dqAiDcVP7y01Xf997GXuCP1JKlycnoHzTlKSdyxdzPM/7 Zm4qHmQbbqrqdlq5TuQWd+nv3RP33X/r3C90KdT1wFz9kytKFV0u8OkaxrT5n0p7XcE6beF6 HamqtwdKlaIUStt9lO/U3PtTuFeZITjF2mz5NQ9rtpMfGX607Pb+zudvVm5wje8un1l6uWXg rNNcf9K9XRb13vidvCJgll3r5qMLlViKMxINtZiLihMBycb9HQwEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrCLMWRmVeSWpSXmKPExsWy7bCSvG7ozvQkg/YGQ4s7C6YxWTw5sojd onnxejaL63/eM1q0P7/AZrHx7Q8mi8u75rBZLFrWymzRvGkKq8XMtcoWXXdvMDpwe8xq6GXz uNzXy+SxYFOpx+I9L5k89s9dw+7Rt2UVo8fnTXIB7FFcNimpOZllqUX6dglcGWcW7WQv6F7E WPG29SVbA+P1NsYuRk4OCQETiTetvSxdjFwcQgI7GCVutM9jhUhISiyde4MdwhaWuN9yhBWi 6BujxIpNH4G6OTjYBLQkvi8EGyQiECex4vIeFhCbWeANk8TV3UkgtrCAo8T3N1fB4iwCqhKX b99jBrF5Bdwk/q7fwgwxX07i5rlOMJtTwF3iRc8isL1CQDWTV1xnmsDIt4CRYRWjZGpBcW56 brFhgVFearlecWJucWleul5yfu4mRnDAamntYNyz6oPeIUYmDsZDjBIczEoivFNV05KEeFMS K6tSi/Lji0pzUosPMUpzsCiJ817oOhkvJJCeWJKanZpakFoEk2Xi4JRqYNr/bdv5/qzTS/+/ 2J03ef1acePW6zxVdmUTMzZHNbesUuVxYdFr2JD46nXCmpRnDioTVCNcjdbFi/fXTGme8+uJ lu717vlVk8WdUveWuH18/+3Xrvkr5pnMM1K4VPvT/EJ1kPaOBSwfzSwamHeIu/b6m+vzzphg dILVpMr76uJ+ta7Q8rRb+9M09qh3MpbvOXxwrkLX7umP2gMO9+xyfT9VwoFZ7XTjL+bTfQ+4 prqGPats85RILNjzzf1tSeLpH7OW/doa+4kn/KPZe1Hhk+1f8oq+mFo9bI3UXpJqmWly5p7T hi9ZHyzFdmtG/r7GozFf/EV54F7FRfPulNctjuwO3/sxJdCCJZjlaeb1SCWW4oxEQy3mouJE AKnFS3jHAgAA X-CMS-MailID: 20220426092021epcas2p1a8d41039d9b3226f4e00f7d4bded833a X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220426092021epcas2p1a8d41039d9b3226f4e00f7d4bded833a References: <1650964728-175347-1-git-send-email-dh10.jung@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org 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. @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 Signed-off-by: J. Avila Signed-off-by: Puma Hsu Signed-off-by: Howard Yen --- drivers/usb/host/xhci-hub.c | 5 ++ drivers/usb/host/xhci-mem.c | 131 +++++++++++++++++++++++++++++++---- drivers/usb/host/xhci-plat.c | 44 +++++++++++- drivers/usb/host/xhci-plat.h | 8 +++ drivers/usb/host/xhci.c | 80 ++++++++++++++++++++- drivers/usb/host/xhci.h | 46 ++++++++++++ 6 files changed, 296 insertions(+), 18 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 841617952ac7..e07c9c132061 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 82b9f90c0f27..5ee0ffb676d3 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -365,6 +365,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. * @@ -417,7 +465,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; } @@ -475,6 +527,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; @@ -488,7 +541,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; @@ -499,9 +557,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); } @@ -894,7 +959,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); @@ -1492,8 +1557,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; @@ -1837,6 +1910,24 @@ void xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) erst->entries = NULL; } +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; @@ -1888,9 +1979,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); @@ -2427,15 +2522,21 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * xHCI section 5.4.6 - Device Context 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 649ffd861b44..a5881ff945a6 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -173,6 +173,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 device *dev) +{ + 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, dev); + 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; @@ -185,7 +220,6 @@ static int xhci_plat_probe(struct platform_device *pdev) int irq; struct xhci_plat_priv *priv = NULL; - if (usb_disabled()) return -ENODEV; @@ -321,6 +355,10 @@ static int xhci_plat_probe(struct platform_device *pdev) goto put_usb3_hcd; } + ret = xhci_vendor_init(xhci, &pdev->dev); + 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; if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) @@ -393,8 +431,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 1fb149d1fbce..8c204f3234d8 100644 --- a/drivers/usb/host/xhci-plat.h +++ b/drivers/usb/host/xhci-plat.h @@ -17,8 +17,16 @@ struct xhci_plat_priv { int (*init_quirk)(struct usb_hcd *); int (*suspend_quirk)(struct usb_hcd *); int (*resume_quirk)(struct usb_hcd *); + void *vendor_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.c b/drivers/usb/host/xhci.c index c06e8b21b724..5ccf1bbe8732 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2986,6 +2986,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; } @@ -3129,7 +3137,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; } } @@ -3290,6 +3302,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 */ @@ -3321,6 +3340,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); @@ -3866,6 +3890,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. @@ -4111,6 +4142,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); @@ -4241,6 +4280,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. @@ -4393,6 +4439,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); @@ -4420,6 +4474,21 @@ 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; +} + #ifdef CONFIG_PM /* BESL to HIRD Encoding array for USB2 LPM */ @@ -5144,6 +5213,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 473a33ce299e..3a414a2f41f0 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1929,6 +1929,9 @@ struct xhci_hcd { struct list_head regset_list; void *dbc; + + struct xhci_vendor_ops *vendor_ops; + /* platform-specific data -- must come last */ unsigned long priv[] __aligned(sizeof(s64)); }; @@ -2207,6 +2210,49 @@ 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 + * @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, struct device *dev); + 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); + + 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); + 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); +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 From patchwork Tue Apr 26 09:18:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jung Daehwan X-Patchwork-Id: 12826766 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CB2E0C433FE for ; Tue, 26 Apr 2022 09:59:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348051AbiDZKCL (ORCPT ); Tue, 26 Apr 2022 06:02:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58516 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348131AbiDZKBg (ORCPT ); Tue, 26 Apr 2022 06:01:36 -0400 Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D097C35ABF for ; Tue, 26 Apr 2022 02:20:28 -0700 (PDT) Received: from epcas2p2.samsung.com (unknown [182.195.41.54]) by mailout3.samsung.com (KnoxPortal) with ESMTP id 20220426092027epoutp03a874a7b37a7f7cdbcb4fdfa64750fbaa~pZ8NXPGhY0038800388epoutp03s for ; Tue, 26 Apr 2022 09:20:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout3.samsung.com 20220426092027epoutp03a874a7b37a7f7cdbcb4fdfa64750fbaa~pZ8NXPGhY0038800388epoutp03s DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1650964827; bh=E9R23DAe1jJ/y4QYxJ8o32xCpnMFRt1+5PhLzGs6fDE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mpYG+yn1iGM839G8R+WDip2gPg459hhhorKwV+yjOZjGBrJhW8ZT6TOAN8JIW2xo5 gtikY9c1VVccbY+A5VdWSI8jY6vfHXL4qxF23WpBGP63ObDWbXYiMqrvgnsUfWBlHZ YaRJkNzz9o5a58vRQZhvta5zutGjezPz1oIF9rrs= Received: from epsnrtp2.localdomain (unknown [182.195.42.163]) by epcas2p4.samsung.com (KnoxPortal) with ESMTP id 20220426092026epcas2p4ceb674ff1a822d94998c6027eb6a1452~pZ8M0t7LD2651026510epcas2p4U; Tue, 26 Apr 2022 09:20:26 +0000 (GMT) Received: from epsmges2p2.samsung.com (unknown [182.195.36.102]) by epsnrtp2.localdomain (Postfix) with ESMTP id 4KnbvV5FtFz4x9Pw; Tue, 26 Apr 2022 09:20:22 +0000 (GMT) Received: from epcas2p1.samsung.com ( [182.195.41.53]) by epsmges2p2.samsung.com (Symantec Messaging Gateway) with SMTP id 4F.30.09764.659B7626; Tue, 26 Apr 2022 18:20:22 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p2.samsung.com (KnoxPortal) with ESMTPA id 20220426092022epcas2p2da47c0c20feba6c96037e125289475f9~pZ8I3rmK42824028240epcas2p26; Tue, 26 Apr 2022 09:20:22 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220426092022epsmtrp26bfca5b948cda1b1ea502c6b75730361~pZ8I2zjo01198711987epsmtrp2B; Tue, 26 Apr 2022 09:20:22 +0000 (GMT) X-AuditID: b6c32a46-f8bff70000002624-e5-6267b956dce8 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id 36.63.08853.659B7626; Tue, 26 Apr 2022 18:20:22 +0900 (KST) Received: from ubuntu.dsn.sec.samsung.com (unknown [10.229.95.128]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220426092022epsmtip267f5b1767f4ea10aac4e0f5c6baf0836~pZ8Iu8jeM2696726967epsmtip2_; Tue, 26 Apr 2022 09:20:22 +0000 (GMT) From: Daehwan Jung To: Mathias Nyman , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org (open list:USB XHCI DRIVER), linux-kernel@vger.kernel.org (open list), Howard Yen , Jack Pham , Puma Hsu , "J . Avila" , Daehwan Jung , sc.suh@samsung.com, Krzysztof Kozlowski Subject: [PATCH v4 3/5] usb: host: xhci-plat: support override of hc driver Date: Tue, 26 Apr 2022 18:18:46 +0900 Message-Id: <1650964728-175347-4-git-send-email-dh10.jung@samsung.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1650964728-175347-1-git-send-email-dh10.jung@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrOKsWRmVeSWpSXmKPExsWy7bCmqW7YzvQkg3vbtCzuLJjGZPHkyCJ2 i+bF69ksrv95z2jR/vwCm8XGtz+YLC7vmsNmsWhZK7NF86YprBYz1ypbdN29wejA7TGroZfN 43JfL5PHgk2lHov3vGTy2D93DbtH35ZVjB6fN8kFsEdl22SkJqakFimk5iXnp2TmpdsqeQfH O8ebmhkY6hpaWpgrKeQl5qbaKrn4BOi6ZeYAnaikUJaYUwoUCkgsLlbSt7Mpyi8tSVXIyC8u sVVKLUjJKTAv0CtOzC0uzUvXy0stsTI0MDAyBSpMyM5Y33+YseA6d8W5p91sDYxzuboYOTkk BEwkzm/5ydjFyMUhJLCDUaKp8xcrSEJI4BOjxPa9thCJb4wSH6fuZobpeNCxHKpjL6NEV+dx JgjnB6PEjOcHgdo5ONgEtCS+L2QEaRARiJNY2nkJrIZZ4AmTxI53t5hAEsIC3hL963vA6lkE VCXWTvIECfMKuElMOXacBWKZnMTNc51gizkF3CVe9CxiB5kjIfCRXaLz5hR2iCIXie0PXjFC 2MISr45vgYpLSXx+t5cNwi6W2PWplQmiuYFRovHBCah3jCVmPWtnBDmCWUBTYv0ufRBTQkBZ 4sgtsBuYBfgkOg7/ZYcI80p0tAlBNCpLTL88gRXClpQ4+Poc1EAPiVnv9zJDgmQWo8S/389Y JzDKzUJYsICRcRWjWGpBcW56arFRgRE8wpLzczcxglOgltsOxilvP+gdYmTiYDzEKMHBrCTC O1U1LUmINyWxsiq1KD++qDQntfgQoykw7CYyS4km5wOTcF5JvKGJpYGJmZmhuZGpgbmSOK9X yoZEIYH0xJLU7NTUgtQimD4mDk6pBqairizWri8nOXc9u+kYG5gYtI5j7uaSgM8vp22d89ay eVXLW87y3PPlYc9u86ks/1tczzQvXVrK//c3d0Zfd81bipvEjC9+vpm++8FRrR86R0wnc7aq MUnwn8/5/StoXTa78rw35m4Fky6IG7kalV/9KrnT/cRUjSXnQ0KepvwUN9W6VNLFn7TjbWWh hVD+5WM+ye1tTDsd16oeMXh1aan7JY9nU5/85+oMLBJ4bXrL/GJ/W5X6jNYTml6T1hwN3GLC c6r8+fOtT8Jv/+SKCBNa6scfa876KCiRoSujqmRZzMry9bf62f02dP4SrN/1n3E9p+rvIhvF LWU3rEoFuF7mqbfbZzNVPPB+eEPsjRJLcUaioRZzUXEiAGmoSrEKBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrILMWRmVeSWpSXmKPExsWy7bCSvG7YzvQkg7v/eCzuLJjGZPHkyCJ2 i+bF69ksrv95z2jR/vwCm8XGtz+YLC7vmsNmsWhZK7NF86YprBYz1ypbdN29wejA7TGroZfN 43JfL5PHgk2lHov3vGTy2D93DbtH35ZVjB6fN8kFsEdx2aSk5mSWpRbp2yVwZazvP8xYcJ27 4tzTbrYGxrlcXYycHBICJhIPOpYzdjFycQgJ7GaUaHt9nxEiISmxdO4NdghbWOJ+yxFWiKJv jBLrZ/9l7mLk4GAT0JL4vhCsXkQgTmLF5T0sIDazwBsmiau7k0BsYQFvif71Pawg5SwCqhJr J3mChHkF3CSmHDvOAjFeTuLmuU5mEJtTwF3iRc8isLVCQDWTV1xnmsDIt4CRYRWjZGpBcW56 brFhgWFearlecWJucWleul5yfu4mRnCoamnuYNy+6oPeIUYmDsZDjBIczEoivFNV05KEeFMS K6tSi/Lji0pzUosPMUpzsCiJ817oOhkvJJCeWJKanZpakFoEk2Xi4JRqYEqW4A6cvK/ipbZ4 /9TuvKMB8UveON8WuysSaL9Bd5VL/nFefus/vd0PvXe31K9Xadve7cfqLPI76uGFFd2OCbMX rd0/996TC3uF3Zqb9jBvK3Surd7W+nzTDecbbdUnvxy4osOo5nUyYv7rnXbRaratfC28ExIP 25jf42it05lYEfmKq++N2dLz0gp1ByyY+Iu6YyS/bzyg4XG4XsRA4O7cCbujimsucc5N6c4T 4OncnbV9pUaFGFvjUitJpz2ma3qnKesmyocYXdPMe975Pastnr9f79k7nn/+lZ98fjA7u+eu Xrug5qfAAmfeV+1Hjrxt/7f3bu/S2i/yD21WfElYJKqx0oSzeHJOtu90JZbijERDLeai4kQA FTyvYcQCAAA= X-CMS-MailID: 20220426092022epcas2p2da47c0c20feba6c96037e125289475f9 X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220426092022epcas2p2da47c0c20feba6c96037e125289475f9 References: <1650964728-175347-1-git-send-email-dh10.jung@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org It helps xhci-plat driver increase usability. Vendors could use functions in xhci-plat mostly and use some overrides to do what they wants without modifying xhci-plat driver. Signed-off-by: Daehwan Jung --- drivers/usb/host/xhci-plat.c | 6 ++++++ drivers/usb/host/xhci-plat.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index a5881ff945a6..6efa3169bf69 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -173,6 +173,12 @@ static const struct of_device_id usb_xhci_of_match[] = { MODULE_DEVICE_TABLE(of, usb_xhci_of_match); #endif +void xhci_plat_override_driver(const struct xhci_driver_overrides *xhci_vendor_overrides) +{ + xhci_init_driver(&xhci_plat_hc_driver, xhci_vendor_overrides); +} +EXPORT_SYMBOL(xhci_plat_override_driver); + static struct xhci_plat_priv_overwrite xhci_plat_vendor_overwrite; int xhci_plat_register_vendor_ops(struct xhci_vendor_ops *vendor_ops) diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h index 8c204f3234d8..455e0018d5e6 100644 --- a/drivers/usb/host/xhci-plat.h +++ b/drivers/usb/host/xhci-plat.h @@ -28,5 +28,6 @@ struct xhci_plat_priv_overwrite { }; int xhci_plat_register_vendor_ops(struct xhci_vendor_ops *vendor_ops); +void xhci_plat_override_driver(const struct xhci_driver_overrides *xhci_vendor_overrides); #endif /* _XHCI_PLAT_H */ From patchwork Tue Apr 26 09:18:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jung Daehwan X-Patchwork-Id: 12826765 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 421BFC433EF for ; Tue, 26 Apr 2022 09:58:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345186AbiDZKBz (ORCPT ); Tue, 26 Apr 2022 06:01:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348171AbiDZKBe (ORCPT ); Tue, 26 Apr 2022 06:01:34 -0400 Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 36F8733E91 for ; Tue, 26 Apr 2022 02:20:28 -0700 (PDT) Received: from epcas2p3.samsung.com (unknown [182.195.41.55]) by mailout3.samsung.com (KnoxPortal) with ESMTP id 20220426092025epoutp039c814c7463fe51918dd88be9f22d6400~pZ8MG1vun3263332633epoutp03G for ; Tue, 26 Apr 2022 09:20:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout3.samsung.com 20220426092025epoutp039c814c7463fe51918dd88be9f22d6400~pZ8MG1vun3263332633epoutp03G DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1650964825; bh=gtJAxLOQgrMmX0jWzFakONkF7P6sHoAQWH61J9RzsI8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bgu5Bgf4OyBF4N0aJBlcQfpYZiB0YEXsu9hVZwunyIvZc0i+E3Zx/r1RqK5VmoMNa jeVIqiLrRGJftWceNMStCc1Yk6zkTsl8eizQe2f2U/KVvvtpcfKf/u3egblj0jM8Ak HLtsUM+BttcvHf/i2QCSjd1vFpCuDthllX8Qx5mU= Received: from epsnrtp2.localdomain (unknown [182.195.42.163]) by epcas2p3.samsung.com (KnoxPortal) with ESMTP id 20220426092025epcas2p3d14f3e24838f8a8d88c8bf0acfe656df~pZ8Lg1Q3S0586405864epcas2p3D; Tue, 26 Apr 2022 09:20:25 +0000 (GMT) Received: from epsmges2p3.samsung.com (unknown [182.195.36.89]) by epsnrtp2.localdomain (Postfix) with ESMTP id 4KnbvW100Sz4x9Q1; Tue, 26 Apr 2022 09:20:23 +0000 (GMT) Received: from epcas2p2.samsung.com ( [182.195.41.54]) by epsmges2p3.samsung.com (Symantec Messaging Gateway) with SMTP id B7.27.10028.659B7626; Tue, 26 Apr 2022 18:20:23 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p2.samsung.com (KnoxPortal) with ESMTPA id 20220426092022epcas2p2c016c83b21e41c7bcd4bdfbb95e464c0~pZ8JPwIwa1542715427epcas2p2g; Tue, 26 Apr 2022 09:20:22 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220426092022epsmtrp2b8129b54ca939ed0c966fdb4b2b8809f~pZ8JOcLlR1198711987epsmtrp2E; Tue, 26 Apr 2022 09:20:22 +0000 (GMT) X-AuditID: b6c32a47-589ff7000000272c-61-6267b956c9f2 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id 3A.63.08853.659B7626; Tue, 26 Apr 2022 18:20:22 +0900 (KST) Received: from ubuntu.dsn.sec.samsung.com (unknown [10.229.95.128]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220426092022epsmtip2bc7ea80debbb111994c4354b8e3a6851~pZ8JFUHWS2696726967epsmtip2A; Tue, 26 Apr 2022 09:20:22 +0000 (GMT) From: Daehwan Jung To: Mathias Nyman , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org (open list:USB XHCI DRIVER), linux-kernel@vger.kernel.org (open list), Howard Yen , Jack Pham , Puma Hsu , "J . Avila" , Daehwan Jung , sc.suh@samsung.com, Krzysztof Kozlowski Subject: [PATCH v4 4/5] usb: host: add some to xhci overrides for xhci-exynos Date: Tue, 26 Apr 2022 18:18:47 +0900 Message-Id: <1650964728-175347-5-git-send-email-dh10.jung@samsung.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1650964728-175347-1-git-send-email-dh10.jung@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrBKsWRmVeSWpSXmKPExsWy7bCmmW74zvQkg4O7mCzuLJjGZPHkyCJ2 i+bF69ksrv95z2jR/vwCm8XGtz+YLC7vmsNmsWhZK7NF86YprBYz1ypbdN29wejA7TGroZfN 43JfL5PHgk2lHov3vGTy2D93DbtH35ZVjB6fN8kFsEdl22SkJqakFimk5iXnp2TmpdsqeQfH O8ebmhkY6hpaWpgrKeQl5qbaKrn4BOi6ZeYAnaikUJaYUwoUCkgsLlbSt7Mpyi8tSVXIyC8u sVVKLUjJKTAv0CtOzC0uzUvXy0stsTI0MDAyBSpMyM54/qKVveCuYMXxObtYGxj/83UxcnJI CJhI7Dt4hbmLkYtDSGAHo8Tlgx8YIZxPjBLzH/6Hcr4xSvxf1coO03L3xFsWiMReRonZn16y Qzg/GCWOLjwN1MLBwSagJfF9ISNIg4hAnMTSzktMIDXMAk+YJHa8u8UEkhAW8Jf42DeLFaSe RUBV4ttKW5Awr4CbxIwZj9gglslJ3DzXyQxicwq4S7zoWQS2S0LgK7vEtv9zoC5ykWh6uJ4J whaWeHV8C1RcSuLzu71Qg4oldn1qZYJobmCUaHxwghkiYSwx61k72NHMApoS63fpg5gSAsoS R26xgFQwC/BJdBz+yw4R5pXoaBOCaFSWmH55AiuELSlx8PU5qIEeEge/T4IG3CxGifYJF1gn MMrNQliwgJFxFaNYakFxbnpqsVGBMTzGkvNzNzGCk6CW+w7GGW8/6B1iZOJgPMQowcGsJMI7 VTUtSYg3JbGyKrUoP76oNCe1+BCjKTDsJjJLiSbnA9NwXkm8oYmlgYmZmaG5kamBuZI4r1fK hkQhgfTEktTs1NSC1CKYPiYOTqkGpq1e5rNvua6QOlt/6fLUd4H3Z3/wa1BK8TXO+f1F9EV5 8KI5kx1fr027u2zy4Q8PP+q+3rH007ZyPs2wwrNdFmmy7I9Yz3l+bFtRnnsjU+mAR8HyIxpM ynJZUtYryvutNZkXbGC/InJfNcNXckLnjZVrGxfKiIdkrZ8Uyn1RQVir//GBzN/Za0qmXT50 7+gs3xlx2x5Uf9n3JETJOD2XMcLkz95aI3lWf5E/ogHcFsf+8GaUfXMtevxxZ+hZhfpPLIzn 761Sj5DtmWfloXowpjDl8Q9OSQGeefcfJx69vs9mb82K3zu/rZTZ8Sfo5qJ3fVtOWCyN2rXc 97KxptKTJo/lfyeKulz4efQp68L5b/cosRRnJBpqMRcVJwIA8rkpfAsEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrALMWRmVeSWpSXmKPExsWy7bCSvG7YzvQkg4nnlS3uLJjGZPHkyCJ2 i+bF69ksrv95z2jR/vwCm8XGtz+YLC7vmsNmsWhZK7NF86YprBYz1ypbdN29wejA7TGroZfN 43JfL5PHgk2lHov3vGTy2D93DbtH35ZVjB6fN8kFsEdx2aSk5mSWpRbp2yVwZTx/0cpecFew 4vicXawNjP/5uhg5OSQETCTunnjLAmILCexmlJj+pAAiLimxdO4NdghbWOJ+yxHWLkYuoJpv jBIvv58BSnBwsAloSXxfyAhSIyIQJ7Hi8h6wOcwCb5gkru5OArGFBXwl/pzazApSziKgKvFt pS1ImFfATWLGjEdsEOPlJG6e62QGsTkF3CVe9CxihzjHTWLyiutMExj5FjAyrGKUTC0ozk3P LTYsMMxLLdcrTswtLs1L10vOz93ECA5ULc0djNtXfdA7xMjEwXiIUYKDWUmEd6pqWpIQb0pi ZVVqUX58UWlOavEhRmkOFiVx3gtdJ+OFBNITS1KzU1MLUotgskwcnFINTFHv25MMz6+4M11f Iv47U3f2KblPwo3uL+d29RlZ2ib0nznVtHC7+k/e8G0pHy6bHuaqUBa2MHjGeahCzk2UO/bS qwIt/6PscpNKul8yKZ/cFyx97tD8bZwxhu0rlyx/qPKJ9yWbzjX5x8fLftt8Vb+ZJhj0TG3v Sa6TRvxMjw5P37J1JuOCeu7eu1+L/9bpTPnTsvjtD79NlzhfTV8scOrc4s2bLfYxyxz68Mwk 6K//pbmT2w+65AsVJhqv6Zrd1cNhkL4s74tixFmui1YvT3080v7liMOPl9lCoaxusfYCge+Z V6xtsEm6mBW0Osdk15uyOxabAs7rZWVuEM8OW+nfPSuZ5ewZv+DfZzfMKlZiKc5INNRiLipO BADwruL+wwIAAA== X-CMS-MailID: 20220426092022epcas2p2c016c83b21e41c7bcd4bdfbb95e464c0 X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220426092022epcas2p2c016c83b21e41c7bcd4bdfbb95e464c0 References: <1650964728-175347-1-git-send-email-dh10.jung@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org 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 --- 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 5ccf1bbe8732..8b3df1302650 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -5555,6 +5555,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 3a414a2f41f0..5bc621e77762 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1947,6 +1947,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 @@ -2103,6 +2106,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); From patchwork Tue Apr 26 09:18:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jung Daehwan X-Patchwork-Id: 12826769 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 47EB3C4332F for ; Tue, 26 Apr 2022 09:59:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348223AbiDZKCQ (ORCPT ); Tue, 26 Apr 2022 06:02:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59076 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347582AbiDZKBi (ORCPT ); Tue, 26 Apr 2022 06:01:38 -0400 Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AB67835DD1 for ; Tue, 26 Apr 2022 02:20:31 -0700 (PDT) Received: from epcas2p1.samsung.com (unknown [182.195.41.53]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20220426092028epoutp0102d5f771beed74fa96d606213d31aedd~pZ8OjogN70651906519epoutp01z for ; Tue, 26 Apr 2022 09:20:28 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20220426092028epoutp0102d5f771beed74fa96d606213d31aedd~pZ8OjogN70651906519epoutp01z DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1650964828; bh=ZNVwTkI0jqgxKhBqbwHfzrqudkVRk2e7rBsoOsg0dHQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=az7yKLxrCmhnoc6BtuBQdamdL/XT2pYwKV8QUkAd/RuGRUEJRW1nkpbMRA1d5yMyI uFvzCUio9FlB00LjqHhm9xUhPIOxiE8Yn3w0dO6R4NfGbHgNEhEiDFJmdjzCN+HlU6 SVU/pbuypBOlqcwf4ybZVAY3TYJRgeR6B49bpzH4= Received: from epsnrtp3.localdomain (unknown [182.195.42.164]) by epcas2p2.samsung.com (KnoxPortal) with ESMTP id 20220426092027epcas2p220a87b91f4eab95417fb4ab5f4b7b021~pZ8OBYLIV2824728247epcas2p2I; Tue, 26 Apr 2022 09:20:27 +0000 (GMT) Received: from epsmges2p1.samsung.com (unknown [182.195.36.89]) by epsnrtp3.localdomain (Postfix) with ESMTP id 4KnbvX39t8z4x9Q7; Tue, 26 Apr 2022 09:20:24 +0000 (GMT) Received: from epcas2p3.samsung.com ( [182.195.41.55]) by epsmges2p1.samsung.com (Symantec Messaging Gateway) with SMTP id C3.76.10069.859B7626; Tue, 26 Apr 2022 18:20:24 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas2p3.samsung.com (KnoxPortal) with ESMTPA id 20220426092023epcas2p32946c087135ca4b7e63b03915060c55d~pZ8JpsKUv0586405864epcas2p3C; Tue, 26 Apr 2022 09:20:23 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20220426092023epsmtrp1e9a83ef21a393a779146bfef9765806d~pZ8Joxfec2050020500epsmtrp14; Tue, 26 Apr 2022 09:20:23 +0000 (GMT) X-AuditID: b6c32a45-a8fff70000002755-0a-6267b958c4d5 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id CB.63.08853.659B7626; Tue, 26 Apr 2022 18:20:22 +0900 (KST) Received: from ubuntu.dsn.sec.samsung.com (unknown [10.229.95.128]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220426092022epsmtip21e6f7119d1113df7baf9b13033c35b73~pZ8JcPZsy2696726967epsmtip2C; Tue, 26 Apr 2022 09:20:22 +0000 (GMT) From: Daehwan Jung To: Mathias Nyman , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org (open list:USB XHCI DRIVER), linux-kernel@vger.kernel.org (open list), Howard Yen , Jack Pham , Puma Hsu , "J . Avila" , Daehwan Jung , sc.suh@samsung.com, Krzysztof Kozlowski Subject: [PATCH v4 5/5] usb: host: add xhci-exynos driver Date: Tue, 26 Apr 2022 18:18:48 +0900 Message-Id: <1650964728-175347-6-git-send-email-dh10.jung@samsung.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1650964728-175347-1-git-send-email-dh10.jung@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrBKsWRmVeSWpSXmKPExsWy7bCmuW7EzvQkgy+HxC3uLJjGZPHkyCJ2 i+bF69ksrv95z2jR/vwCm8XGtz+YLC7vmsNmsWhZK7NF86YprBYz1ypbdN29wejA7TGroZfN 43JfL5PHgk2lHov3vGTy2D93DbtH35ZVjB6fN8kFsEdl22SkJqakFimk5iXnp2TmpdsqeQfH O8ebmhkY6hpaWpgrKeQl5qbaKrn4BOi6ZeYAnaikUJaYUwoUCkgsLlbSt7Mpyi8tSVXIyC8u sVVKLUjJKTAv0CtOzC0uzUvXy0stsTI0MDAyBSpMyM7Yd+gDS8GBOYwV516dYGtg/NjE2MXI ySEhYCJx8dwDIJuLQ0hgB6PEyk+vWSGcT4wSz67vZIdwvjFKrDjXyQrTcu3jBBYQW0hgL6PE k2PyEEU/GCX+fX3F3MXIwcEmoCXxfSHYChGBOImlnZeYQGqYBZ4wSex4d4sJJCEsYCnRvnMD K0g9i4CqxI33GSBhXgE3idct25kgdslJ3DzXyQxicwq4S7zoWcQOEf/JLnH5US6E7SLR1niW GcIWlnh1fAtUjZTEy/42KLtYYtenVrAbJAQaGCUaH5yAajCWmPWsnRHkBmYBTYn1u/RBTAkB ZYkjt8BeZBbgk+g4/JcdIswr0dEmBNGoLDH98gRoiEhKHHx9Dmqgh8S3pxvZICEyi1GifcJD 5gmMcrMQFixgZFzFKJZaUJybnlpsVGAIj7Hk/NxNjOAkqOW6g3Hy2w96hxiZOBgPMUpwMCuJ 8E5VTUsS4k1JrKxKLcqPLyrNSS0+xGgKDLqJzFKiyfnANJxXEm9oYmlgYmZmaG5kamCuJM7r lbIhUUggPbEkNTs1tSC1CKaPiYNTqoHpgmtrs1R/s/JBpd0zrmR2/W5bLX7wiX2sdUrpvqQT R0zn5723m5my5/u8E3mbYnrk5/QGyPwo+uGi/YmhyHMpQ/yFxqDneQ8bg5JffFFbse3gYVZ3 n2eyD3Z8qD5665CR6aWlCqereqr/c3+ZLtpZayk2bUaU1LmAeJvg6I/vp2yzDgqtmtm5fdPd 9TsYjlRvyHjYpvXi9AyXXT98mu5a+ftorVkwlW1ng8vvP7te13+/xWzz7Vev3oeMDXVX+cRY Pk88uzX4k3jbjGsVO/bcsLJ6E/BLw93m0l6e6TGtP49eOzdn9s3QUIH5i2bnJV7U3vb0SXeD ZfIsvdWXyhlvLIvamJxjsqVyQvZ/W41fx5VYijMSDbWYi4oTAfFDTu4LBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrMLMWRmVeSWpSXmKPExsWy7bCSvG7YzvQkgxMvbSzuLJjGZPHkyCJ2 i+bF69ksrv95z2jR/vwCm8XGtz+YLC7vmsNmsWhZK7NF86YprBYz1ypbdN29wejA7TGroZfN 43JfL5PHgk2lHov3vGTy2D93DbtH35ZVjB6fN8kFsEdx2aSk5mSWpRbp2yVwZew79IGl4MAc xopzr06wNTB+bGLsYuTkkBAwkbj2cQJLFyMXh5DAbkaJef+3sEEkJCWWzr3BDmELS9xvOcIK UfSNUeLxhmlMXYwcHGwCWhLfF4INEhGIk1hxeQ8LiM0s8IZJ4uruJBBbWMBSon3nBlaQchYB VYkb7zNAwrwCbhKvW7YzQYyXk7h5rpMZxOYUcJd40bMIbK0QUM3kFdeZJjDyLWBkWMUomVpQ nJueW2xYYJiXWq5XnJhbXJqXrpecn7uJERyuWpo7GLev+qB3iJGJg/EQowQHs5II71TVtCQh 3pTEyqrUovz4otKc1OJDjNIcLErivBe6TsYLCaQnlqRmp6YWpBbBZJk4OKUamMoTuZ6Vclk/ PZ6xxEdKWOHpllXLjnyW3BAyLfjktpMBRfNSHukUXli9t+XoTIaZBUacTz4e6RbsPX5MVStS 89Bh3snrO3+GbuSYfOP37kXZqzjMSjISFrAcrwzrFl8Q+mpjws0ZpxZ4qU37lXl77c83ejsk llitNZnnF/tgWgXfP/nXrXV79q6VLa8zsdx2Pj7g/BSNjdYznArLrHf+c26aejXdbOs9uykJ Kw/OD4yNNNPsUZiocV6rL/8/e+e5KeuO5Gk+Dt83r6NP/18Nz7zVfzyZuN4Z7dE8vdNjyYod N7OV/Q9vLnpqO1tS10c968qpfdoyFY0bTefzaq4UCj4fvfrnFW6XW3WnbpzS3WanxFKckWio xVxUnAgAnNy4MsYCAAA= X-CMS-MailID: 20220426092023epcas2p32946c087135ca4b7e63b03915060c55d X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220426092023epcas2p32946c087135ca4b7e63b03915060c55d References: <1650964728-175347-1-git-send-email-dh10.jung@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This driver is for Samsung Exynos xhci host conroller. It uses xhci-plat driver mainly and extends some functions by xhci hooks and overrides. It supports USB Audio offload with Co-processor. It only cares DCBAA, Device Context, Transfer Ring, Event Ring, and ERST. They are allocated on specific address with xhci hooks. Co-processor could use them directly without xhci driver after then. Signed-off-by: Daehwan Jung Reported-by: kernel test robot --- drivers/usb/host/Kconfig | 8 + drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-exynos.c | 567 +++++++++++++++++++++++++++++++++ drivers/usb/host/xhci-exynos.h | 50 +++ 4 files changed, 626 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/Kconfig b/drivers/usb/host/Kconfig index 682b3d2da623..ccafcd9b4212 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -104,6 +104,14 @@ config USB_XHCI_TEGRA Say 'Y' to enable the support for the xHCI host controller found in NVIDIA Tegra124 and later SoCs. +config USB_XHCI_EXYNOS + tristate "xHCI support for Samsung Exynos SoC Series" + depends on USB_XHCI_PLATFORM + depends on ARCH_EXYNOS || COMPILE_TEST + help + Say 'Y' to enable the support for the xHCI host controller + found in Samsung Exynos SoCs. + endif # USB_XHCI_HCD config USB_EHCI_BRCMSTB diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 2948983618fb..300f22b6eb1b 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -86,3 +86,4 @@ obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o obj-$(CONFIG_USB_FOTG210_HCD) += fotg210-hcd.o obj-$(CONFIG_USB_MAX3421_HCD) += max3421-hcd.o obj-$(CONFIG_USB_XEN_HCD) += xen-hcd.o +obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos.o diff --git a/drivers/usb/host/xhci-exynos.c b/drivers/usb/host/xhci-exynos.c new file mode 100644 index 000000000000..4f22f620d7e0 --- /dev/null +++ b/drivers/usb/host/xhci-exynos.c @@ -0,0 +1,567 @@ +// 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 + * + * A lot of code borrowed from the Linux xHCI driver. + */ +#include +#include + +#include "xhci.h" +#include "xhci-plat.h" +#include "xhci-exynos.h" + +static const struct dev_pm_ops xhci_exynos_pm_ops; + +static struct xhci_vendor_ops ops; +static void xhci_exynos_parse_endpoint(struct xhci_hcd *xhci, struct usb_device *udev, + struct usb_endpoint_descriptor *desc, struct xhci_container_ctx *ctx); +static void xhci_exynos_free_event_ring(struct xhci_hcd *xhci); +static 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 xhci_exynos_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring); +static int xhci_exynos_alloc_event_ring(struct xhci_hcd *xhci, gfp_t flags); + +static int xhci_exynos_register_vendor_ops(struct xhci_vendor_ops *vendor_ops) +{ + return xhci_plat_register_vendor_ops(&ops); +} + +static void xhci_exynos_quirks(struct device *dev, struct xhci_hcd *xhci) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + xhci->quirks |= XHCI_PLAT | xhci_exynos->quirks; +} + +/* called during probe() after chip reset completes */ +static int xhci_exynos_setup(struct usb_hcd *hcd) +{ + int ret; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + ret = xhci_gen_setup(hcd, xhci_exynos_quirks); + xhci_exynos_alloc_event_ring(xhci, GFP_KERNEL); + + return ret; +} + +static void xhci_exynos_usb_offload_enable_event_ring(struct xhci_hcd *xhci) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + u32 temp; + u64 temp_64; + + temp_64 = xhci_read_64(xhci, &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(&xhci_exynos->ir_set_audio->irq_control); + temp &= ~ER_IRQ_INTERVAL_MASK; + temp |= (u32)160; + writel(temp, &xhci_exynos->ir_set_audio->irq_control); + + temp = readl(&xhci_exynos->ir_set_audio->irq_pending); + xhci_info(xhci, "// [USB Audio] Enabling event ring interrupter %p by writing 0x%x to irq_pending", + xhci_exynos->ir_set_audio, (unsigned int) ER_IRQ_ENABLE(temp)); + writel(ER_IRQ_ENABLE(temp), &xhci_exynos->ir_set_audio->irq_pending); +} + +static int xhci_exynos_start(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci; + int ret; + + ret = xhci_run(hcd); + + xhci = hcd_to_xhci(hcd); + xhci_exynos_usb_offload_enable_event_ring(xhci); + + return ret; +} + +static 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; + + 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); + } + + return ret; +} + +static int xhci_exynos_address_device(struct usb_hcd *hcd, struct usb_device *udev) +{ + struct xhci_hcd *xhci; + int ret; + + ret = xhci_address_device(hcd, udev); + xhci = hcd_to_xhci(hcd); + + /* TODO: store and pass hw info to Co-Processor here*/ + + return ret; +} + +static 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; + 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; + + if (xhci->xhc_state & XHCI_STATE_REMOVING) + return -ESHUTDOWN; + + if (is_lock) { + if (is_main_hcd) + __pm_stay_awake(main_wakelock); + else + __pm_stay_awake(shared_wakelock); + } else { + if (is_main_hcd) + __pm_relax(main_wakelock); + else + __pm_relax(shared_wakelock); + } + + return 0; +} + +static int xhci_exynos_bus_suspend(struct usb_hcd *hcd) +{ + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + + int ret, main_hcd; + + 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; +} + +static int xhci_exynos_bus_resume(struct usb_hcd *hcd) +{ + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + int ret, main_hcd; + + if (hcd == xhci->main_hcd) + main_hcd = 1; + else + main_hcd = 0; + + ret = xhci_bus_resume(hcd); + xhci_exynos_wake_lock(xhci_exynos, main_hcd, 1); + + return ret; +} + +const struct xhci_driver_overrides xhci_exynos_overrides = { + .reset = xhci_exynos_setup, + .start = xhci_exynos_start, + .add_endpoint = xhci_exynos_add_endpoint, + .address_device = xhci_exynos_address_device, + .bus_suspend = xhci_exynos_bus_suspend, + .bus_resume = xhci_exynos_bus_resume, +}; + +static int xhci_exynos_vendor_init(struct xhci_hcd *xhci, struct device *dev) +{ + struct usb_hcd *hcd; + struct xhci_hcd_exynos *xhci_exynos; + struct xhci_plat_priv *priv; + struct wakeup_source *main_wakelock, *shared_wakelock; + struct platform_device *pdev; + + pdev = to_platform_device(dev); + + xhci_plat_override_driver(&xhci_exynos_overrides); + dev->driver->pm = &xhci_exynos_pm_ops; + + main_wakelock = wakeup_source_register(dev, dev_name(dev)); + __pm_stay_awake(main_wakelock); + + /* Initialization shared wakelock for SS HCD */ + shared_wakelock = wakeup_source_register(dev, dev_name(dev)); + __pm_stay_awake(shared_wakelock); + + hcd = xhci->main_hcd; + + priv = hcd_to_xhci_priv(hcd); + xhci_exynos = priv->vendor_priv; + xhci_exynos->dev = dev; + xhci_exynos->main_wakelock = main_wakelock; + xhci_exynos->shared_wakelock = shared_wakelock; + + 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) +{ + /* TODO */ + return true; +} + +static struct xhci_device_context_array *xhci_exynos_alloc_dcbaa( + struct xhci_hcd *xhci, gfp_t flags) +{ + int i; + + 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; + + return xhci->dcbaa; +} + +static void xhci_exynos_free_dcbaa(struct xhci_hcd *xhci) +{ + iounmap(xhci->dcbaa); + xhci->dcbaa = NULL; +} + +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) +{ + return xhci_ring_alloc_uram(xhci, 1, 1, ring_type, max_packet, mem_flags, endpoint_type); +} + +static void xhci_exynos_free_transfer_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, + unsigned int ep_index) +{ + xhci_exynos_ring_free(xhci, ring); +} + +static void xhci_exynos_alloc_container_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, + int type, gfp_t flags) +{ + /* Only first Device Context uses URAM */ + int i; + + ctx->bytes = ioremap(EXYNOS_URAM_DEVICE_CTX_ADDR, EXYNOS_URAM_CTX_SIZE); + if (!ctx->bytes) + return; + + for (i = 0; i < EXYNOS_URAM_CTX_SIZE; i++) + ctx->bytes[i] = 0; + + ctx->dma = EXYNOS_URAM_DEVICE_CTX_ADDR; +} + +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 int xhci_exynos_sync_dev_ctx(struct xhci_hcd *xhci, unsigned int slot_id) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + struct xhci_virt_device *virt_dev; + struct xhci_slot_ctx *slot_ctx; + + int i; + int last_ep; + int last_ep_ctx = 31; + + virt_dev = xhci->devs[slot_id]; + slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); + + last_ep = LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)); + + if (last_ep < 31) + last_ep_ctx = last_ep + 1; + + for (i = 0; i < last_ep_ctx; ++i) { + unsigned int epaddr = xhci_get_endpoint_address(i); + struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->out_ctx, i); + + if (epaddr == xhci_exynos->in_ep) + xhci_exynos->in_deq = ep_ctx->deq; + else if (epaddr == xhci_exynos->out_ep) + xhci_exynos->out_deq = ep_ctx->deq; + } + + return 0; +} +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, + .sync_dev_ctx = xhci_exynos_sync_dev_ctx, +}; + + +static void xhci_exynos_parse_endpoint(struct xhci_hcd *xhci, struct usb_device *udev, + struct usb_endpoint_descriptor *desc, struct xhci_container_ctx *ctx) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + struct usb_endpoint_descriptor *d = desc; + unsigned int ep_index; + struct xhci_ep_ctx *ep_ctx; + + ep_index = xhci_get_endpoint_index(d); + ep_ctx = xhci_get_ep_ctx(xhci, ctx, ep_index); + + if ((d->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC) { + if (d->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + xhci_exynos->in_ep = d->bEndpointAddress; + else + xhci_exynos->out_ep = d->bEndpointAddress; + } +} + +static void xhci_exynos_segment_free_skip(struct xhci_hcd *xhci, struct xhci_segment *seg) +{ + kfree(seg->bounce_buf); + kfree(seg); +} + +static void xhci_exynos_free_segments_for_ring(struct xhci_hcd *xhci, + struct xhci_segment *first) +{ + struct xhci_segment *seg; + + seg = first->next; + + 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); +} + +static void xhci_exynos_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring) +{ + if (!ring) + return; + + 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_event_ring(struct xhci_hcd *xhci) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + xhci_exynos_ring_free(xhci, xhci_exynos->event_ring_audio); +} + +static void xhci_exynos_set_hc_event_deq_audio(struct xhci_hcd *xhci) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + u64 temp; + dma_addr_t deq; + + deq = xhci_trb_virt_to_dma(xhci_exynos->event_ring_audio->deq_seg, + 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, &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, + &xhci_exynos->ir_set_audio->erst_dequeue); + +} + + + +static int xhci_exynos_alloc_event_ring(struct xhci_hcd *xhci, gfp_t flags) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + if (xhci_check_trb_in_td_math(xhci) < 0) + goto fail; + + xhci_exynos->event_ring_audio = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, + TYPE_EVENT, 0, flags); + /* Set the event ring dequeue address */ + xhci_exynos_set_hc_event_deq_audio(xhci); + + return 0; +fail: + return -1; +} + +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 = false; + + while (num_segs > 0) { + struct xhci_segment *next = NULL; + + 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; +} + +static 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); + + return ring; + +fail: + kfree(ring); + return NULL; +} + +static int xhci_exynos_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + /* TODO: AP sleep scenario*/ + + return xhci_suspend(xhci, device_may_wakeup(dev)); +} + +static int xhci_exynos_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + int ret; + + /* TODO: AP resume scenario*/ + + ret = xhci_resume(xhci, 0); + if (ret) + return ret; + + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + return 0; +} + +static const struct dev_pm_ops xhci_exynos_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(xhci_exynos_suspend, xhci_exynos_resume) +}; + +MODULE_DESCRIPTION("xHCI Exynos 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..4428f8f3a5ff --- /dev/null +++ b/drivers/usb/host/xhci-exynos.h @@ -0,0 +1,50 @@ +/* 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 + * + * A lot of code borrowed from the Linux xHCI driver. + */ + +#include "xhci.h" + +/* EXYNOS uram memory map */ +#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 +#define EXYNOS_URAM_CTX_SIZE 2112 + +struct xhci_hcd_exynos { + struct xhci_intr_reg __iomem *ir_set_audio; + + struct xhci_ring *event_ring_audio; + struct xhci_erst erst_audio; + + 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 */ + + u32 in_ep; + u32 out_ep; + u32 in_deq; + u32 out_deq; + + unsigned long long quirks; +}; + +int xhci_check_trb_in_td_math(struct xhci_hcd *xhci); +void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg); +void xhci_link_segments(struct xhci_segment *prev, + struct xhci_segment *next, + enum xhci_ring_type type, bool chain_links); +void xhci_initialize_ring_info(struct xhci_ring *ring, + unsigned int cycle_state); +void xhci_remove_stream_mapping(struct xhci_ring *ring);