aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2013-08-13 07:27:37 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-14 16:51:02 -0400
commitbad41a5bf1775cdf6026d5a1b233bdc4853f27ca (patch)
treef3e75a02337bad3cd38ddfbf8d1fa37290dd9cb7
parent2fcd1c9b327c23414a5215a0fa53df9d75871a46 (diff)
USB: keyspan: fix port DMA-buffer allocations
Make sure port DMA-buffers are allocated separately from containing structure to prevent potential memory corruption on non-cache-coherent systems. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/serial/keyspan.c64
1 files changed, 56 insertions, 8 deletions
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 3d2ce56e1009..e731bbc166a0 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -50,6 +50,10 @@
50#define INSTAT_BUFLEN 32 50#define INSTAT_BUFLEN 32
51#define GLOCONT_BUFLEN 64 51#define GLOCONT_BUFLEN 64
52#define INDAT49W_BUFLEN 512 52#define INDAT49W_BUFLEN 512
53#define IN_BUFLEN 64
54#define OUT_BUFLEN 64
55#define INACK_BUFLEN 1
56#define OUTCONT_BUFLEN 64
53 57
54 /* Per device and per port private data */ 58 /* Per device and per port private data */
55struct keyspan_serial_private { 59struct keyspan_serial_private {
@@ -81,18 +85,18 @@ struct keyspan_port_private {
81 85
82 /* Input endpoints and buffer for this port */ 86 /* Input endpoints and buffer for this port */
83 struct urb *in_urbs[2]; 87 struct urb *in_urbs[2];
84 char in_buffer[2][64]; 88 char *in_buffer[2];
85 /* Output endpoints and buffer for this port */ 89 /* Output endpoints and buffer for this port */
86 struct urb *out_urbs[2]; 90 struct urb *out_urbs[2];
87 char out_buffer[2][64]; 91 char *out_buffer[2];
88 92
89 /* Input ack endpoint */ 93 /* Input ack endpoint */
90 struct urb *inack_urb; 94 struct urb *inack_urb;
91 char inack_buffer[1]; 95 char *inack_buffer;
92 96
93 /* Output control endpoint */ 97 /* Output control endpoint */
94 struct urb *outcont_urb; 98 struct urb *outcont_urb;
95 char outcont_buffer[64]; 99 char *outcont_buffer;
96 100
97 /* Settings for the port */ 101 /* Settings for the port */
98 int baud; 102 int baud;
@@ -2406,6 +2410,26 @@ static int keyspan_port_probe(struct usb_serial_port *port)
2406 if (!p_priv) 2410 if (!p_priv)
2407 return -ENOMEM; 2411 return -ENOMEM;
2408 2412
2413 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) {
2414 p_priv->in_buffer[i] = kzalloc(IN_BUFLEN, GFP_KERNEL);
2415 if (!p_priv->in_buffer[i])
2416 goto err_in_buffer;
2417 }
2418
2419 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) {
2420 p_priv->out_buffer[i] = kzalloc(OUT_BUFLEN, GFP_KERNEL);
2421 if (!p_priv->out_buffer[i])
2422 goto err_out_buffer;
2423 }
2424
2425 p_priv->inack_buffer = kzalloc(INACK_BUFLEN, GFP_KERNEL);
2426 if (!p_priv->inack_buffer)
2427 goto err_inack_buffer;
2428
2429 p_priv->outcont_buffer = kzalloc(OUTCONT_BUFLEN, GFP_KERNEL);
2430 if (!p_priv->outcont_buffer)
2431 goto err_outcont_buffer;
2432
2409 p_priv->device_details = d_details; 2433 p_priv->device_details = d_details;
2410 2434
2411 /* Setup values for the various callback routines */ 2435 /* Setup values for the various callback routines */
@@ -2418,7 +2442,8 @@ static int keyspan_port_probe(struct usb_serial_port *port)
2418 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) { 2442 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2419 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp, 2443 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2420 USB_DIR_IN, port, 2444 USB_DIR_IN, port,
2421 p_priv->in_buffer[i], 64, 2445 p_priv->in_buffer[i],
2446 IN_BUFLEN,
2422 cback->indat_callback); 2447 cback->indat_callback);
2423 } 2448 }
2424 /* outdat endpoints also have flip */ 2449 /* outdat endpoints also have flip */
@@ -2426,25 +2451,41 @@ static int keyspan_port_probe(struct usb_serial_port *port)
2426 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) { 2451 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2427 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp, 2452 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2428 USB_DIR_OUT, port, 2453 USB_DIR_OUT, port,
2429 p_priv->out_buffer[i], 64, 2454 p_priv->out_buffer[i],
2455 OUT_BUFLEN,
2430 cback->outdat_callback); 2456 cback->outdat_callback);
2431 } 2457 }
2432 /* inack endpoint */ 2458 /* inack endpoint */
2433 p_priv->inack_urb = keyspan_setup_urb(serial, 2459 p_priv->inack_urb = keyspan_setup_urb(serial,
2434 d_details->inack_endpoints[port_num], 2460 d_details->inack_endpoints[port_num],
2435 USB_DIR_IN, port, 2461 USB_DIR_IN, port,
2436 p_priv->inack_buffer, 1, 2462 p_priv->inack_buffer,
2463 INACK_BUFLEN,
2437 cback->inack_callback); 2464 cback->inack_callback);
2438 /* outcont endpoint */ 2465 /* outcont endpoint */
2439 p_priv->outcont_urb = keyspan_setup_urb(serial, 2466 p_priv->outcont_urb = keyspan_setup_urb(serial,
2440 d_details->outcont_endpoints[port_num], 2467 d_details->outcont_endpoints[port_num],
2441 USB_DIR_OUT, port, 2468 USB_DIR_OUT, port,
2442 p_priv->outcont_buffer, 64, 2469 p_priv->outcont_buffer,
2470 OUTCONT_BUFLEN,
2443 cback->outcont_callback); 2471 cback->outcont_callback);
2444 2472
2445 usb_set_serial_port_data(port, p_priv); 2473 usb_set_serial_port_data(port, p_priv);
2446 2474
2447 return 0; 2475 return 0;
2476
2477err_outcont_buffer:
2478 kfree(p_priv->inack_buffer);
2479err_inack_buffer:
2480 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
2481 kfree(p_priv->out_buffer[i]);
2482err_out_buffer:
2483 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
2484 kfree(p_priv->in_buffer[i]);
2485err_in_buffer:
2486 kfree(p_priv);
2487
2488 return -ENOMEM;
2448} 2489}
2449 2490
2450static int keyspan_port_remove(struct usb_serial_port *port) 2491static int keyspan_port_remove(struct usb_serial_port *port)
@@ -2468,6 +2509,13 @@ static int keyspan_port_remove(struct usb_serial_port *port)
2468 usb_free_urb(p_priv->out_urbs[i]); 2509 usb_free_urb(p_priv->out_urbs[i]);
2469 } 2510 }
2470 2511
2512 kfree(p_priv->outcont_buffer);
2513 kfree(p_priv->inack_buffer);
2514 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
2515 kfree(p_priv->out_buffer[i]);
2516 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
2517 kfree(p_priv->in_buffer[i]);
2518
2471 kfree(p_priv); 2519 kfree(p_priv);
2472 2520
2473 return 0; 2521 return 0;