[media] technisat-usb2: don't do DMA on the stack
authorMauro Carvalho Chehab <mchehab@osg.samsung.com>
Sat, 27 Feb 2016 10:51:10 +0000 (07:51 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Tue, 1 Mar 2016 15:00:34 +0000 (12:00 -0300)
As warned by smatch:
drivers/media/usb/dvb-usb/technisat-usb2.c:263 technisat_usb2_set_led() error: doing dma on the stack (led)
drivers/media/usb/dvb-usb/technisat-usb2.c:280 technisat_usb2_set_led_timer() error: doing dma on the stack (&b)
drivers/media/usb/dvb-usb/technisat-usb2.c:341 technisat_usb2_identify_state() error: doing dma on the stack (version)
drivers/media/usb/dvb-usb/technisat-usb2.c:609 technisat_usb2_get_ir() error: doing dma on the stack (buf)
drivers/media/usb/dvb-usb/technisat-usb2.c:619 technisat_usb2_get_ir() error: doing dma on the stack (buf)

Create a buffer at the device state and use it for all the DMA
transfers.

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/usb/dvb-usb/technisat-usb2.c

index 51487d2..d9f3262 100644 (file)
@@ -60,6 +60,8 @@ struct technisat_usb2_state {
        u8 power_state;
 
        u16 last_scan_code;
+
+       u8 buf[64];
 };
 
 /* debug print helpers */
@@ -220,19 +222,19 @@ enum technisat_usb2_led_state {
        TECH_LED_UNDEFINED
 };
 
-static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum technisat_usb2_led_state state)
+static int technisat_usb2_set_led(struct dvb_usb_device *d, int red,
+                                 enum technisat_usb2_led_state st)
 {
+       struct technisat_usb2_state *state = d->priv;
+       u8 *led = state->buf;
        int ret;
 
-       u8 led[8] = {
-               red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
-               0
-       };
+       led[0] = red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST;
 
-       if (disable_led_control && state != TECH_LED_OFF)
+       if (disable_led_control && st != TECH_LED_OFF)
                return 0;
 
-       switch (state) {
+       switch (st) {
        case TECH_LED_ON:
                led[1] = 0x82;
                break;
@@ -263,7 +265,7 @@ static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum techni
                red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
                USB_TYPE_VENDOR | USB_DIR_OUT,
                0, 0,
-               led, sizeof(led), 500);
+               led, 8, 500);
 
        mutex_unlock(&d->i2c_mutex);
        return ret;
@@ -271,8 +273,11 @@ static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum techni
 
 static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 green)
 {
+       struct technisat_usb2_state *state = d->priv;
+       u8 *b = state->buf;
        int ret;
-       u8 b = 0;
+
+       b[0] = 0;
 
        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
                return -EAGAIN;
@@ -281,7 +286,7 @@ static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 gre
                SET_LED_TIMER_DIVIDER_VENDOR_REQUEST,
                USB_TYPE_VENDOR | USB_DIR_OUT,
                (red << 8) | green, 0,
-               &b, 1, 500);
+               b, 1, 500);
 
        mutex_unlock(&d->i2c_mutex);
 
@@ -328,7 +333,11 @@ static int technisat_usb2_identify_state(struct usb_device *udev,
                struct dvb_usb_device_description **desc, int *cold)
 {
        int ret;
-       u8 version[3];
+       u8 *version;
+
+       version = kmalloc(3, GFP_KERNEL);
+       if (!version)
+               return -ENOMEM;
 
        /* first select the interface */
        if (usb_set_interface(udev, 0, 1) != 0)
@@ -342,7 +351,7 @@ static int technisat_usb2_identify_state(struct usb_device *udev,
                GET_VERSION_INFO_VENDOR_REQUEST,
                USB_TYPE_VENDOR | USB_DIR_IN,
                0, 0,
-               version, sizeof(version), 500);
+               version, 3, 500);
 
        if (ret < 0)
                *cold = 1;
@@ -351,6 +360,8 @@ static int technisat_usb2_identify_state(struct usb_device *udev,
                *cold = 0;
        }
 
+       kfree(version);
+
        return 0;
 }
 
@@ -594,7 +605,9 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
 
 static int technisat_usb2_get_ir(struct dvb_usb_device *d)
 {
-       u8 buf[62], *b;
+       struct technisat_usb2_state *state = d->priv;
+       u8 *buf = state->buf;
+       u8 *b;
        int ret;
        struct ir_raw_event ev;
 
@@ -620,7 +633,7 @@ static int technisat_usb2_get_ir(struct dvb_usb_device *d)
                        GET_IR_DATA_VENDOR_REQUEST,
                        USB_TYPE_VENDOR | USB_DIR_IN,
                        0x8080, 0,
-                       buf, sizeof(buf), 500);
+                       buf, 62, 500);
 
 unlock:
        mutex_unlock(&d->i2c_mutex);