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: Oliver Neukum <oneukum@suse.de>
Acked-By: Matthias Urlichs <matthias@urlichs.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 5e8bf1b..a812698 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -247,10 +247,10 @@
 struct option_port_private {
 	/* Input endpoints and buffer for this port */
 	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 */
 	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 */
 
 	/* Settings for the port */
@@ -737,9 +737,10 @@
 
 static int option_startup(struct usb_serial *serial)
 {
-	int i, err;
+	int i, j, err;
 	struct usb_serial_port *port;
 	struct option_port_private *portdata;
+	u8 *buffer;
 
 	dbg("%s", __FUNCTION__);
 
@@ -753,6 +754,20 @@
 			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);
 
 		if (! port->interrupt_in_urb)
@@ -766,6 +781,16 @@
 	option_setup_urbs(serial);
 
 	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)
@@ -794,12 +819,14 @@
 		for (j = 0; j < N_IN_URB; j++) {
 			if (portdata->in_urbs[j]) {
 				usb_free_urb(portdata->in_urbs[j]);
+				free_page((unsigned long)portdata->in_buffer[j]);
 				portdata->in_urbs[j] = NULL;
 			}
 		}
 		for (j = 0; j < N_OUT_URB; j++) {
 			if (portdata->out_urbs[j]) {
 				usb_free_urb(portdata->out_urbs[j]);
+				kfree(portdata->out_buffer[j]);
 				portdata->out_urbs[j] = NULL;
 			}
 		}