mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-04-13 10:47:31 +07:00
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>
This commit is contained in:
parent
bbc5d276ec
commit
2129c4e1b4
@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user