static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id)
 {
-       return ctrl->data + id * ctrl->info->size;
+       return ctrl->uvc_data + id * ctrl->info->size;
 }
 
 static inline int uvc_test_bit(const __u8 *data, int bit)
  * Control and mapping handling
  */
 
-static void uvc_ctrl_add_ctrl(struct uvc_device *dev,
+static int uvc_ctrl_add_ctrl(struct uvc_device *dev,
        struct uvc_control_info *info)
 {
        struct uvc_entity *entity;
        struct uvc_control *ctrl = NULL;
-       int ret, found = 0;
+       int ret = 0, found = 0;
        unsigned int i;
+       u8 *uvc_info;
+       u8 *uvc_data;
 
        list_for_each_entry(entity, &dev->entities, list) {
                if (!uvc_entity_match_guid(entity, info->entity))
        }
 
        if (!found)
-               return;
+               return 0;
+
+       uvc_data = kmalloc(info->size * UVC_CTRL_DATA_LAST + 1, GFP_KERNEL);
+       if (uvc_data == NULL)
+               return -ENOMEM;
+
+       uvc_info = uvc_data + info->size * UVC_CTRL_DATA_LAST;
 
        if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) {
                /* Check if the device control information and length match
                 * the user supplied information.
                 */
-               __le16 size;
-               __u8 _info;
-
                ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id,
-                       dev->intfnum, info->selector, (__u8 *)&size, 2);
+                                    dev->intfnum, info->selector, uvc_data, 2);
                if (ret < 0) {
                        uvc_trace(UVC_TRACE_CONTROL,
                                "GET_LEN failed on control %pUl/%u (%d).\n",
                                info->entity, info->selector, ret);
-                       return;
+                       goto done;
                }
 
-               if (info->size != le16_to_cpu(size)) {
+               if (info->size != le16_to_cpu(*(__le16 *)uvc_data)) {
                        uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u size "
                                "doesn't match user supplied value.\n",
                                info->entity, info->selector);
-                       return;
+                       ret = -EINVAL;
+                       goto done;
                }
 
                ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id,
-                                    dev->intfnum, info->selector, &_info, 1);
+                                    dev->intfnum, info->selector, uvc_info, 1);
                if (ret < 0) {
                        uvc_trace(UVC_TRACE_CONTROL,
                                "GET_INFO failed on control %pUl/%u (%d).\n",
                                info->entity, info->selector, ret);
-                       return;
+                       goto done;
                }
 
                if (((info->flags & UVC_CONTROL_GET_CUR) &&
-                   !(_info & UVC_CONTROL_CAP_GET)) ||
+                   !(*uvc_info & UVC_CONTROL_CAP_GET)) ||
                    ((info->flags & UVC_CONTROL_SET_CUR) &&
-                   !(_info & UVC_CONTROL_CAP_SET))) {
+                   !(*uvc_info & UVC_CONTROL_CAP_SET))) {
                        uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u flags "
                                "don't match supported operations.\n",
                                info->entity, info->selector);
-                       return;
+                       ret = -EINVAL;
+                       goto done;
                }
        }
 
        ctrl->info = info;
-       ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_DATA_LAST, GFP_KERNEL);
+       ctrl->uvc_data = uvc_data;
+       ctrl->uvc_info = uvc_info;
+
        uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s "
                "entity %u\n", ctrl->info->entity, ctrl->info->selector,
                dev->udev->devpath, entity->id);
+
+done:
+       if (ret < 0)
+               kfree(uvc_data);
+
+       return ret;
 }
 
 /*
 
        list_for_each_entry(entity, &dev->entities, list) {
                for (i = 0; i < entity->ncontrols; ++i)
-                       kfree(entity->controls[i].data);
+                       kfree(entity->controls[i].uvc_data);
 
                kfree(entity->controls);
        }