diff options
author | Johan Hovold <jhovold@gmail.com> | 2009-12-28 17:01:48 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 17:53:51 -0500 |
commit | 0954644bf5a5a2281746516ce0f5df988d504c31 (patch) | |
tree | 78e49914f5988e768f82928b8e53582e81ee9d55 | |
parent | 52372ccb5a19d35b68b79118fafdced0c12f0ec9 (diff) |
USB: cypress_m8: fix DMA buffer on stack
Cc: Lonnie Mendez <dignome@gmail.com>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/serial/cypress_m8.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 60c200230bc8..1ce1a3a3e21a 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -344,7 +344,8 @@ static int cypress_serial_control(struct tty_struct *tty, | |||
344 | { | 344 | { |
345 | int new_baudrate = 0, retval = 0, tries = 0; | 345 | int new_baudrate = 0, retval = 0, tries = 0; |
346 | struct cypress_private *priv; | 346 | struct cypress_private *priv; |
347 | __u8 feature_buffer[5]; | 347 | u8 *feature_buffer; |
348 | const unsigned int feature_len = 5; | ||
348 | unsigned long flags; | 349 | unsigned long flags; |
349 | 350 | ||
350 | dbg("%s", __func__); | 351 | dbg("%s", __func__); |
@@ -354,6 +355,10 @@ static int cypress_serial_control(struct tty_struct *tty, | |||
354 | if (!priv->comm_is_ok) | 355 | if (!priv->comm_is_ok) |
355 | return -ENODEV; | 356 | return -ENODEV; |
356 | 357 | ||
358 | feature_buffer = kcalloc(feature_len, sizeof(u8), GFP_KERNEL); | ||
359 | if (!feature_buffer) | ||
360 | return -ENOMEM; | ||
361 | |||
357 | switch (cypress_request_type) { | 362 | switch (cypress_request_type) { |
358 | case CYPRESS_SET_CONFIG: | 363 | case CYPRESS_SET_CONFIG: |
359 | /* 0 means 'Hang up' so doesn't change the true bit rate */ | 364 | /* 0 means 'Hang up' so doesn't change the true bit rate */ |
@@ -370,7 +375,6 @@ static int cypress_serial_control(struct tty_struct *tty, | |||
370 | dbg("%s - baud rate is being sent as %d", | 375 | dbg("%s - baud rate is being sent as %d", |
371 | __func__, new_baudrate); | 376 | __func__, new_baudrate); |
372 | 377 | ||
373 | memset(feature_buffer, 0, sizeof(feature_buffer)); | ||
374 | /* fill the feature_buffer with new configuration */ | 378 | /* fill the feature_buffer with new configuration */ |
375 | *((u_int32_t *)feature_buffer) = new_baudrate; | 379 | *((u_int32_t *)feature_buffer) = new_baudrate; |
376 | feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */ | 380 | feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */ |
@@ -394,15 +398,15 @@ static int cypress_serial_control(struct tty_struct *tty, | |||
394 | HID_REQ_SET_REPORT, | 398 | HID_REQ_SET_REPORT, |
395 | USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, | 399 | USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, |
396 | 0x0300, 0, feature_buffer, | 400 | 0x0300, 0, feature_buffer, |
397 | sizeof(feature_buffer), 500); | 401 | feature_len, 500); |
398 | 402 | ||
399 | if (tries++ >= 3) | 403 | if (tries++ >= 3) |
400 | break; | 404 | break; |
401 | 405 | ||
402 | } while (retval != sizeof(feature_buffer) && | 406 | } while (retval != feature_len && |
403 | retval != -ENODEV); | 407 | retval != -ENODEV); |
404 | 408 | ||
405 | if (retval != sizeof(feature_buffer)) { | 409 | if (retval != feature_len) { |
406 | dev_err(&port->dev, "%s - failed sending serial " | 410 | dev_err(&port->dev, "%s - failed sending serial " |
407 | "line settings - %d\n", __func__, retval); | 411 | "line settings - %d\n", __func__, retval); |
408 | cypress_set_dead(port); | 412 | cypress_set_dead(port); |
@@ -422,30 +426,28 @@ static int cypress_serial_control(struct tty_struct *tty, | |||
422 | /* Not implemented for this device, | 426 | /* Not implemented for this device, |
423 | and if we try to do it we're likely | 427 | and if we try to do it we're likely |
424 | to crash the hardware. */ | 428 | to crash the hardware. */ |
425 | return -ENOTTY; | 429 | retval = -ENOTTY; |
430 | goto out; | ||
426 | } | 431 | } |
427 | dbg("%s - retreiving serial line settings", __func__); | 432 | dbg("%s - retreiving serial line settings", __func__); |
428 | /* set initial values in feature buffer */ | ||
429 | memset(feature_buffer, 0, sizeof(feature_buffer)); | ||
430 | |||
431 | do { | 433 | do { |
432 | retval = usb_control_msg(port->serial->dev, | 434 | retval = usb_control_msg(port->serial->dev, |
433 | usb_rcvctrlpipe(port->serial->dev, 0), | 435 | usb_rcvctrlpipe(port->serial->dev, 0), |
434 | HID_REQ_GET_REPORT, | 436 | HID_REQ_GET_REPORT, |
435 | USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS, | 437 | USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS, |
436 | 0x0300, 0, feature_buffer, | 438 | 0x0300, 0, feature_buffer, |
437 | sizeof(feature_buffer), 500); | 439 | feature_len, 500); |
438 | 440 | ||
439 | if (tries++ >= 3) | 441 | if (tries++ >= 3) |
440 | break; | 442 | break; |
441 | } while (retval != sizeof(feature_buffer) | 443 | } while (retval != feature_len |
442 | && retval != -ENODEV); | 444 | && retval != -ENODEV); |
443 | 445 | ||
444 | if (retval != sizeof(feature_buffer)) { | 446 | if (retval != feature_len) { |
445 | dev_err(&port->dev, "%s - failed to retrieve serial " | 447 | dev_err(&port->dev, "%s - failed to retrieve serial " |
446 | "line settings - %d\n", __func__, retval); | 448 | "line settings - %d\n", __func__, retval); |
447 | cypress_set_dead(port); | 449 | cypress_set_dead(port); |
448 | return retval; | 450 | goto out; |
449 | } else { | 451 | } else { |
450 | spin_lock_irqsave(&priv->lock, flags); | 452 | spin_lock_irqsave(&priv->lock, flags); |
451 | /* store the config in one byte, and later | 453 | /* store the config in one byte, and later |
@@ -458,7 +460,8 @@ static int cypress_serial_control(struct tty_struct *tty, | |||
458 | spin_lock_irqsave(&priv->lock, flags); | 460 | spin_lock_irqsave(&priv->lock, flags); |
459 | ++priv->cmd_count; | 461 | ++priv->cmd_count; |
460 | spin_unlock_irqrestore(&priv->lock, flags); | 462 | spin_unlock_irqrestore(&priv->lock, flags); |
461 | 463 | out: | |
464 | kfree(feature_buffer); | ||
462 | return retval; | 465 | return retval; |
463 | } /* cypress_serial_control */ | 466 | } /* cypress_serial_control */ |
464 | 467 | ||