diff mbox series

[v20,06/41] usb: host: xhci-sideband: Expose a sideband interrupter enable API

Message ID 20240425215125.29761-7-quic_wcheng@quicinc.com
State New
Headers show
Series Introduce QC USB SND audio offloading support | expand

Commit Message

Wesley Cheng April 25, 2024, 9:50 p.m. UTC
Some use cases maybe require that the secondary interrupter's events to
be handled by the OS.  In this case, configure the IMOD and the
skip_events property to enable the interrupter's events.  By default,
assume that the secondary interrupter doesn't want to enable OS event
handling.

Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
---
 drivers/usb/host/xhci-sideband.c  | 28 ++++++++++++++++++++++++++++
 include/linux/usb/xhci-sideband.h |  2 ++
 2 files changed, 30 insertions(+)

Comments

Mathias Nyman May 2, 2024, 11:07 a.m. UTC | #1
On 26.4.2024 0.50, Wesley Cheng wrote:
> Some use cases maybe require that the secondary interrupter's events to
> be handled by the OS.  In this case, configure the IMOD and the
> skip_events property to enable the interrupter's events.  By default,
> assume that the secondary interrupter doesn't want to enable OS event
> handling.
> 
> Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
> ---
>   drivers/usb/host/xhci-sideband.c  | 28 ++++++++++++++++++++++++++++
>   include/linux/usb/xhci-sideband.h |  2 ++
>   2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/usb/host/xhci-sideband.c b/drivers/usb/host/xhci-sideband.c
> index 255feae33c6e..6fdae9840c11 100644
> --- a/drivers/usb/host/xhci-sideband.c
> +++ b/drivers/usb/host/xhci-sideband.c
> @@ -237,6 +237,30 @@ xhci_sideband_get_event_buffer(struct xhci_sideband *sb)
>   }
>   EXPORT_SYMBOL_GPL(xhci_sideband_get_event_buffer);
>   
> +/**
> + * xhci_sideband_enable_interrupt - enable interrupt for secondary interrupter
> + * @sb: sideband instance for this usb device
> + * @imod_interval: number of event ring segments to allocate
> + *
> + * Enables OS owned event handling for a particular interrupter if client
> + * requests for it.  In addition, set the IMOD interval for this particular
> + * interrupter.
> + *
> + * Returns 0 on success, negative error otherwise
> + */
> +int xhci_sideband_enable_interrupt(struct xhci_sideband *sb, u32 imod_interval)
> +{
> +	if (!sb || !sb->ir)
> +		return -ENODEV;
> +
> +	xhci_set_interrupter_moderation(sb->ir, imod_interval);

Is there a need to adjust the moderation after initial setup?

If not then maybe we could pass the imod_interval as a parameter to
xhci_create_secondary_interrupter(), and avoid exporting
xhci_set_interrupter_moderation()


> +	sb->ir->skip_events = false;
> +	xhci_enable_interrupter(sb->ir);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(xhci_sideband_enable_interrupt);

I can't find the place where xhci_sideband_enable_interrupt() is called in
this series. How is it planned to be used?

Thanks
Mathias
Wesley Cheng May 2, 2024, 11:37 p.m. UTC | #2
Hi Mathias,

On 5/2/2024 4:07 AM, Mathias Nyman wrote:
> On 26.4.2024 0.50, Wesley Cheng wrote:
>> Some use cases maybe require that the secondary interrupter's events to
>> be handled by the OS.  In this case, configure the IMOD and the
>> skip_events property to enable the interrupter's events.  By default,
>> assume that the secondary interrupter doesn't want to enable OS event
>> handling.
>>
>> Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
>> ---
>>   drivers/usb/host/xhci-sideband.c  | 28 ++++++++++++++++++++++++++++
>>   include/linux/usb/xhci-sideband.h |  2 ++
>>   2 files changed, 30 insertions(+)
>>
>> diff --git a/drivers/usb/host/xhci-sideband.c 
>> b/drivers/usb/host/xhci-sideband.c
>> index 255feae33c6e..6fdae9840c11 100644
>> --- a/drivers/usb/host/xhci-sideband.c
>> +++ b/drivers/usb/host/xhci-sideband.c
>> @@ -237,6 +237,30 @@ xhci_sideband_get_event_buffer(struct 
>> xhci_sideband *sb)
>>   }
>>   EXPORT_SYMBOL_GPL(xhci_sideband_get_event_buffer);
>> +/**
>> + * xhci_sideband_enable_interrupt - enable interrupt for secondary 
>> interrupter
>> + * @sb: sideband instance for this usb device
>> + * @imod_interval: number of event ring segments to allocate
>> + *
>> + * Enables OS owned event handling for a particular interrupter if 
>> client
>> + * requests for it.  In addition, set the IMOD interval for this 
>> particular
>> + * interrupter.
>> + *
>> + * Returns 0 on success, negative error otherwise
>> + */
>> +int xhci_sideband_enable_interrupt(struct xhci_sideband *sb, u32 
>> imod_interval)
>> +{
>> +    if (!sb || !sb->ir)
>> +        return -ENODEV;
>> +
>> +    xhci_set_interrupter_moderation(sb->ir, imod_interval);
> 
> Is there a need to adjust the moderation after initial setup?
> 
> If not then maybe we could pass the imod_interval as a parameter to
> xhci_create_secondary_interrupter(), and avoid exporting
> xhci_set_interrupter_moderation()
> 
> 

Let me preface my comments by saying that I was trying to include some 
aspects of enabling the secondary interrupter line within the main apps 
proc.  If this gets too confusing, I can remove these mechanisms for 
now.  For example, as you mentioned below 
xhci_sideband_enable_interrupt() isn't going to be used in the offload path.

However, I decided to add it so we can have some corresponding function 
that will utilize/set skip_events = false. (as it is "true" by default) 
Again, I can remove this part and revisit later when we actually have a 
use case to handle secondary interrupts on apps.

As for the IMOD setting, depending on what you think, I can add it as 
part of xhci_create_secondary_interrupter()

>> +    sb->ir->skip_events = false;
>> +    xhci_enable_interrupter(sb->ir);
>> +
>> +    return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(xhci_sideband_enable_interrupt);
> 
> I can't find the place where xhci_sideband_enable_interrupt() is called in
> this series. How is it planned to be used?
> 
> Thanks
> Mathias

Thanks
Wesley Cheng
diff mbox series

Patch

diff --git a/drivers/usb/host/xhci-sideband.c b/drivers/usb/host/xhci-sideband.c
index 255feae33c6e..6fdae9840c11 100644
--- a/drivers/usb/host/xhci-sideband.c
+++ b/drivers/usb/host/xhci-sideband.c
@@ -237,6 +237,30 @@  xhci_sideband_get_event_buffer(struct xhci_sideband *sb)
 }
 EXPORT_SYMBOL_GPL(xhci_sideband_get_event_buffer);
 
+/**
+ * xhci_sideband_enable_interrupt - enable interrupt for secondary interrupter
+ * @sb: sideband instance for this usb device
+ * @imod_interval: number of event ring segments to allocate
+ *
+ * Enables OS owned event handling for a particular interrupter if client
+ * requests for it.  In addition, set the IMOD interval for this particular
+ * interrupter.
+ *
+ * Returns 0 on success, negative error otherwise
+ */
+int xhci_sideband_enable_interrupt(struct xhci_sideband *sb, u32 imod_interval)
+{
+	if (!sb || !sb->ir)
+		return -ENODEV;
+
+	xhci_set_interrupter_moderation(sb->ir, imod_interval);
+	sb->ir->skip_events = false;
+	xhci_enable_interrupter(sb->ir);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xhci_sideband_enable_interrupt);
+
 /**
  * xhci_sideband_create_interrupter - creates a new interrupter for this sideband
  * @sb: sideband instance for this usb device
@@ -275,6 +299,8 @@  xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg,
 	}
 
 	sb->ir->ip_autoclear = ip_autoclear;
+	/* skip events for secondary interrupters by default */
+	sb->ir->skip_events = true;
 
 out:
 	mutex_unlock(&sb->mutex);
@@ -297,6 +323,8 @@  xhci_sideband_remove_interrupter(struct xhci_sideband *sb)
 		return;
 
 	mutex_lock(&sb->mutex);
+	if (!sb->ir->skip_events)
+		xhci_disable_interrupter(sb->ir);
 	xhci_remove_secondary_interrupter(xhci_to_hcd(sb->xhci), sb->ir);
 
 	sb->ir = NULL;
diff --git a/include/linux/usb/xhci-sideband.h b/include/linux/usb/xhci-sideband.h
index 1035dae43cee..a749ae307ba7 100644
--- a/include/linux/usb/xhci-sideband.h
+++ b/include/linux/usb/xhci-sideband.h
@@ -54,6 +54,8 @@  xhci_sideband_get_endpoint_buffer(struct xhci_sideband *sb,
 struct sg_table *
 xhci_sideband_get_event_buffer(struct xhci_sideband *sb);
 
+int xhci_sideband_enable_interrupt(struct xhci_sideband *sb, u32 imod_interval);
+
 int
 xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg,
 				 bool ip_autoclear);