[media] flexcop-usb: don't use stack for DMA
authorMauro Carvalho Chehab <mchehab@s-opensource.com>
Mon, 10 Oct 2016 10:55:54 +0000 (07:55 -0300)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Fri, 14 Oct 2016 15:52:29 +0000 (12:52 -0300)
The USB control messages require DMA to work. We cannot pass
a stack-allocated buffer, as it is not warranted that the
stack would be into a DMA enabled area.

While here, remove a dead function calling usb_control_msg().

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
drivers/media/usb/b2c2/flexcop-usb.c
drivers/media/usb/b2c2/flexcop-usb.h

index d4bdba60b0f71436065e4884d5622cc34dffbfe6..52bc42da8a4ce4dde4848c3a2497c5b286b6ae8b 100644 (file)
@@ -73,23 +73,34 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI,
        u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
        u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |
                (read ? 0x80 : 0);
+       int ret;
+
+       mutex_lock(&fc_usb->data_mutex);
+       if (!read)
+               memcpy(fc_usb->data, val, sizeof(*val));
 
-       int len = usb_control_msg(fc_usb->udev,
+       ret = usb_control_msg(fc_usb->udev,
                        read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
                        request,
                        request_type, /* 0xc0 read or 0x40 write */
                        wAddress,
                        0,
-                       val,
+                       fc_usb->data,
                        sizeof(u32),
                        B2C2_WAIT_FOR_OPERATION_RDW * HZ);
 
-       if (len != sizeof(u32)) {
+       if (ret != sizeof(u32)) {
                err("error while %s dword from %d (%d).", read ? "reading" :
                                "writing", wAddress, wRegOffsPCI);
-               return -EIO;
+               if (ret >= 0)
+                       ret = -EIO;
        }
-       return 0;
+
+       if (read && ret >= 0)
+               memcpy(val, fc_usb->data, sizeof(*val));
+       mutex_unlock(&fc_usb->data_mutex);
+
+       return ret;
 }
 /*
  * DKT 010817 - add support for V8 memory read/write and flash update
@@ -100,9 +111,14 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
 {
        u8 request_type = USB_TYPE_VENDOR;
        u16 wIndex;
-       int nWaitTime, pipe, len;
+       int nWaitTime, pipe, ret;
        wIndex = page << 8;
 
+       if (buflen > sizeof(fc_usb->data)) {
+               err("Buffer size bigger than max URB control message\n");
+               return -EIO;
+       }
+
        switch (req) {
        case B2C2_USB_READ_V8_MEM:
                nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
@@ -127,17 +143,32 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
        deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req,
                        wAddress, wIndex, buflen);
 
-       len = usb_control_msg(fc_usb->udev, pipe,
+       mutex_lock(&fc_usb->data_mutex);
+
+       if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
+               memcpy(fc_usb->data, pbBuffer, buflen);
+
+       ret = usb_control_msg(fc_usb->udev, pipe,
                        req,
                        request_type,
                        wAddress,
                        wIndex,
-                       pbBuffer,
+                       fc_usb->data,
                        buflen,
                        nWaitTime * HZ);
+       if (ret != buflen)
+               ret = -EIO;
+
+       if (ret >= 0) {
+               ret = 0;
+               if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+                       memcpy(pbBuffer, fc_usb->data, buflen);
+       }
 
-       debug_dump(pbBuffer, len, deb_v8);
-       return len == buflen ? 0 : -EIO;
+       mutex_unlock(&fc_usb->data_mutex);
+
+       debug_dump(pbBuffer, ret, deb_v8);
+       return ret;
 }
 
 #define bytes_left_to_read_on_page(paddr,buflen) \
@@ -196,29 +227,6 @@ static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)
                fc->dvb_adapter.proposed_mac, 6);
 }
 
-#if 0
-static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
-               flexcop_usb_utility_function_t func, u8 extra, u16 wIndex,
-               u16 buflen, u8 *pvBuffer)
-{
-       u16 wValue;
-       u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
-       int nWaitTime = 2,
-           pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len;
-       wValue = (func << 8) | extra;
-
-       len = usb_control_msg(fc_usb->udev,pipe,
-                       B2C2_USB_UTILITY,
-                       request_type,
-                       wValue,
-                       wIndex,
-                       pvBuffer,
-                       buflen,
-                       nWaitTime * HZ);
-       return len == buflen ? 0 : -EIO;
-}
-#endif
-
 /* usb i2c stuff */
 static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
                flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
@@ -226,9 +234,14 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
 {
        struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
        u16 wValue, wIndex;
-       int nWaitTime,pipe,len;
+       int nWaitTime, pipe, ret;
        u8 request_type = USB_TYPE_VENDOR;
 
+       if (buflen > sizeof(fc_usb->data)) {
+               err("Buffer size bigger than max URB control message\n");
+               return -EIO;
+       }
+
        switch (func) {
        case USB_FUNC_I2C_WRITE:
        case USB_FUNC_I2C_MULTIWRITE:
@@ -257,15 +270,32 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
                        wValue & 0xff, wValue >> 8,
                        wIndex & 0xff, wIndex >> 8);
 
-       len = usb_control_msg(fc_usb->udev,pipe,
+       mutex_lock(&fc_usb->data_mutex);
+
+       if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
+               memcpy(fc_usb->data, buf, buflen);
+
+       ret = usb_control_msg(fc_usb->udev, pipe,
                        req,
                        request_type,
                        wValue,
                        wIndex,
-                       buf,
+                       fc_usb->data,
                        buflen,
                        nWaitTime * HZ);
-       return len == buflen ? 0 : -EREMOTEIO;
+
+       if (ret != buflen)
+               ret = -EIO;
+
+       if (ret >= 0) {
+               ret = 0;
+               if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+                       memcpy(buf, fc_usb->data, buflen);
+       }
+
+       mutex_unlock(&fc_usb->data_mutex);
+
+       return 0;
 }
 
 /* actual bus specific access functions,
@@ -516,6 +546,7 @@ static int flexcop_usb_probe(struct usb_interface *intf,
        /* general flexcop init */
        fc_usb = fc->bus_specific;
        fc_usb->fc_dev = fc;
+       mutex_init(&fc_usb->data_mutex);
 
        fc->read_ibi_reg  = flexcop_usb_read_ibi_reg;
        fc->write_ibi_reg = flexcop_usb_write_ibi_reg;
index 92529a9c4475b71ca5381670ceb16d5ccfcd079c..25ad43166e78c759226c603e66fa6e6b81a361f8 100644 (file)
@@ -29,6 +29,10 @@ struct flexcop_usb {
 
        u8 tmp_buffer[1023+190];
        int tmp_buffer_length;
+
+       /* for URB control messages */
+       u8 data[80];
+       struct mutex data_mutex;
 };
 
 #if 0