aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.de>2008-02-01 07:58:52 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-21 18:38:48 -0500
commit2129c4e1b4469e1f9711a54e97e8ddf8b26bb62d (patch)
tree90b58e9648ebff476c90ce7c3f28a0c832396e76 /drivers
parentbbc5d276ec1e24d48f794dae1c4bdfc1512f65d5 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/serial/option.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 5e8bf1bc1e50..a8126988efe6 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -247,10 +247,10 @@ static int debug;
247struct option_port_private { 247struct option_port_private {
248 /* Input endpoints and buffer for this port */ 248 /* Input endpoints and buffer for this port */
249 struct urb *in_urbs[N_IN_URB]; 249 struct urb *in_urbs[N_IN_URB];
250 char in_buffer[N_IN_URB][IN_BUFLEN]; 250 u8 *in_buffer[N_IN_URB];
251 /* Output endpoints and buffer for this port */ 251 /* Output endpoints and buffer for this port */
252 struct urb *out_urbs[N_OUT_URB]; 252 struct urb *out_urbs[N_OUT_URB];
253 char out_buffer[N_OUT_URB][OUT_BUFLEN]; 253 u8 *out_buffer[N_OUT_URB];
254 unsigned long out_busy; /* Bit vector of URBs in use */ 254 unsigned long out_busy; /* Bit vector of URBs in use */
255 255
256 /* Settings for the port */ 256 /* Settings for the port */
@@ -737,9 +737,10 @@ static int option_send_setup(struct usb_serial_port *port)
737 737
738static int option_startup(struct usb_serial *serial) 738static int option_startup(struct usb_serial *serial)
739{ 739{
740 int i, err; 740 int i, j, err;
741 struct usb_serial_port *port; 741 struct usb_serial_port *port;
742 struct option_port_private *portdata; 742 struct option_port_private *portdata;
743 u8 *buffer;
743 744
744 dbg("%s", __FUNCTION__); 745 dbg("%s", __FUNCTION__);
745 746
@@ -753,6 +754,20 @@ static int option_startup(struct usb_serial *serial)
753 return (1); 754 return (1);
754 } 755 }
755 756
757 for (j = 0; j < N_IN_URB; j++) {
758 buffer = (u8 *)__get_free_page(GFP_KERNEL);
759 if (!buffer)
760 goto bail_out_error;
761 portdata->in_buffer[j] = buffer;
762 }
763
764 for (j = 0; j < N_OUT_URB; j++) {
765 buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
766 if (!buffer)
767 goto bail_out_error2;
768 portdata->out_buffer[j] = buffer;
769 }
770
756 usb_set_serial_port_data(port, portdata); 771 usb_set_serial_port_data(port, portdata);
757 772
758 if (! port->interrupt_in_urb) 773 if (! port->interrupt_in_urb)
@@ -766,6 +781,16 @@ static int option_startup(struct usb_serial *serial)
766 option_setup_urbs(serial); 781 option_setup_urbs(serial);
767 782
768 return (0); 783 return (0);
784
785bail_out_error2:
786 for (j = 0; j < N_OUT_URB; j++)
787 kfree(portdata->out_buffer[j]);
788bail_out_error:
789 for (j = 0; j < N_IN_URB; j++)
790 if (portdata->in_buffer[j])
791 free_page((unsigned long)portdata->in_buffer[j]);
792 kfree(portdata);
793 return 1;
769} 794}
770 795
771static void option_shutdown(struct usb_serial *serial) 796static void option_shutdown(struct usb_serial *serial)
@@ -794,12 +819,14 @@ static void option_shutdown(struct usb_serial *serial)
794 for (j = 0; j < N_IN_URB; j++) { 819 for (j = 0; j < N_IN_URB; j++) {
795 if (portdata->in_urbs[j]) { 820 if (portdata->in_urbs[j]) {
796 usb_free_urb(portdata->in_urbs[j]); 821 usb_free_urb(portdata->in_urbs[j]);
822 free_page((unsigned long)portdata->in_buffer[j]);
797 portdata->in_urbs[j] = NULL; 823 portdata->in_urbs[j] = NULL;
798 } 824 }
799 } 825 }
800 for (j = 0; j < N_OUT_URB; j++) { 826 for (j = 0; j < N_OUT_URB; j++) {
801 if (portdata->out_urbs[j]) { 827 if (portdata->out_urbs[j]) {
802 usb_free_urb(portdata->out_urbs[j]); 828 usb_free_urb(portdata->out_urbs[j]);
829 kfree(portdata->out_buffer[j]);
803 portdata->out_urbs[j] = NULL; 830 portdata->out_urbs[j] = NULL;
804 } 831 }
805 } 832 }