From nobody Thu Nov 14 03:59:35 2024 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6155A1C2312; Thu, 12 Sep 2024 19:40:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726170022; cv=none; b=VaNyhhNSsB2tOcLk/mNDcJb/V5j5ExYTdiibsR9iRZC3+T64Z+R+VqTI+xQDVpA2KYZgQI8NxCqiBCAnwpV/QAsYJFf8jq+jhw41tJuX4guJbrKzCZqHaM6eObe1+8x+rq9j4LglrUGQ20dCQtZj5sfBt4fsu+Uzl0OfkYnhqJ0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726170022; c=relaxed/simple; bh=Eqv339OJtjJ3T6xXMI3sEuHD29MstKzwp+v9zaqcxOU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HmFnPfuA8kUcmURaXr95qhQsHWFhjfD9/1/XsIdAUUDHzpxqeG2FB9URjRzI/rK/SfOH/1K4y7aLNU0pLPGMPxzLoLon4tdg9dXQezFWQH6sYDKjVoVGFWHTDwnCTt6SaFE2ddOCdSBItQ+JlAi7gAknrMiKiqvzaNLoQ+WNVCE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=W+F37rEe; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="W+F37rEe" Received: from pps.filterd (m0279863.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 48CHspxV014002; Thu, 12 Sep 2024 19:39:49 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= DBoQc14++f1KkHjyymf2dfEVwqjOA2izDjzzPyT9FM4=; b=W+F37rEeGhK54OPL aWKNaNEV2s6KyZJqPH4h64E6yGek9CKVy/Vh4cx9WooculE1BBPxtdM0Cfd2ZckT WLMbslEFR3ods6pciW172l/FzuKLG9dvX3ZCPqYCLW5t5TpYrJHRKs6zylfr9/JA rsy7cy9ctCABdEPasc6bWhvqVK5dkN3ew7cNxgGI43VUUYegl3N+pMNOGXc4XQ7m EEIKV9uQS+sjl2nm3oG7PMBpMuEsxrnwz1lsduzBjcVixQ/PUMOmTkvVpAE6O8su PaK0QuaNpySMafd8sIQQ+cwKHYNebBBZ3xoDrJ/QQWevmNgNnm+1OGr1otWABkus OEA+jQ== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 41gy5a6khw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 12 Sep 2024 19:39:48 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 48CJdlg2032738 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 12 Sep 2024 19:39:47 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 12 Sep 2024 12:39:47 -0700 From: Wesley Cheng To: , , , , , , , , , , , , , , CC: , , , , , , , , Mathias Nyman , Wesley Cheng Subject: [PATCH v27 03/32] xhci: sideband: add initial api to register a sideband entity Date: Thu, 12 Sep 2024 12:39:06 -0700 Message-ID: <20240912193935.1916426-4-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240912193935.1916426-1-quic_wcheng@quicinc.com> References: <20240912193935.1916426-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: UTvTAr14nu4opXGfo2193hv82t44HWzT X-Proofpoint-ORIG-GUID: UTvTAr14nu4opXGfo2193hv82t44HWzT X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 suspectscore=0 bulkscore=0 mlxlogscore=999 phishscore=0 impostorscore=0 mlxscore=0 priorityscore=1501 clxscore=1015 adultscore=0 lowpriorityscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2408220000 definitions=main-2409120144 Content-Type: text/plain; charset="utf-8" From: Mathias Nyman Introduce XHCI sideband, which manages the USB endpoints being requested by a client driver. This is used for when client drivers are attempting to offload USB endpoints to another entity for handling USB transfers. XHCI sideband will allow for drivers to fetch the required information about the transfer ring, so the user can submit transfers independently. Expose the required APIs for drivers to register and request for a USB endpoint and to manage XHCI secondary interrupters. Multiple ring segment page linking, proper endpoint clean up, and allowing module compilation added by Wesley Cheng to complete original concept code by Mathias Nyman. Signed-off-by: Mathias Nyman Co-developed-by: Wesley Cheng Signed-off-by: Wesley Cheng --- drivers/usb/host/Kconfig | 9 + drivers/usb/host/Makefile | 2 + drivers/usb/host/xhci-sideband.c | 424 ++++++++++++++++++++++++++++++ drivers/usb/host/xhci.h | 4 + include/linux/usb/xhci-sideband.h | 70 +++++ 5 files changed, 509 insertions(+) create mode 100644 drivers/usb/host/xhci-sideband.c create mode 100644 include/linux/usb/xhci-sideband.h diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 4448d0ab06f0..96659efa4be5 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -104,6 +104,15 @@ config USB_XHCI_RZV2M Say 'Y' to enable the support for the xHCI host controller found in Renesas RZ/V2M SoC. =20 +config USB_XHCI_SIDEBAND + tristate "xHCI support for sideband" + help + Say 'Y' to enable the support for the xHCI sideband capability. + Provide a mechanism for a sideband datapath for payload associated + with audio class endpoints. This allows for an audio DSP to use + xHCI USB endpoints directly, allowing CPU to sleep while playing + audio. + config USB_XHCI_TEGRA tristate "xHCI support for NVIDIA Tegra SoCs" depends on PHY_TEGRA_XUSB diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index be4e5245c52f..435a1e93b40b 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -32,6 +32,8 @@ endif xhci-rcar-hcd-y +=3D xhci-rcar.o xhci-rcar-hcd-$(CONFIG_USB_XHCI_RZV2M) +=3D xhci-rzv2m.o =20 +obj-$(CONFIG_USB_XHCI_SIDEBAND) +=3D xhci-sideband.o + obj-$(CONFIG_USB_PCI) +=3D pci-quirks.o =20 obj-$(CONFIG_USB_EHCI_HCD) +=3D ehci-hcd.o diff --git a/drivers/usb/host/xhci-sideband.c b/drivers/usb/host/xhci-sideb= and.c new file mode 100644 index 000000000000..4380a1910a19 --- /dev/null +++ b/drivers/usb/host/xhci-sideband.c @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * xHCI host controller sideband support + * + * Copyright (c) 2023, Intel Corporation. + * + * Author: Mathias Nyman + */ + +#include +#include + +#include "xhci.h" + +/* sideband internal helpers */ +static struct sg_table * +xhci_ring_to_sgtable(struct xhci_sideband *sb, struct xhci_ring *ring) +{ + struct xhci_segment *seg; + struct sg_table *sgt; + unsigned int n_pages; + struct page **pages; + struct device *dev; + size_t sz; + int i; + + dev =3D xhci_to_hcd(sb->xhci)->self.sysdev; + sz =3D ring->num_segs * TRB_SEGMENT_SIZE; + n_pages =3D PAGE_ALIGN(sz) >> PAGE_SHIFT; + pages =3D kvmalloc_array(n_pages, sizeof(struct page *), GFP_KERNEL); + if (!pages) + return NULL; + + sgt =3D kzalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) { + kvfree(pages); + return NULL; + } + + seg =3D ring->first_seg; + if (!seg) + goto err; + /* + * Rings can potentially have multiple segments, create an array that + * carries page references to allocated segments. Utilize the + * sg_alloc_table_from_pages() to create the sg table, and to ensure + * that page links are created. + */ + for (i =3D 0; i < ring->num_segs; i++) { + dma_get_sgtable(dev, sgt, seg->trbs, seg->dma, + TRB_SEGMENT_SIZE); + pages[i] =3D sg_page(sgt->sgl); + sg_free_table(sgt); + seg =3D seg->next; + } + + if (sg_alloc_table_from_pages(sgt, pages, n_pages, 0, sz, GFP_KERNEL)) + goto err; + + /* + * Save first segment dma address to sg dma_address field for the sideband + * client to have access to the IOVA of the ring. + */ + sg_dma_address(sgt->sgl) =3D ring->first_seg->dma; + + return sgt; + +err: + kvfree(pages); + kfree(sgt); + + return NULL; +} + +static void +__xhci_sideband_remove_endpoint(struct xhci_sideband *sb, struct xhci_virt= _ep *ep) +{ + /* + * Issue a stop endpoint command when an endpoint is removed. + * The stop ep cmd handler will handle the ring cleanup. + */ + xhci_stop_endpoint_sync(sb->xhci, ep, 0, GFP_KERNEL); + + ep->sideband =3D NULL; + sb->eps[ep->ep_index] =3D NULL; +} + +/* sideband api functions */ + +/** + * xhci_sideband_add_endpoint - add endpoint to sideband access list + * @sb: sideband instance for this usb device + * @host_ep: usb host endpoint + * + * Adds an endpoint to the list of sideband accessed endpoints for this usb + * device. + * After an endpoint is added the sideband client can get the endpoint tra= nsfer + * ring buffer by calling xhci_sideband_endpoint_buffer() + * + * Return: 0 on success, negative error otherwise. + */ +int +xhci_sideband_add_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep) +{ + struct xhci_virt_ep *ep; + unsigned int ep_index; + + mutex_lock(&sb->mutex); + ep_index =3D xhci_get_endpoint_index(&host_ep->desc); + ep =3D &sb->vdev->eps[ep_index]; + + if (ep->ep_state & EP_HAS_STREAMS) { + mutex_unlock(&sb->mutex); + return -EINVAL; + } + + /* + * Note, we don't know the DMA mask of the audio DSP device, if its + * smaller than for xhci it won't be able to access the endpoint ring + * buffer. This could be solved by not allowing the audio class driver + * to add the endpoint the normal way, but instead offload it immediately, + * and let this function add the endpoint and allocate the ring buffer + * with the smallest common DMA mask + */ + if (sb->eps[ep_index] || ep->sideband) { + mutex_unlock(&sb->mutex); + return -EBUSY; + } + + ep->sideband =3D sb; + sb->eps[ep_index] =3D ep; + mutex_unlock(&sb->mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(xhci_sideband_add_endpoint); + +/** + * xhci_sideband_remove_endpoint - remove endpoint from sideband access li= st + * @sb: sideband instance for this usb device + * @host_ep: usb host endpoint + * + * Removes an endpoint from the list of sideband accessed endpoints for th= is usb + * device. + * sideband client should no longer touch the endpoint transfer buffer aft= er + * calling this. + * + * Return: 0 on success, negative error otherwise. + */ +int +xhci_sideband_remove_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep) +{ + struct xhci_virt_ep *ep; + unsigned int ep_index; + + mutex_lock(&sb->mutex); + ep_index =3D xhci_get_endpoint_index(&host_ep->desc); + ep =3D sb->eps[ep_index]; + + if (!ep || !ep->sideband || ep->sideband !=3D sb) { + mutex_unlock(&sb->mutex); + return -ENODEV; + } + + __xhci_sideband_remove_endpoint(sb, ep); + xhci_initialize_ring_info(ep->ring, 1); + mutex_unlock(&sb->mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(xhci_sideband_remove_endpoint); + +int +xhci_sideband_stop_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep) +{ + struct xhci_virt_ep *ep; + unsigned int ep_index; + + ep_index =3D xhci_get_endpoint_index(&host_ep->desc); + ep =3D sb->eps[ep_index]; + + if (!ep || !ep->sideband || ep->sideband !=3D sb) + return -EINVAL; + + return xhci_stop_endpoint_sync(sb->xhci, ep, 0, GFP_KERNEL); +} +EXPORT_SYMBOL_GPL(xhci_sideband_stop_endpoint); + +/** + * xhci_sideband_get_endpoint_buffer - gets the endpoint transfer buffer a= ddress + * @sb: sideband instance for this usb device + * @host_ep: usb host endpoint + * + * Returns the address of the endpoint buffer where xHC controller reads q= ueued + * transfer TRBs from. This is the starting address of the ringbuffer wher= e the + * sideband client should write TRBs to. + * + * Caller needs to free the returned sg_table + * + * Return: struct sg_table * if successful. NULL otherwise. + */ +struct sg_table * +xhci_sideband_get_endpoint_buffer(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep) +{ + struct xhci_virt_ep *ep; + unsigned int ep_index; + + ep_index =3D xhci_get_endpoint_index(&host_ep->desc); + ep =3D sb->eps[ep_index]; + + if (!ep || !ep->sideband || ep->sideband !=3D sb) + return NULL; + + return xhci_ring_to_sgtable(sb, ep->ring); +} +EXPORT_SYMBOL_GPL(xhci_sideband_get_endpoint_buffer); + +/** + * xhci_sideband_get_event_buffer - return the event buffer for this device + * @sb: sideband instance for this usb device + * + * If a secondary xhci interupter is set up for this usb device then this + * function returns the address of the event buffer where xHC writes + * the transfer completion events. + * + * Caller needs to free the returned sg_table + * + * Return: struct sg_table * if successful. NULL otherwise. + */ +struct sg_table * +xhci_sideband_get_event_buffer(struct xhci_sideband *sb) +{ + if (!sb || !sb->ir) + return NULL; + + return xhci_ring_to_sgtable(sb, sb->ir->event_ring); +} +EXPORT_SYMBOL_GPL(xhci_sideband_get_event_buffer); + +/** + * xhci_sideband_create_interrupter - creates a new interrupter for this s= ideband + * @sb: sideband instance for this usb device + * @num_seg: number of event ring segments to allocate + * @ip_autoclear: IP autoclearing support such as MSI implemented + * + * Sets up a xhci interrupter that can be used for this sideband accessed = usb + * device. Transfer events for this device can be routed to this interrupt= ers + * event ring by setting the 'Interrupter Target' field correctly when que= ueing + * the transfer TRBs. + * Once this interrupter is created the interrupter target ID can be obtai= ned + * by calling xhci_sideband_interrupter_id() + * + * Returns 0 on success, negative error otherwise + */ +int +xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, + bool ip_autoclear) +{ + int ret =3D 0; + + if (!sb) + return -ENODEV; + + mutex_lock(&sb->mutex); + if (sb->ir) { + ret =3D -EBUSY; + goto out; + } + + sb->ir =3D xhci_create_secondary_interrupter(xhci_to_hcd(sb->xhci), + num_seg); + if (!sb->ir) { + ret =3D -ENOMEM; + goto out; + } + + sb->ir->ip_autoclear =3D ip_autoclear; + /* skip events for secondary interrupters by default */ + sb->ir->skip_events =3D true; + +out: + mutex_unlock(&sb->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(xhci_sideband_create_interrupter); + +/** + * xhci_sideband_remove_interrupter - remove the interrupter from a sideba= nd + * @sb: sideband instance for this usb device + * + * Removes a registered interrupt for a sideband. This would allow for ot= her + * sideband users to utilize this interrupter. + */ +void +xhci_sideband_remove_interrupter(struct xhci_sideband *sb) +{ + if (!sb || !sb->ir) + return; + + mutex_lock(&sb->mutex); + xhci_remove_secondary_interrupter(xhci_to_hcd(sb->xhci), sb->ir); + + sb->ir =3D NULL; + mutex_unlock(&sb->mutex); +} +EXPORT_SYMBOL_GPL(xhci_sideband_remove_interrupter); + +/** + * xhci_sideband_interrupter_id - return the interrupter target id + * @sb: sideband instance for this usb device + * + * If a secondary xhci interrupter is set up for this usb device then this + * function returns the ID used by the interrupter. The sideband client + * needs to write this ID to the 'Interrupter Target' field of the transfe= r TRBs + * it queues on the endpoints transfer ring to ensure transfer completion = event + * are written by xHC to the correct interrupter event ring. + * + * Returns interrupter id on success, negative error othgerwise + */ +int +xhci_sideband_interrupter_id(struct xhci_sideband *sb) +{ + if (!sb || !sb->ir) + return -ENODEV; + + return sb->ir->intr_num; +} +EXPORT_SYMBOL_GPL(xhci_sideband_interrupter_id); + +/** + * xhci_sideband_register - register a sideband for a usb device + * @udev: usb device to be accessed via sideband + * + * Allows for clients to utilize XHCI interrupters and fetch transfer and = event + * ring parameters for executing data transfers. + * + * Return: pointer to a new xhci_sideband instance if successful. NULL oth= erwise. + */ +struct xhci_sideband * +xhci_sideband_register(struct usb_device *udev) +{ + struct usb_hcd *hcd =3D bus_to_hcd(udev->bus); + struct xhci_hcd *xhci =3D hcd_to_xhci(hcd); + struct xhci_virt_device *vdev; + struct xhci_sideband *sb; + + /* make sure the usb device is connected to a xhci controller */ + if (!udev->slot_id) + return NULL; + + sb =3D kzalloc_node(sizeof(*sb), GFP_KERNEL, dev_to_node(hcd->self.sysdev= )); + if (!sb) + return NULL; + + mutex_init(&sb->mutex); + + /* check this device isn't already controlled via sideband */ + spin_lock_irq(&xhci->lock); + + vdev =3D xhci->devs[udev->slot_id]; + + if (!vdev || vdev->sideband) { + xhci_warn(xhci, "XHCI sideband for slot %d already in use\n", + udev->slot_id); + spin_unlock_irq(&xhci->lock); + kfree(sb); + return NULL; + } + + sb->xhci =3D xhci; + sb->vdev =3D vdev; + vdev->sideband =3D sb; + + spin_unlock_irq(&xhci->lock); + + return sb; +} +EXPORT_SYMBOL_GPL(xhci_sideband_register); + +/** + * xhci_sideband_unregister - unregister sideband access to a usb device + * @sb: sideband instance to be unregistered + * + * Unregisters sideband access to a usb device and frees the sideband + * instance. + * After this the endpoint and interrupter event buffers should no longer + * be accessed via sideband. The xhci driver can now take over handling + * the buffers. + */ +void +xhci_sideband_unregister(struct xhci_sideband *sb) +{ + struct xhci_hcd *xhci; + int i; + + if (!sb) + return; + + xhci =3D sb->xhci; + + mutex_lock(&sb->mutex); + for (i =3D 0; i < EP_CTX_PER_DEV; i++) + if (sb->eps[i]) + __xhci_sideband_remove_endpoint(sb, sb->eps[i]); + mutex_unlock(&sb->mutex); + + xhci_sideband_remove_interrupter(sb); + + spin_lock_irq(&xhci->lock); + sb->xhci =3D NULL; + sb->vdev->sideband =3D NULL; + spin_unlock_irq(&xhci->lock); + + kfree(sb); +} +EXPORT_SYMBOL_GPL(xhci_sideband_unregister); +MODULE_DESCRIPTION("xHCI sideband driver for secondary interrupter managem= ent"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index a6fbfc11fb1d..503784345787 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -693,6 +693,8 @@ struct xhci_virt_ep { int next_frame_id; /* Use new Isoch TRB layout needed for extended TBC support */ bool use_extended_tbc; + /* set if this endpoint is controlled via sideband access*/ + struct xhci_sideband *sideband; }; =20 enum xhci_overhead_type { @@ -755,6 +757,8 @@ struct xhci_virt_device { u16 current_mel; /* Used for the debugfs interfaces. */ void *debugfs_private; + /* set if this device is registered for sideband access */ + struct xhci_sideband *sideband; }; =20 /* diff --git a/include/linux/usb/xhci-sideband.h b/include/linux/usb/xhci-sid= eband.h new file mode 100644 index 000000000000..6c11e240fbca --- /dev/null +++ b/include/linux/usb/xhci-sideband.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * xHCI host controller sideband support + * + * Copyright (c) 2023, Intel Corporation. + * + * Author: Mathias Nyman + */ + +#ifndef __LINUX_XHCI_SIDEBAND_H +#define __LINUX_XHCI_SIDEBAND_H + +#include +#include + +#define EP_CTX_PER_DEV 31 /* FIXME defined twice, from xhci.h */ + +struct xhci_sideband; + +/** + * struct xhci_sideband - representation of a sideband accessed usb device. + * @xhci: The xhci host controller the usb device is connected to + * @vdev: the usb device accessed via sideband + * @eps: array of endpoints controlled via sideband + * @ir: event handling and buffer for sideband accessed device + * @mutex: mutex for sideband operations + * + * FIXME usb device accessed via sideband Keeping track of sideband access= ed usb devices. + */ + +struct xhci_sideband { + struct xhci_hcd *xhci; + struct xhci_virt_device *vdev; + struct xhci_virt_ep *eps[EP_CTX_PER_DEV]; + struct xhci_interrupter *ir; + + /* Synchronizing xHCI sideband operations with client drivers operations = */ + struct mutex mutex; +}; + +struct xhci_sideband * +xhci_sideband_register(struct usb_device *udev); +void +xhci_sideband_unregister(struct xhci_sideband *sb); +int +xhci_sideband_add_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +int +xhci_sideband_remove_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +int +xhci_sideband_stop_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +struct sg_table * +xhci_sideband_get_endpoint_buffer(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +struct sg_table * +xhci_sideband_get_event_buffer(struct xhci_sideband *sb); + +int +xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, + bool ip_autoclear); + +void +xhci_sideband_remove_interrupter(struct xhci_sideband *sb); + +int +xhci_sideband_interrupter_id(struct xhci_sideband *sb); + +#endif /* __LINUX_XHCI_SIDEBAND_H */