mirror of https://gitee.com/openkylin/linux.git
[media] si470x: don't use buffer on the stack for USB transfers
You shouldn't use buffers allocated on the stack for USB transfers, always kmalloc them. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
This commit is contained in:
parent
0149a2e149
commit
567e2e9660
|
@ -137,6 +137,8 @@ MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
|
||||||
/* interrupt out endpoint 2 every 1 millisecond */
|
/* interrupt out endpoint 2 every 1 millisecond */
|
||||||
#define UNUSED_REPORT 23
|
#define UNUSED_REPORT 23
|
||||||
|
|
||||||
|
#define MAX_REPORT_SIZE 64
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
|
@ -208,7 +210,7 @@ MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
|
||||||
*/
|
*/
|
||||||
static int si470x_get_report(struct si470x_device *radio, void *buf, int size)
|
static int si470x_get_report(struct si470x_device *radio, void *buf, int size)
|
||||||
{
|
{
|
||||||
unsigned char *report = (unsigned char *) buf;
|
unsigned char *report = buf;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
retval = usb_control_msg(radio->usbdev,
|
retval = usb_control_msg(radio->usbdev,
|
||||||
|
@ -231,7 +233,7 @@ static int si470x_get_report(struct si470x_device *radio, void *buf, int size)
|
||||||
*/
|
*/
|
||||||
static int si470x_set_report(struct si470x_device *radio, void *buf, int size)
|
static int si470x_set_report(struct si470x_device *radio, void *buf, int size)
|
||||||
{
|
{
|
||||||
unsigned char *report = (unsigned char *) buf;
|
unsigned char *report = buf;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
retval = usb_control_msg(radio->usbdev,
|
retval = usb_control_msg(radio->usbdev,
|
||||||
|
@ -254,15 +256,14 @@ static int si470x_set_report(struct si470x_device *radio, void *buf, int size)
|
||||||
*/
|
*/
|
||||||
int si470x_get_register(struct si470x_device *radio, int regnr)
|
int si470x_get_register(struct si470x_device *radio, int regnr)
|
||||||
{
|
{
|
||||||
unsigned char buf[REGISTER_REPORT_SIZE];
|
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
buf[0] = REGISTER_REPORT(regnr);
|
radio->usb_buf[0] = REGISTER_REPORT(regnr);
|
||||||
|
|
||||||
retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
|
retval = si470x_get_report(radio, radio->usb_buf, REGISTER_REPORT_SIZE);
|
||||||
|
|
||||||
if (retval >= 0)
|
if (retval >= 0)
|
||||||
radio->registers[regnr] = get_unaligned_be16(&buf[1]);
|
radio->registers[regnr] = get_unaligned_be16(&radio->usb_buf[1]);
|
||||||
|
|
||||||
return (retval < 0) ? -EINVAL : 0;
|
return (retval < 0) ? -EINVAL : 0;
|
||||||
}
|
}
|
||||||
|
@ -273,13 +274,12 @@ int si470x_get_register(struct si470x_device *radio, int regnr)
|
||||||
*/
|
*/
|
||||||
int si470x_set_register(struct si470x_device *radio, int regnr)
|
int si470x_set_register(struct si470x_device *radio, int regnr)
|
||||||
{
|
{
|
||||||
unsigned char buf[REGISTER_REPORT_SIZE];
|
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
buf[0] = REGISTER_REPORT(regnr);
|
radio->usb_buf[0] = REGISTER_REPORT(regnr);
|
||||||
put_unaligned_be16(radio->registers[regnr], &buf[1]);
|
put_unaligned_be16(radio->registers[regnr], &radio->usb_buf[1]);
|
||||||
|
|
||||||
retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
|
retval = si470x_set_report(radio, radio->usb_buf, REGISTER_REPORT_SIZE);
|
||||||
|
|
||||||
return (retval < 0) ? -EINVAL : 0;
|
return (retval < 0) ? -EINVAL : 0;
|
||||||
}
|
}
|
||||||
|
@ -295,18 +295,17 @@ int si470x_set_register(struct si470x_device *radio, int regnr)
|
||||||
*/
|
*/
|
||||||
static int si470x_get_all_registers(struct si470x_device *radio)
|
static int si470x_get_all_registers(struct si470x_device *radio)
|
||||||
{
|
{
|
||||||
unsigned char buf[ENTIRE_REPORT_SIZE];
|
|
||||||
int retval;
|
int retval;
|
||||||
unsigned char regnr;
|
unsigned char regnr;
|
||||||
|
|
||||||
buf[0] = ENTIRE_REPORT;
|
radio->usb_buf[0] = ENTIRE_REPORT;
|
||||||
|
|
||||||
retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
|
retval = si470x_get_report(radio, radio->usb_buf, ENTIRE_REPORT_SIZE);
|
||||||
|
|
||||||
if (retval >= 0)
|
if (retval >= 0)
|
||||||
for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
|
for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
|
||||||
radio->registers[regnr] = get_unaligned_be16(
|
radio->registers[regnr] = get_unaligned_be16(
|
||||||
&buf[regnr * RADIO_REGISTER_SIZE + 1]);
|
&radio->usb_buf[regnr * RADIO_REGISTER_SIZE + 1]);
|
||||||
|
|
||||||
return (retval < 0) ? -EINVAL : 0;
|
return (retval < 0) ? -EINVAL : 0;
|
||||||
}
|
}
|
||||||
|
@ -323,14 +322,13 @@ static int si470x_get_all_registers(struct si470x_device *radio)
|
||||||
static int si470x_set_led_state(struct si470x_device *radio,
|
static int si470x_set_led_state(struct si470x_device *radio,
|
||||||
unsigned char led_state)
|
unsigned char led_state)
|
||||||
{
|
{
|
||||||
unsigned char buf[LED_REPORT_SIZE];
|
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
buf[0] = LED_REPORT;
|
radio->usb_buf[0] = LED_REPORT;
|
||||||
buf[1] = LED_COMMAND;
|
radio->usb_buf[1] = LED_COMMAND;
|
||||||
buf[2] = led_state;
|
radio->usb_buf[2] = led_state;
|
||||||
|
|
||||||
retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
|
retval = si470x_set_report(radio, radio->usb_buf, LED_REPORT_SIZE);
|
||||||
|
|
||||||
return (retval < 0) ? -EINVAL : 0;
|
return (retval < 0) ? -EINVAL : 0;
|
||||||
}
|
}
|
||||||
|
@ -346,19 +344,18 @@ static int si470x_set_led_state(struct si470x_device *radio,
|
||||||
*/
|
*/
|
||||||
static int si470x_get_scratch_page_versions(struct si470x_device *radio)
|
static int si470x_get_scratch_page_versions(struct si470x_device *radio)
|
||||||
{
|
{
|
||||||
unsigned char buf[SCRATCH_REPORT_SIZE];
|
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
buf[0] = SCRATCH_REPORT;
|
radio->usb_buf[0] = SCRATCH_REPORT;
|
||||||
|
|
||||||
retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
|
retval = si470x_get_report(radio, radio->usb_buf, SCRATCH_REPORT_SIZE);
|
||||||
|
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
dev_warn(&radio->intf->dev, "si470x_get_scratch: "
|
dev_warn(&radio->intf->dev, "si470x_get_scratch: "
|
||||||
"si470x_get_report returned %d\n", retval);
|
"si470x_get_report returned %d\n", retval);
|
||||||
else {
|
else {
|
||||||
radio->software_version = buf[1];
|
radio->software_version = radio->usb_buf[1];
|
||||||
radio->hardware_version = buf[2];
|
radio->hardware_version = radio->usb_buf[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (retval < 0) ? -EINVAL : 0;
|
return (retval < 0) ? -EINVAL : 0;
|
||||||
|
@ -509,6 +506,7 @@ static void si470x_usb_release(struct v4l2_device *v4l2_dev)
|
||||||
v4l2_device_unregister(&radio->v4l2_dev);
|
v4l2_device_unregister(&radio->v4l2_dev);
|
||||||
kfree(radio->int_in_buffer);
|
kfree(radio->int_in_buffer);
|
||||||
kfree(radio->buffer);
|
kfree(radio->buffer);
|
||||||
|
kfree(radio->usb_buf);
|
||||||
kfree(radio);
|
kfree(radio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,6 +591,11 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto err_initial;
|
goto err_initial;
|
||||||
}
|
}
|
||||||
|
radio->usb_buf = kmalloc(MAX_REPORT_SIZE, GFP_KERNEL);
|
||||||
|
if (radio->usb_buf == NULL) {
|
||||||
|
retval = -ENOMEM;
|
||||||
|
goto err_radio;
|
||||||
|
}
|
||||||
radio->usbdev = interface_to_usbdev(intf);
|
radio->usbdev = interface_to_usbdev(intf);
|
||||||
radio->intf = intf;
|
radio->intf = intf;
|
||||||
radio->band = 1; /* Default to 76 - 108 MHz */
|
radio->band = 1; /* Default to 76 - 108 MHz */
|
||||||
|
@ -612,7 +615,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
|
||||||
if (!radio->int_in_endpoint) {
|
if (!radio->int_in_endpoint) {
|
||||||
dev_info(&intf->dev, "could not find interrupt in endpoint\n");
|
dev_info(&intf->dev, "could not find interrupt in endpoint\n");
|
||||||
retval = -EIO;
|
retval = -EIO;
|
||||||
goto err_radio;
|
goto err_usbbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int_end_size = le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize);
|
int_end_size = le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize);
|
||||||
|
@ -621,7 +624,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
|
||||||
if (!radio->int_in_buffer) {
|
if (!radio->int_in_buffer) {
|
||||||
dev_info(&intf->dev, "could not allocate int_in_buffer");
|
dev_info(&intf->dev, "could not allocate int_in_buffer");
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto err_radio;
|
goto err_usbbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
|
radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
|
@ -743,6 +746,8 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
|
||||||
usb_free_urb(radio->int_in_urb);
|
usb_free_urb(radio->int_in_urb);
|
||||||
err_intbuffer:
|
err_intbuffer:
|
||||||
kfree(radio->int_in_buffer);
|
kfree(radio->int_in_buffer);
|
||||||
|
err_usbbuf:
|
||||||
|
kfree(radio->usb_buf);
|
||||||
err_radio:
|
err_radio:
|
||||||
kfree(radio);
|
kfree(radio);
|
||||||
err_initial:
|
err_initial:
|
||||||
|
|
|
@ -167,6 +167,7 @@ struct si470x_device {
|
||||||
/* reference to USB and video device */
|
/* reference to USB and video device */
|
||||||
struct usb_device *usbdev;
|
struct usb_device *usbdev;
|
||||||
struct usb_interface *intf;
|
struct usb_interface *intf;
|
||||||
|
char *usb_buf;
|
||||||
|
|
||||||
/* Interrupt endpoint handling */
|
/* Interrupt endpoint handling */
|
||||||
char *int_in_buffer;
|
char *int_in_buffer;
|
||||||
|
|
Loading…
Reference in New Issue