From: Wesley Cheng <quic_wcheng@quicinc.com>
To: <srinivas.kandagatla@linaro.org>, <mathias.nyman@intel.com>,
<perex@perex.cz>, <conor+dt@kernel.org>, <corbet@lwn.net>,
<gregkh@linuxfoundation.org>, <lgirdwood@gmail.com>,
<andersson@kernel.org>, <krzysztof.kozlowski+dt@linaro.org>,
<konrad.dybcio@linaro.org>, <Thinh.Nguyen@synopsys.com>,
<broonie@kernel.org>, <bgoswami@quicinc.com>, <tiwai@suse.com>,
<robh+dt@kernel.org>, <agross@kernel.org>
Cc: <linux-kernel@vger.kernel.org>, <devicetree@vger.kernel.org>,
<linux-sound@vger.kernel.org>, <linux-usb@vger.kernel.org>,
<linux-arm-msm@vger.kernel.org>, <linux-doc@vger.kernel.org>,
<alsa-devel@alsa-project.org>,
Mathias Nyman <mathias.nyman@linux.intel.com>,
Wesley Cheng <quic_wcheng@quicinc.com>
Subject: [PATCH v10 01/41] xhci: add support to allocate several interrupters
Date: Fri, 15 Dec 2023 13:49:15 -0800 [thread overview]
Message-ID: <20231215214955.12110-2-quic_wcheng@quicinc.com> (raw)
In-Reply-To: <20231215214955.12110-1-quic_wcheng@quicinc.com>
From: Mathias Nyman <mathias.nyman@linux.intel.com>
Modify the XHCI drivers to accommodate for handling multiple event rings in
case there are multiple interrupters. Add the required APIs so clients are
able to allocate/request for an interrupter ring, and pass this information
back to the client driver. This allows for users to handle the resource
accordingly, such as passing the event ring base address to an audio DSP.
There is no actual support for multiple MSI/MSI-X vectors.
[export xhci_initialize_ring_info() -wcheng]
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
---
drivers/usb/host/xhci-debugfs.c | 2 +-
drivers/usb/host/xhci-mem.c | 108 ++++++++++++++++++++++++++++----
drivers/usb/host/xhci-ring.c | 2 +-
drivers/usb/host/xhci.c | 51 +++++++++------
drivers/usb/host/xhci.h | 6 +-
5 files changed, 137 insertions(+), 32 deletions(-)
diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c
index 6d142cd61bd6..f8ba15e7c225 100644
--- a/drivers/usb/host/xhci-debugfs.c
+++ b/drivers/usb/host/xhci-debugfs.c
@@ -693,7 +693,7 @@ void xhci_debugfs_init(struct xhci_hcd *xhci)
"command-ring",
xhci->debugfs_root);
- xhci_debugfs_create_ring_dir(xhci, &xhci->interrupter->event_ring,
+ xhci_debugfs_create_ring_dir(xhci, &xhci->interrupters[0]->event_ring,
"event-ring",
xhci->debugfs_root);
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 6faa854152ef..4460fa7e9fab 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -323,6 +323,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,
@@ -1855,6 +1856,31 @@ xhci_free_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
kfree(ir);
}
+void xhci_remove_secondary_interrupter(struct usb_hcd *hcd, struct xhci_interrupter *ir)
+{
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ unsigned int intr_num;
+
+ /* interrupter 0 is primary interrupter, don't touch it */
+ if (!ir || !ir->intr_num || ir->intr_num >= xhci->max_interrupters)
+ xhci_dbg(xhci, "Invalid secondary interrupter, can't remove\n");
+
+ /* fixme, should we check xhci->interrupter[intr_num] == ir */
+ /* fixme locking */
+
+ spin_lock_irq(&xhci->lock);
+
+ intr_num = ir->intr_num;
+
+ xhci_remove_interrupter(xhci, ir);
+ xhci->interrupters[intr_num] = NULL;
+
+ spin_unlock_irq(&xhci->lock);
+
+ xhci_free_interrupter(xhci, ir);
+}
+EXPORT_SYMBOL_GPL(xhci_remove_secondary_interrupter);
+
void xhci_mem_cleanup(struct xhci_hcd *xhci)
{
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
@@ -1862,10 +1888,14 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
cancel_delayed_work_sync(&xhci->cmd_timer);
- xhci_remove_interrupter(xhci, xhci->interrupter);
- xhci_free_interrupter(xhci, xhci->interrupter);
- xhci->interrupter = NULL;
- xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed primary event ring");
+ for (i = 0; i < xhci->max_interrupters; i++) {
+ if (xhci->interrupters[i]) {
+ xhci_remove_interrupter(xhci, xhci->interrupters[i]);
+ xhci_free_interrupter(xhci, xhci->interrupters[i]);
+ xhci->interrupters[i] = NULL;
+ }
+ }
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed interrupters");
if (xhci->cmd_ring)
xhci_ring_free(xhci, xhci->cmd_ring);
@@ -1935,6 +1965,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
for (i = 0; i < xhci->num_port_caps; i++)
kfree(xhci->port_caps[i].psi);
kfree(xhci->port_caps);
+ kfree(xhci->interrupters);
xhci->num_port_caps = 0;
xhci->usb2_rhub.ports = NULL;
@@ -1943,6 +1974,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->rh_bw = NULL;
xhci->ext_caps = NULL;
xhci->port_caps = NULL;
+ xhci->interrupters = NULL;
xhci->page_size = 0;
xhci->page_shift = 0;
@@ -2248,18 +2280,20 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
}
static struct xhci_interrupter *
-xhci_alloc_interrupter(struct xhci_hcd *xhci, gfp_t flags)
+xhci_alloc_interrupter(struct xhci_hcd *xhci, int segs, gfp_t flags)
{
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
struct xhci_interrupter *ir;
- unsigned int num_segs;
+ unsigned int num_segs = segs;
int ret;
ir = kzalloc_node(sizeof(*ir), flags, dev_to_node(dev));
if (!ir)
return NULL;
- num_segs = min_t(unsigned int, 1 << HCS_ERST_MAX(xhci->hcs_params2),
+ /* number of ring segments should be greater than 0 */
+ if (segs <= 0)
+ num_segs = min_t(unsigned int, 1 << HCS_ERST_MAX(xhci->hcs_params2),
ERST_MAX_SEGS);
ir->event_ring = xhci_ring_alloc(xhci, num_segs, 1, TYPE_EVENT, 0,
@@ -2294,6 +2328,13 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir,
return -EINVAL;
}
+ if (xhci->interrupters[intr_num]) {
+ xhci_warn(xhci, "Interrupter %d\n already set up", intr_num);
+ return -EINVAL;
+ }
+
+ xhci->interrupters[intr_num] = ir;
+ ir->intr_num = intr_num;
ir->ir_set = &xhci->run_regs->ir_set[intr_num];
/* set ERST count with the number of entries in the segment table */
@@ -2313,10 +2354,52 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir,
return 0;
}
+struct xhci_interrupter *
+xhci_create_secondary_interrupter(struct usb_hcd *hcd, int num_seg)
+{
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct xhci_interrupter *ir;
+ unsigned int i;
+ int err = -ENOSPC;
+
+ if (!xhci->interrupters || xhci->max_interrupters <= 1)
+ return NULL;
+
+ ir = xhci_alloc_interrupter(xhci, num_seg, GFP_KERNEL);
+ if (!ir)
+ return NULL;
+
+ spin_lock_irq(&xhci->lock);
+
+ /* Find available secondary interrupter, interrupter 0 is reserved for primary */
+ for (i = 1; i < xhci->max_interrupters; i++) {
+ if (xhci->interrupters[i] == NULL) {
+ err = xhci_add_interrupter(xhci, ir, i);
+ break;
+ }
+ }
+
+ spin_unlock_irq(&xhci->lock);
+
+ if (err) {
+ xhci_warn(xhci, "Failed to add secondary interrupter, max interrupters %d\n",
+ xhci->max_interrupters);
+ xhci_free_interrupter(xhci, ir);
+ return NULL;
+ }
+
+ xhci_dbg(xhci, "Add secondary interrupter %d, max interrupters %d\n",
+ i, xhci->max_interrupters);
+
+ return ir;
+}
+EXPORT_SYMBOL_GPL(xhci_create_secondary_interrupter);
+
int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
{
- dma_addr_t dma;
+ struct xhci_interrupter *ir;
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+ dma_addr_t dma;
unsigned int val, val2;
u64 val_64;
u32 page_size, temp;
@@ -2440,11 +2523,14 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
/* Allocate and set up primary interrupter 0 with an event ring. */
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Allocating primary event ring");
- xhci->interrupter = xhci_alloc_interrupter(xhci, flags);
- if (!xhci->interrupter)
+ xhci->interrupters = kcalloc_node(xhci->max_interrupters, sizeof(*xhci->interrupters),
+ flags, dev_to_node(dev));
+
+ ir = xhci_alloc_interrupter(xhci, 0, flags);
+ if (!ir)
goto fail;
- if (xhci_add_interrupter(xhci, xhci->interrupter, 0))
+ if (xhci_add_interrupter(xhci, ir, 0))
goto fail;
xhci->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 2c1d614b3b0f..33806ae966f9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3061,7 +3061,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
writel(status, &xhci->op_regs->status);
/* This is the handler of the primary interrupter */
- ir = xhci->interrupter;
+ ir = xhci->interrupters[0];
if (!hcd->msi_enabled) {
u32 irq_pending;
irq_pending = readl(&ir->ir_set->irq_pending);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 08fbabff23a0..b3c9abd97ab1 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -480,7 +480,7 @@ static int xhci_init(struct usb_hcd *hcd)
static int xhci_run_finished(struct xhci_hcd *xhci)
{
- struct xhci_interrupter *ir = xhci->interrupter;
+ struct xhci_interrupter *ir = xhci->interrupters[0];
unsigned long flags;
u32 temp;
@@ -532,7 +532,7 @@ int xhci_run(struct usb_hcd *hcd)
u64 temp_64;
int ret;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- struct xhci_interrupter *ir = xhci->interrupter;
+ struct xhci_interrupter *ir = xhci->interrupters[0];
/* Start the xHCI host controller running only after the USB 2.0 roothub
* is setup.
*/
@@ -596,7 +596,7 @@ void xhci_stop(struct usb_hcd *hcd)
{
u32 temp;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- struct xhci_interrupter *ir = xhci->interrupter;
+ struct xhci_interrupter *ir = xhci->interrupters[0];
mutex_lock(&xhci->mutex);
@@ -692,36 +692,51 @@ EXPORT_SYMBOL_GPL(xhci_shutdown);
#ifdef CONFIG_PM
static void xhci_save_registers(struct xhci_hcd *xhci)
{
- struct xhci_interrupter *ir = xhci->interrupter;
+ struct xhci_interrupter *ir;
+ unsigned int i;
xhci->s3.command = readl(&xhci->op_regs->command);
xhci->s3.dev_nt = readl(&xhci->op_regs->dev_notification);
xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
xhci->s3.config_reg = readl(&xhci->op_regs->config_reg);
- if (!ir)
- return;
+ /* save both primary and all secondary interrupters */
+ /* fixme, shold we lock to prevent race with remove secondary interrupter? */
+ for (i = 0; i < xhci->max_interrupters; i++) {
+ ir = xhci->interrupters[i];
+ if (!ir)
+ continue;
- ir->s3_erst_size = readl(&ir->ir_set->erst_size);
- ir->s3_erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base);
- ir->s3_erst_dequeue = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
- ir->s3_irq_pending = readl(&ir->ir_set->irq_pending);
- ir->s3_irq_control = readl(&ir->ir_set->irq_control);
+ ir->s3_erst_size = readl(&ir->ir_set->erst_size);
+ ir->s3_erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base);
+ ir->s3_erst_dequeue = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
+ ir->s3_irq_pending = readl(&ir->ir_set->irq_pending);
+ ir->s3_irq_control = readl(&ir->ir_set->irq_control);
+ }
}
static void xhci_restore_registers(struct xhci_hcd *xhci)
{
- struct xhci_interrupter *ir = xhci->interrupter;
+ struct xhci_interrupter *ir;
+ unsigned int i;
writel(xhci->s3.command, &xhci->op_regs->command);
writel(xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
writel(xhci->s3.config_reg, &xhci->op_regs->config_reg);
- writel(ir->s3_erst_size, &ir->ir_set->erst_size);
- xhci_write_64(xhci, ir->s3_erst_base, &ir->ir_set->erst_base);
- xhci_write_64(xhci, ir->s3_erst_dequeue, &ir->ir_set->erst_dequeue);
- writel(ir->s3_irq_pending, &ir->ir_set->irq_pending);
- writel(ir->s3_irq_control, &ir->ir_set->irq_control);
+
+ /* FIXME should we lock to protect against freeing of interrupters */
+ for (i = 0; i < xhci->max_interrupters; i++) {
+ ir = xhci->interrupters[i];
+ if (!ir)
+ continue;
+
+ writel(ir->s3_erst_size, &ir->ir_set->erst_size);
+ xhci_write_64(xhci, ir->s3_erst_base, &ir->ir_set->erst_base);
+ xhci_write_64(xhci, ir->s3_erst_dequeue, &ir->ir_set->erst_dequeue);
+ writel(ir->s3_irq_pending, &ir->ir_set->irq_pending);
+ writel(ir->s3_irq_control, &ir->ir_set->irq_control);
+ }
}
static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
@@ -1084,7 +1099,7 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
xhci_dbg(xhci, "// Disabling event ring interrupts\n");
temp = readl(&xhci->op_regs->status);
writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status);
- xhci_disable_interrupter(xhci->interrupter);
+ xhci_disable_interrupter(xhci->interrupters[0]);
xhci_dbg(xhci, "cleaning up memory\n");
xhci_mem_cleanup(xhci);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 90e6b6ef7bd2..a5c72a634e6a 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1774,7 +1774,7 @@ struct xhci_hcd {
struct reset_control *reset;
/* data structures */
struct xhci_device_context_array *dcbaa;
- struct xhci_interrupter *interrupter;
+ struct xhci_interrupter **interrupters;
struct xhci_ring *cmd_ring;
unsigned int cmd_ring_state;
#define CMD_RING_STATE_RUNNING (1 << 0)
@@ -2085,6 +2085,10 @@ struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci,
int type, gfp_t flags);
void xhci_free_container_ctx(struct xhci_hcd *xhci,
struct xhci_container_ctx *ctx);
+struct xhci_interrupter *
+xhci_create_secondary_interrupter(struct usb_hcd *hcd, int num_seg);
+void xhci_remove_secondary_interrupter(struct usb_hcd
+ *hcd, struct xhci_interrupter *ir);
/* xHCI host controller glue */
typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
next prev parent reply other threads:[~2023-12-15 21:50 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-15 21:49 [PATCH v10 00/41] Introduce QC USB SND audio offloading support Wesley Cheng
2023-12-15 21:49 ` Wesley Cheng [this message]
2023-12-15 21:49 ` [PATCH v10 02/41] xhci: add helper to stop endpoint and wait for completion Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 03/41] xhci: sideband: add initial api to register a sideband entity Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 04/41] usb: host: xhci-mem: Cleanup pending secondary event ring events Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 05/41] usb: host: xhci-mem: Allow for interrupter clients to choose specific index Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 06/41] ASoC: Add SOC USB APIs for adding an USB backend Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 07/41] ASoC: dt-bindings: qcom,q6dsp-lpass-ports: Add USB_RX port Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 08/41] ASoC: qcom: qdsp6: Introduce USB AFE port to q6dsp Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 09/41] ASoC: qdsp6: q6afe: Increase APR timeout Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 10/41] ASoC: qcom: qdsp6: Add USB backend ASoC driver for Q6 Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 11/41] ALSA: usb-audio: Introduce USB SND platform op callbacks Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 12/41] ALSA: usb-audio: Export USB SND APIs for modules Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 13/41] ALSA: usb-audio: Save UAC sample size information Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 14/41] dt-bindings: usb: xhci: Add num-hc-interrupters definition Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 15/41] dt-bindings: usb: dwc3: Limit " Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 16/41] usb: dwc3: Specify maximum number of XHCI interrupters Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 17/41] usb: host: xhci-plat: Set XHCI max interrupters if property is present Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 18/41] ALSA: usb-audio: qcom: Add USB QMI definitions Wesley Cheng
2023-12-15 22:38 ` Jeff Johnson
2023-12-18 19:58 ` Wesley Cheng
2023-12-19 12:01 ` Konrad Dybcio
2023-12-19 12:01 ` Konrad Dybcio
2023-12-15 21:49 ` [PATCH v10 19/41] ALSA: usb-audio: qcom: Introduce QC USB SND offloading support Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 20/41] ALSA: usb-audio: Check for support for requested audio format Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 21/41] ASoC: usb: Add PCM format check API for USB backend Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 22/41] ASoC: qcom: qdsp6: Ensure PCM format is supported by USB audio device Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 23/41] ALSA: usb-audio: Prevent starting of audio stream if in use Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 24/41] ALSA: usb-audio: Do not allow USB offload path if PCM device is " Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 25/41] ASoC: dt-bindings: Add Q6USB backend Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 26/41] ASoC: dt-bindings: Update example for enabling USB offload on SM8250 Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 27/41] ALSA: usb-audio: qcom: Populate PCM and USB chip information Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 28/41] ASoC: qcom: qdsp6: Add support to track available USB PCM devices Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 29/41] ASoC: Introduce SND kcontrols to select sound card and PCM device Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 30/41] ASoC: qcom: qdsp6: Add SOC USB offload select get/put callbacks Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 31/41] ASoC: Add SND kcontrol for fetching USB offload status Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 32/41] ASoC: qcom: qdsp6: Add PCM ops to track current state Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 33/41] ASoC: usb: Create SOC USB SND jack kcontrol Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 34/41] ASoC: qcom: qdsp6: Add headphone jack for offload connection status Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 35/41] ASoC: usb: Fetch ASoC sound card information Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 36/41] ALSA: usb-audio: mixer: Add USB offloading mixer control Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 37/41] ALSA: usb-audio: qcom: Use card and PCM index from QMI request Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 38/41] ALSA: usb-audio: Allow for rediscovery of connected USB SND devices Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 39/41] ASoC: usb: Rediscover USB SND devices on USB port add Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 40/41] ASoC: qcom: Populate SoC components string Wesley Cheng
2023-12-15 21:49 ` [PATCH v10 41/41] ASoC: doc: Add documentation for SOC USB Wesley Cheng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231215214955.12110-2-quic_wcheng@quicinc.com \
--to=quic_wcheng@quicinc.com \
--cc=Thinh.Nguyen@synopsys.com \
--cc=agross@kernel.org \
--cc=alsa-devel@alsa-project.org \
--cc=andersson@kernel.org \
--cc=bgoswami@quicinc.com \
--cc=broonie@kernel.org \
--cc=conor+dt@kernel.org \
--cc=corbet@lwn.net \
--cc=devicetree@vger.kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=konrad.dybcio@linaro.org \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=lgirdwood@gmail.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mathias.nyman@intel.com \
--cc=mathias.nyman@linux.intel.com \
--cc=perex@perex.cz \
--cc=robh+dt@kernel.org \
--cc=srinivas.kandagatla@linaro.org \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®