Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+30 −3
Original line number Diff line number Diff line
@@ -247,10 +247,10 @@ static int debug;
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_send_setup(struct usb_serial_port *port)

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 @@ static int option_startup(struct usb_serial *serial)
			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 @@ static int option_startup(struct usb_serial *serial)
	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 @@ static void option_shutdown(struct usb_serial *serial)
		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;
			}
		}