Commit 2129c4e1 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman

USB: Sane memory allocation in option driver

The option driver
- violates DMA coherency rules
- allocates ~16500 bytes in one chunk
This patch splits out the buffers and uses __get_free_page() to avoid
higher order allocations.
Signed-off-by: default avatarOliver Neukum <oneukum@suse.de>
Acked-By: default avatarMatthias Urlichs <matthias@urlichs.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent bbc5d276
...@@ -247,10 +247,10 @@ static int debug; ...@@ -247,10 +247,10 @@ static int debug;
struct option_port_private { struct option_port_private {
/* Input endpoints and buffer for this port */ /* Input endpoints and buffer for this port */
struct urb *in_urbs[N_IN_URB]; struct urb *in_urbs[N_IN_URB];
char in_buffer[N_IN_URB][IN_BUFLEN]; u8 *in_buffer[N_IN_URB];
/* Output endpoints and buffer for this port */ /* Output endpoints and buffer for this port */
struct urb *out_urbs[N_OUT_URB]; struct urb *out_urbs[N_OUT_URB];
char out_buffer[N_OUT_URB][OUT_BUFLEN]; u8 *out_buffer[N_OUT_URB];
unsigned long out_busy; /* Bit vector of URBs in use */ unsigned long out_busy; /* Bit vector of URBs in use */
/* Settings for the port */ /* Settings for the port */
...@@ -737,9 +737,10 @@ static int option_send_setup(struct usb_serial_port *port) ...@@ -737,9 +737,10 @@ static int option_send_setup(struct usb_serial_port *port)
static int option_startup(struct usb_serial *serial) static int option_startup(struct usb_serial *serial)
{ {
int i, err; int i, j, err;
struct usb_serial_port *port; struct usb_serial_port *port;
struct option_port_private *portdata; struct option_port_private *portdata;
u8 *buffer;
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
...@@ -753,6 +754,20 @@ static int option_startup(struct usb_serial *serial) ...@@ -753,6 +754,20 @@ static int option_startup(struct usb_serial *serial)
return (1); return (1);
} }
for (j = 0; j < N_IN_URB; j++) {
buffer = (u8 *)__get_free_page(GFP_KERNEL);
if (!buffer)
goto bail_out_error;
portdata->in_buffer[j] = buffer;
}
for (j = 0; j < N_OUT_URB; j++) {
buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
if (!buffer)
goto bail_out_error2;
portdata->out_buffer[j] = buffer;
}
usb_set_serial_port_data(port, portdata); usb_set_serial_port_data(port, portdata);
if (! port->interrupt_in_urb) if (! port->interrupt_in_urb)
...@@ -766,6 +781,16 @@ static int option_startup(struct usb_serial *serial) ...@@ -766,6 +781,16 @@ static int option_startup(struct usb_serial *serial)
option_setup_urbs(serial); option_setup_urbs(serial);
return (0); return (0);
bail_out_error2:
for (j = 0; j < N_OUT_URB; j++)
kfree(portdata->out_buffer[j]);
bail_out_error:
for (j = 0; j < N_IN_URB; j++)
if (portdata->in_buffer[j])
free_page((unsigned long)portdata->in_buffer[j]);
kfree(portdata);
return 1;
} }
static void option_shutdown(struct usb_serial *serial) static void option_shutdown(struct usb_serial *serial)
...@@ -794,12 +819,14 @@ static void option_shutdown(struct usb_serial *serial) ...@@ -794,12 +819,14 @@ static void option_shutdown(struct usb_serial *serial)
for (j = 0; j < N_IN_URB; j++) { for (j = 0; j < N_IN_URB; j++) {
if (portdata->in_urbs[j]) { if (portdata->in_urbs[j]) {
usb_free_urb(portdata->in_urbs[j]); usb_free_urb(portdata->in_urbs[j]);
free_page((unsigned long)portdata->in_buffer[j]);
portdata->in_urbs[j] = NULL; portdata->in_urbs[j] = NULL;
} }
} }
for (j = 0; j < N_OUT_URB; j++) { for (j = 0; j < N_OUT_URB; j++) {
if (portdata->out_urbs[j]) { if (portdata->out_urbs[j]) {
usb_free_urb(portdata->out_urbs[j]); usb_free_urb(portdata->out_urbs[j]);
kfree(portdata->out_buffer[j]);
portdata->out_urbs[j] = NULL; portdata->out_urbs[j] = NULL;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment