aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/serial
diff options
context:
space:
mode:
authorJohan Hovold2013-10-09 17:01:11 +0200
committerGreg Kroah-Hartman2013-10-11 17:00:26 -0700
commit818f60365a29ab1266d92c6a91094fbf93465ff8 (patch)
treeab684c393c0c268fd556179d405de1cc982093fa /drivers/usb/serial
parent92ad247995c587e07cb67dcc8aafac4db636e394 (diff)
USB: serial: add memory flags to usb_serial_generic_write_start
Add memory-flags parameter to usb_serial_generic_write_start which is called from write, resume and completion handler, all with different allocation requirements. Note that by using the memory flag to determine when called from the completion handler, everything will work as before even if the completion handler is run with interrupts enabled (as suggested). Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/generic.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index fce374657ea2..31f78290c0e4 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -123,12 +123,14 @@ int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port,
/**
* usb_serial_generic_write_start - start writing buffered data
* @port: usb-serial port
+ * @mem_flags: flags to use for memory allocations
*
* Serialised using USB_SERIAL_WRITE_BUSY flag.
*
* Return: Zero on success or if busy, otherwise a negative errno value.
*/
-static int usb_serial_generic_write_start(struct usb_serial_port *port)
+static int usb_serial_generic_write_start(struct usb_serial_port *port,
+ gfp_t mem_flags)
{
struct urb *urb;
int count, result;
@@ -159,7 +161,7 @@ retry:
spin_unlock_irqrestore(&port->lock, flags);
clear_bit(i, &port->write_urbs_free);
- result = usb_submit_urb(urb, GFP_ATOMIC);
+ result = usb_submit_urb(urb, mem_flags);
if (result) {
dev_err_console(port, "%s - error submitting urb: %d\n",
__func__, result);
@@ -172,10 +174,10 @@ retry:
return result;
}
/*
- * Try sending off another urb, unless in irq context (in which case
- * there will be no free urb).
+ * Try sending off another urb, unless called from completion handler
+ * (in which case there will be no free urb or no data).
*/
- if (!in_irq())
+ if (mem_flags != GFP_ATOMIC)
goto retry;
clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
@@ -205,7 +207,7 @@ int usb_serial_generic_write(struct tty_struct *tty,
return 0;
count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
- result = usb_serial_generic_write_start(port);
+ result = usb_serial_generic_write_start(port, GFP_KERNEL);
if (result)
return result;
@@ -409,7 +411,7 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
kfifo_reset_out(&port->write_fifo);
spin_unlock_irqrestore(&port->lock, flags);
} else {
- usb_serial_generic_write_start(port);
+ usb_serial_generic_write_start(port, GFP_ATOMIC);
}
usb_serial_port_softint(port);
@@ -598,7 +600,7 @@ int usb_serial_generic_resume(struct usb_serial *serial)
}
if (port->bulk_out_size) {
- r = usb_serial_generic_write_start(port);
+ r = usb_serial_generic_write_start(port, GFP_NOIO);
if (r < 0)
c++;
}