All of lore.kernel.org
 help / color / mirror / Atom feed
* USB: cdc-wdm: don't enable interrupts in USB-giveback
@ 2018-06-13  8:30 Oliver Neukum
  0 siblings, 0 replies; 6+ messages in thread
From: Oliver Neukum @ 2018-06-13  8:30 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, Bjørn Mork
  Cc: Robert Foss, Greg Kroah-Hartman, Alan Stern, linux-usb

On Di, 2018-06-12 at 21:57 +0200, Sebastian Andrzej Siewior wrote:
> > Yes, the atomic case should be rare.  It will only happen on errors, and
> > IIUC that's only to work around issues caused by reporting errors back
> > to userspace without actually wanting to err out anyway.
> 
> Yup. The missing part is if this was done to workaround a specific
> userland application or most/all of them.

Yes, If possible we should not regress in that regard.

> > I believe it would be better to decide one an error policy and stick to
> > that.  Then you could just simplify away that whole mess, by either
> > ignoring the error and continue or bailing out and die.
> 
> "Bailing out and die" would be a revert of commit c1da59dad0eb
> ("cdc-wdm: Clear read pipeline in case of error")?
> And ignoring the error would be "not updating rerr" in
> wdm_in_callback().
> I don't care either way. I can do whatever works for you/users best.

It seems to me that the core of the problem is handling an error
in irq context potentially. How about shifting it to a work queue?

	Regards
		Oliver
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* USB: cdc-wdm: don't enable interrupts in USB-giveback
@ 2018-06-12 19:57 Sebastian Andrzej Siewior
  0 siblings, 0 replies; 6+ messages in thread
From: Sebastian Andrzej Siewior @ 2018-06-12 19:57 UTC (permalink / raw)
  To: Bjørn Mork
  Cc: Alan Stern, linux-usb, Greg Kroah-Hartman, Robert Foss, Oliver Neukum

On 2018-06-12 20:28:27 [+0200], Bjørn Mork wrote:
> Yes, the atomic case should be rare.  It will only happen on errors, and
> IIUC that's only to work around issues caused by reporting errors back
> to userspace without actually wanting to err out anyway.

Yup. The missing part is if this was done to workaround a specific
userland application or most/all of them.

> I believe it would be better to decide one an error policy and stick to
> that.  Then you could just simplify away that whole mess, by either
> ignoring the error and continue or bailing out and die.

"Bailing out and die" would be a revert of commit c1da59dad0eb
("cdc-wdm: Clear read pipeline in case of error")?
And ignoring the error would be "not updating rerr" in
wdm_in_callback().
I don't care either way. I can do whatever works for you/users best.

> Bjørn

Sebastian
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* USB: cdc-wdm: don't enable interrupts in USB-giveback
@ 2018-06-12 18:28 Bjørn Mork
  0 siblings, 0 replies; 6+ messages in thread
From: Bjørn Mork @ 2018-06-12 18:28 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Alan Stern, linux-usb, Greg Kroah-Hartman, Robert Foss, Oliver Neukum

Sebastian Andrzej Siewior <bigeasy@linutronix.de> writes:

> On 2018-06-12 12:43:01 [-0400], Alan Stern wrote:
>> On Tue, 12 Jun 2018, Sebastian Andrzej Siewior wrote:
>> 
>> > In the code path
>> >   __usb_hcd_giveback_urb()
>> >   -> wdm_in_callback()
>> >    -> service_outstanding_interrupt()
>> > 
>> > The function service_outstanding_interrupt() will unconditionally enable
>> > interrupts during unlock and invoke usb_submit_urb() with GFP_KERNEL.
>> > If the HCD completes in BH (like ehci does) then the context remains
>> > atomic due local_bh_disable() and enabling interrupts does not change
>> > this.
>> > 
>> > Add an argument to service_outstanding_interrupt() which decides
>> > whether or not it is save to enable interrupts during unlocking and use
>> > GFP_KERNEL or not.
>> 
>> Wouldn't it be easier just to use spin_lock_irqsave() and GFP_ATOMIC
>> all the time?  That's what people normally do with code that can be 
>> called in both process and interrupt contexts.
>
> service_outstanding_interrupt() does unlock + lock instead lock +
> unlock. If you want to have this "always" working (without the
> argument), we could do the false case:
> +               spin_unlock(&desc->iuspin);
> +               rv = usb_submit_urb(desc->response, GFP_ATOMIC);
> +               spin_lock(&desc->iuspin);
>
> all the time. I wanted to preserve the GFP_KERNEL part which is probably
> used more often but fell that this is not needed I could drop that part.

Yes, the atomic case should be rare.  It will only happen on errors, and
IIUC that's only to work around issues caused by reporting errors back
to userspace without actually wanting to err out anyway.

I believe it would be better to decide one an error policy and stick to
that.  Then you could just simplify away that whole mess, by either
ignoring the error and continue or bailing out and die.


Bjørn
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* USB: cdc-wdm: don't enable interrupts in USB-giveback
@ 2018-06-12 17:48 Sebastian Andrzej Siewior
  0 siblings, 0 replies; 6+ messages in thread
From: Sebastian Andrzej Siewior @ 2018-06-12 17:48 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-usb, Greg Kroah-Hartman, Robert Foss, Oliver Neukum

On 2018-06-12 12:43:01 [-0400], Alan Stern wrote:
> On Tue, 12 Jun 2018, Sebastian Andrzej Siewior wrote:
> 
> > In the code path
> >   __usb_hcd_giveback_urb()
> >   -> wdm_in_callback()
> >    -> service_outstanding_interrupt()
> > 
> > The function service_outstanding_interrupt() will unconditionally enable
> > interrupts during unlock and invoke usb_submit_urb() with GFP_KERNEL.
> > If the HCD completes in BH (like ehci does) then the context remains
> > atomic due local_bh_disable() and enabling interrupts does not change
> > this.
> > 
> > Add an argument to service_outstanding_interrupt() which decides
> > whether or not it is save to enable interrupts during unlocking and use
> > GFP_KERNEL or not.
> 
> Wouldn't it be easier just to use spin_lock_irqsave() and GFP_ATOMIC
> all the time?  That's what people normally do with code that can be 
> called in both process and interrupt contexts.

service_outstanding_interrupt() does unlock + lock instead lock +
unlock. If you want to have this "always" working (without the
argument), we could do the false case:
+               spin_unlock(&desc->iuspin);
+               rv = usb_submit_urb(desc->response, GFP_ATOMIC);
+               spin_lock(&desc->iuspin);

all the time. I wanted to preserve the GFP_KERNEL part which is probably
used more often but fell that this is not needed I could drop that part.

> Alan Stern
Sebastian
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* USB: cdc-wdm: don't enable interrupts in USB-giveback
@ 2018-06-12 16:43 Alan Stern
  0 siblings, 0 replies; 6+ messages in thread
From: Alan Stern @ 2018-06-12 16:43 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-usb, Greg Kroah-Hartman, Robert Foss, Oliver Neukum

On Tue, 12 Jun 2018, Sebastian Andrzej Siewior wrote:

> In the code path
>   __usb_hcd_giveback_urb()
>   -> wdm_in_callback()
>    -> service_outstanding_interrupt()
> 
> The function service_outstanding_interrupt() will unconditionally enable
> interrupts during unlock and invoke usb_submit_urb() with GFP_KERNEL.
> If the HCD completes in BH (like ehci does) then the context remains
> atomic due local_bh_disable() and enabling interrupts does not change
> this.
> 
> Add an argument to service_outstanding_interrupt() which decides
> whether or not it is save to enable interrupts during unlocking and use
> GFP_KERNEL or not.

Wouldn't it be easier just to use spin_lock_irqsave() and GFP_ATOMIC
all the time?  That's what people normally do with code that can be 
called in both process and interrupt contexts.

Alan Stern
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* USB: cdc-wdm: don't enable interrupts in USB-giveback
@ 2018-06-12 16:31 Sebastian Andrzej Siewior
  0 siblings, 0 replies; 6+ messages in thread
From: Sebastian Andrzej Siewior @ 2018-06-12 16:31 UTC (permalink / raw)
  To: linux-usb; +Cc: Greg Kroah-Hartman, Robert Foss, Oliver Neukum, Alan Stern

In the code path
  __usb_hcd_giveback_urb()
  -> wdm_in_callback()
   -> service_outstanding_interrupt()

The function service_outstanding_interrupt() will unconditionally enable
interrupts during unlock and invoke usb_submit_urb() with GFP_KERNEL.
If the HCD completes in BH (like ehci does) then the context remains
atomic due local_bh_disable() and enabling interrupts does not change
this.

Add an argument to service_outstanding_interrupt() which decides
whether or not it is save to enable interrupts during unlocking and use
GFP_KERNEL or not.

Fixes: c1da59dad0eb ("cdc-wdm: Clear read pipeline in case of error")
Cc: Robert Foss <robert.foss@collabora.com>
Cc: Oliver Neukum <oneukum@suse.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/usb/class/cdc-wdm.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index a0d284ef3f40..45076b9c7c5e 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -152,7 +152,7 @@ static void wdm_out_callback(struct urb *urb)
 }
 
 /* forward declaration */
-static int service_outstanding_interrupt(struct wdm_device *desc);
+static int service_outstanding_interrupt(struct wdm_device *desc, bool en_irq);
 
 static void wdm_in_callback(struct urb *urb)
 {
@@ -219,7 +219,7 @@ static void wdm_in_callback(struct urb *urb)
 		 * We should respond to further attempts from the device to send
 		 * data, so that we can get unstuck.
 		 */
-		service_outstanding_interrupt(desc);
+		service_outstanding_interrupt(desc, false);
 	}
 
 	spin_unlock(&desc->iuspin);
@@ -448,7 +448,7 @@ static ssize_t wdm_write
  *
  * Called with desc->iuspin locked
  */
-static int service_outstanding_interrupt(struct wdm_device *desc)
+static int service_outstanding_interrupt(struct wdm_device *desc, bool en_irq)
 {
 	int rv = 0;
 
@@ -457,9 +457,15 @@ static int service_outstanding_interrupt(struct wdm_device *desc)
 		goto out;
 
 	set_bit(WDM_RESPONDING, &desc->flags);
-	spin_unlock_irq(&desc->iuspin);
-	rv = usb_submit_urb(desc->response, GFP_KERNEL);
-	spin_lock_irq(&desc->iuspin);
+	if (en_irq) {
+		spin_unlock_irq(&desc->iuspin);
+		rv = usb_submit_urb(desc->response, GFP_KERNEL);
+		spin_lock_irq(&desc->iuspin);
+	} else {
+		spin_unlock(&desc->iuspin);
+		rv = usb_submit_urb(desc->response, GFP_ATOMIC);
+		spin_lock(&desc->iuspin);
+	}
 	if (rv) {
 		dev_err(&desc->intf->dev,
 			"usb_submit_urb failed with result %d\n", rv);
@@ -544,7 +550,7 @@ static ssize_t wdm_read
 		if (!desc->reslength) { /* zero length read */
 			dev_dbg(&desc->intf->dev, "zero length - clearing WDM_READ\n");
 			clear_bit(WDM_READ, &desc->flags);
-			rv = service_outstanding_interrupt(desc);
+			rv = service_outstanding_interrupt(desc, true);
 			spin_unlock_irq(&desc->iuspin);
 			if (rv < 0)
 				goto err;
@@ -571,7 +577,7 @@ static ssize_t wdm_read
 	/* in case we had outstanding data */
 	if (!desc->length) {
 		clear_bit(WDM_READ, &desc->flags);
-		service_outstanding_interrupt(desc);
+		service_outstanding_interrupt(desc, true);
 	}
 	spin_unlock_irq(&desc->iuspin);
 	rv = cntr;

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

end of thread, other threads:[~2018-06-13  8:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-13  8:30 USB: cdc-wdm: don't enable interrupts in USB-giveback Oliver Neukum
  -- strict thread matches above, loose matches on Subject: below --
2018-06-12 19:57 Sebastian Andrzej Siewior
2018-06-12 18:28 Bjørn Mork
2018-06-12 17:48 Sebastian Andrzej Siewior
2018-06-12 16:43 Alan Stern
2018-06-12 16:31 Sebastian Andrzej Siewior

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