summaryrefslogtreecommitdiffstats
path: root/drivers/media/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb')
-rw-r--r--drivers/media/usb/b2c2/flexcop-usb.c9
-rw-r--r--drivers/media/usb/cx231xx/cx231xx.h2
-rw-r--r--drivers/media/usb/dvb-usb-v2/anysee.c21
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb.h34
-rw-r--r--drivers/media/usb/dvb-usb/dvb-usb-init.c90
-rw-r--r--drivers/media/usb/dvb-usb/dvb-usb.h91
-rw-r--r--drivers/media/usb/em28xx/em28xx-cards.c4
-rw-r--r--drivers/media/usb/em28xx/em28xx-dvb.c1
-rw-r--r--drivers/media/usb/em28xx/em28xx.h4
-rw-r--r--drivers/media/usb/gspca/gspca.c2
-rw-r--r--drivers/media/usb/gspca/gspca.h1
-rw-r--r--drivers/media/usb/gspca/sq905.c2
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx.c9
-rw-r--r--drivers/media/usb/gspca/w996Xcf.c3
-rw-r--r--drivers/media/usb/pwc/pwc-dec23.c2
-rw-r--r--drivers/media/usb/pwc/pwc-if.c8
-rw-r--r--drivers/media/usb/pwc/pwc-uncompress.c3
-rw-r--r--drivers/media/usb/ttusb-dec/ttusb_dec.c4
-rw-r--r--drivers/media/usb/usbtv/usbtv-video.c6
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c34
-rw-r--r--drivers/media/usb/uvc/uvc_video.c94
-rw-r--r--drivers/media/usb/uvc/uvcvideo.h5
-rw-r--r--drivers/media/usb/zr364xx/zr364xx.c13
23 files changed, 284 insertions, 158 deletions
diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c
index e731243267e4..5d38171b7638 100644
--- a/drivers/media/usb/b2c2/flexcop-usb.c
+++ b/drivers/media/usb/b2c2/flexcop-usb.c
@@ -15,8 +15,8 @@
/* debug */
#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
-#define dprintk(level,args...) \
- do { if ((debug & level)) printk(args); } while (0)
+#define dprintk(level, args...) \
+ do { if ((debug & (level))) printk(args); } while (0)
#define debug_dump(b, l, method) do {\
int i; \
@@ -27,8 +27,8 @@
#define DEBSTATUS ""
#else
-#define dprintk(level, args...)
-#define debug_dump(b, l, method)
+#define dprintk(level, args...) no_printk(args)
+#define debug_dump(b, l, method) do { } while (0)
#define DEBSTATUS " (debugging is not enabled)"
#endif
@@ -195,7 +195,6 @@ static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,
break;
default:
return -EINVAL;
- break;
}
for (i = 0; i < len;) {
pagechunk =
diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h
index b32eab641793..6929e4d97067 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -425,8 +425,6 @@ struct cx231xx_audio {
u16 end_point_addr;
};
-struct cx231xx;
-
/*****************************************************************/
/* set/get i2c */
/* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index 89a1b204b90c..aa45b5d263f6 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -1171,14 +1171,9 @@ static int anysee_ci_write_attribute_mem(struct dvb_ca_en50221 *ci, int slot,
int addr, u8 val)
{
struct dvb_usb_device *d = ci->data;
- int ret;
u8 buf[] = {CMD_CI, 0x03, 0x40 | addr >> 8, addr & 0xff, 0x00, 1, val};
- ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
- if (ret)
- return ret;
-
- return 0;
+ return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
}
static int anysee_ci_read_cam_control(struct dvb_ca_en50221 *ci, int slot,
@@ -1200,14 +1195,9 @@ static int anysee_ci_write_cam_control(struct dvb_ca_en50221 *ci, int slot,
u8 addr, u8 val)
{
struct dvb_usb_device *d = ci->data;
- int ret;
u8 buf[] = {CMD_CI, 0x05, 0x40, addr, 0x00, 1, val};
- ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
- if (ret)
- return ret;
-
- return 0;
+ return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
}
static int anysee_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot)
@@ -1252,13 +1242,8 @@ static int anysee_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot)
static int anysee_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot)
{
struct dvb_usb_device *d = ci->data;
- int ret;
- ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 1), 0x02);
- if (ret)
- return ret;
-
- return 0;
+ return anysee_wr_reg_mask(d, REG_IOD, (0 << 1), 0x02);
}
static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot,
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
index 52bcc2d2efe5..288c15a7d72b 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
@@ -100,7 +100,8 @@ struct dvb_usb_device;
struct dvb_usb_adapter;
/**
- * structure for carrying all needed data from the device driver to the general
+ * struct dvb_usb_driver_info - structure for carrying all needed data from the
+ * device driver to the general
* dvb usb routines
* @name: device name
* @rc_map: name of rc codes table
@@ -113,7 +114,7 @@ struct dvb_usb_driver_info {
};
/**
- * structure for remote controller configuration
+ * struct dvb_usb_rc - structure for remote controller configuration
* @map_name: name of rc codes table
* @allowed_protos: protocol(s) supported by the driver
* @change_protocol: callback to change protocol
@@ -135,10 +136,11 @@ struct dvb_usb_rc {
};
/**
- * usb streaming configuration for adapter
+ * struct usb_data_stream_properties - usb streaming configuration for adapter
* @type: urb type
* @count: count of used urbs
* @endpoint: stream usb endpoint number
+ * @u: union for @bulk and @isoc
*/
struct usb_data_stream_properties {
#define USB_BULK 1
@@ -160,15 +162,15 @@ struct usb_data_stream_properties {
};
/**
- * properties of dvb usb device adapter
+ * struct dvb_usb_adapter_properties - properties of dvb usb device adapter
* @caps: adapter capabilities
* @pid_filter_count: pid count of adapter pid-filter
* @pid_filter_ctrl: called to enable/disable pid-filter
* @pid_filter: called to set/unset pid for filtering
* @stream: adapter usb stream configuration
*/
-#define MAX_NO_OF_FE_PER_ADAP 3
struct dvb_usb_adapter_properties {
+#define MAX_NO_OF_FE_PER_ADAP 3
#define DVB_USB_ADAP_HAS_PID_FILTER 0x01
#define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02
#define DVB_USB_ADAP_NEED_PID_FILTERING 0x04
@@ -208,6 +210,7 @@ struct dvb_usb_adapter_properties {
* @frontend_attach: called to attach the possible frontends
* @frontend_detach: called to detach the possible frontends
* @tuner_attach: called to attach the possible tuners
+ * @tuner_detach: called to detach the possible tuners
* @frontend_ctrl: called to power on/off active frontend
* @streaming_ctrl: called to start/stop the usb streaming of adapter
* @init: called after adapters are created in order to finalize device
@@ -218,8 +221,8 @@ struct dvb_usb_adapter_properties {
* of the adapter just before streaming is started. input stream is transport
* stream from the demodulator and output stream is usb stream to host.
*/
-#define MAX_NO_OF_ADAPTER_PER_DEVICE 2
struct dvb_usb_device_properties {
+#define MAX_NO_OF_ADAPTER_PER_DEVICE 2
const char *driver_name;
struct module *owner;
short *adapter_nr;
@@ -265,7 +268,12 @@ struct dvb_usb_device_properties {
};
/**
- * generic object of an usb stream
+ * struct usb_data_stream - generic object of an usb stream
+ * @udev: USB device
+ * @props: properties
+ * @state: state of the data stream
+ * @complete: complete callback
+ * @urb_list: list of URBs
* @buf_num: number of buffer allocated
* @buf_size: size of each buffer in buf_list
* @buf_list: array containing all allocate buffers for streaming
@@ -273,9 +281,10 @@ struct dvb_usb_device_properties {
*
* @urbs_initialized: number of URBs initialized
* @urbs_submitted: number of URBs submitted
+ * @user_priv: private pointer
*/
-#define MAX_NO_URBS_FOR_DATA_STREAM 10
struct usb_data_stream {
+#define MAX_NO_URBS_FOR_DATA_STREAM 10
struct usb_device *udev;
struct usb_data_stream_properties props;
@@ -298,7 +307,7 @@ struct usb_data_stream {
};
/**
- * dvb adapter object on dvb usb device
+ * struct dvb_usb_adapter - dvb adapter object on dvb usb device
* @props: pointer to adapter properties
* @stream: adapter the usb data stream
* @id: index of this adapter (starting with 0)
@@ -307,11 +316,12 @@ struct usb_data_stream {
* @pid_filtering: is hardware pid_filtering used or not
* @feed_count: current feed count
* @max_feed_count: maimum feed count device can handle
+ * @active_fe: active frontend
+ * @state_bits: status bits
* @dvb_adap: adapter dvb_adapter
* @dmxdev: adapter dmxdev
* @demux: adapter software demuxer
* @dvb_net: adapter dvb_net interfaces
- * @sync_mutex: mutex used to sync control and streaming of the adapter
* @fe: adapter frontends
* @fe_init: rerouted frontend-init function
* @fe_sleep: rerouted frontend-sleep function
@@ -343,7 +353,7 @@ struct dvb_usb_adapter {
};
/**
- * dvb usb device object
+ * struct dvb_usb_device - dvb usb device object
* @props: device properties
* @name: device name
* @rc_map: name of rc codes table
@@ -355,7 +365,9 @@ struct dvb_usb_adapter {
* @usb_mutex: mutex for usb control messages
* @i2c_mutex: mutex for i2c-transfers
* @i2c_adap: device's i2c-adapter
+ * @adapter: adapters
* @rc_dev: rc device for the remote control
+ * @rc_phys: rc path
* @rc_query_work: work for polling remote
* @priv: private data of the actual driver (allocate by dvb usb, size defined
* in size_of_priv of dvb_usb_properties).
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c
index c1a7634e27b4..28e1fd64dd3c 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c
@@ -79,11 +79,17 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
}
}
- if ((ret = dvb_usb_adapter_stream_init(adap)) ||
- (ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) ||
- (ret = dvb_usb_adapter_frontend_init(adap))) {
+ ret = dvb_usb_adapter_stream_init(adap);
+ if (ret)
return ret;
- }
+
+ ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs);
+ if (ret)
+ goto dvb_init_err;
+
+ ret = dvb_usb_adapter_frontend_init(adap);
+ if (ret)
+ goto frontend_init_err;
/* use exclusive FE lock if there is multiple shared FEs */
if (adap->fe_adap[1].fe)
@@ -103,6 +109,12 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
}
return 0;
+
+frontend_init_err:
+ dvb_usb_adapter_dvb_exit(adap);
+dvb_init_err:
+ dvb_usb_adapter_stream_exit(adap);
+ return ret;
}
static int dvb_usb_adapter_exit(struct dvb_usb_device *d)
@@ -158,22 +170,20 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
if (d->props.priv_init != NULL) {
ret = d->props.priv_init(d);
- if (ret != 0) {
- kfree(d->priv);
- d->priv = NULL;
- return ret;
- }
+ if (ret != 0)
+ goto err_priv_init;
}
}
/* check the capabilities and set appropriate variables */
dvb_usb_device_power_ctrl(d, 1);
- if ((ret = dvb_usb_i2c_init(d)) ||
- (ret = dvb_usb_adapter_init(d, adapter_nums))) {
- dvb_usb_exit(d);
- return ret;
- }
+ ret = dvb_usb_i2c_init(d);
+ if (ret)
+ goto err_i2c_init;
+ ret = dvb_usb_adapter_init(d, adapter_nums);
+ if (ret)
+ goto err_adapter_init;
if ((ret = dvb_usb_remote_init(d)))
err("could not initialize remote control.");
@@ -181,6 +191,17 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
dvb_usb_device_power_ctrl(d, 0);
return 0;
+
+err_adapter_init:
+ dvb_usb_adapter_exit(d);
+err_i2c_init:
+ dvb_usb_i2c_exit(d);
+ if (d->priv && d->props.priv_destroy)
+ d->props.priv_destroy(d);
+err_priv_init:
+ kfree(d->priv);
+ d->priv = NULL;
+ return ret;
}
/* determine the name and the state of the just found USB device */
@@ -255,41 +276,50 @@ int dvb_usb_device_init(struct usb_interface *intf,
if (du != NULL)
*du = NULL;
- if ((desc = dvb_usb_find_device(udev, props, &cold)) == NULL) {
+ d = kzalloc(sizeof(*d), GFP_KERNEL);
+ if (!d) {
+ err("no memory for 'struct dvb_usb_device'");
+ return -ENOMEM;
+ }
+
+ memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
+
+ desc = dvb_usb_find_device(udev, &d->props, &cold);
+ if (!desc) {
deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto error;
}
if (cold) {
info("found a '%s' in cold state, will try to load a firmware", desc->name);
ret = dvb_usb_download_firmware(udev, props);
if (!props->no_reconnect || ret != 0)
- return ret;
+ goto error;
}
info("found a '%s' in warm state.", desc->name);
- d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
- if (d == NULL) {
- err("no memory for 'struct dvb_usb_device'");
- return -ENOMEM;
- }
-
d->udev = udev;
- memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
d->desc = desc;
d->owner = owner;
usb_set_intfdata(intf, d);
- if (du != NULL)
+ ret = dvb_usb_init(d, adapter_nums);
+ if (ret) {
+ info("%s error while loading driver (%d)", desc->name, ret);
+ goto error;
+ }
+
+ if (du)
*du = d;
- ret = dvb_usb_init(d, adapter_nums);
+ info("%s successfully initialized and connected.", desc->name);
+ return 0;
- if (ret == 0)
- info("%s successfully initialized and connected.", desc->name);
- else
- info("%s error while loading driver (%d)", desc->name, ret);
+ error:
+ usb_set_intfdata(intf, NULL);
+ kfree(d);
return ret;
}
EXPORT_SYMBOL(dvb_usb_device_init);
diff --git a/drivers/media/usb/dvb-usb/dvb-usb.h b/drivers/media/usb/dvb-usb/dvb-usb.h
index 741be0e69447..0990aa4a17bb 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb.h
+++ b/drivers/media/usb/dvb-usb/dvb-usb.h
@@ -28,18 +28,19 @@
/* debug */
#ifdef CONFIG_DVB_USB_DEBUG
-#define dprintk(var,level,args...) \
- do { if ((var & level)) { printk(args); } } while (0)
+#define dprintk(var, level, args...) \
+ do { if (((var) & (level))) { printk(args); } } while (0)
-#define debug_dump(b,l,func) {\
+#define debug_dump(b, l, func) {\
int loop_; \
- for (loop_ = 0; loop_ < l; loop_++) func("%02x ", b[loop_]); \
+ for (loop_ = 0; loop_ < (l); loop_++) \
+ func("%02x ", b[loop_]); \
func("\n");\
}
#define DVB_USB_DEBUG_STATUS
#else
-#define dprintk(args...)
-#define debug_dump(b,l,func)
+#define dprintk(var, level, args...) no_printk(args)
+#define debug_dump(b, l, func) do { } while (0)
#define DVB_USB_DEBUG_STATUS " (debugging is not enabled)"
@@ -95,7 +96,7 @@ struct dvb_usb_device;
struct dvb_usb_adapter;
struct usb_data_stream;
-/**
+/*
* Properties of USB streaming - TODO this structure should be somewhere else
* describes the kind of USB transfer used for data-streaming.
* (BULK or ISOC)
@@ -120,7 +121,7 @@ struct usb_data_stream_properties {
};
/**
- * struct dvb_usb_adapter_properties - properties of a dvb-usb-adapter.
+ * struct dvb_usb_adapter_fe_properties - properties of a dvb-usb-adapter.
* A DVB-USB-Adapter is basically a dvb_adapter which is present on a USB-device.
* @caps: capabilities of the DVB USB device.
* @pid_filter_count: number of PID filter position in the optional hardware
@@ -139,6 +140,7 @@ struct usb_data_stream_properties {
* @tuner_attach: called to attach the correct tuner and to fill pll_addr,
* pll_desc and pll_init_buf of struct dvb_usb_device).
* @stream: configuration of the USB streaming
+ * @size_of_priv: size of the priv memory in struct dvb_usb_adapter
*/
struct dvb_usb_adapter_fe_properties {
#define DVB_USB_ADAP_HAS_PID_FILTER 0x01
@@ -191,15 +193,17 @@ struct dvb_rc_legacy {
};
/**
- * struct dvb_rc properties of remote controller, using rc-core
+ * struct dvb_rc - properties of remote controller, using rc-core
* @rc_codes: name of rc codes table
* @protocol: type of protocol(s) currently used by the driver
* @allowed_protos: protocol(s) supported by the driver
* @driver_type: Used to point if a device supports raw mode
* @change_protocol: callback to change protocol
+ * @module_name: module name
* @rc_query: called to query an event event.
* @rc_interval: time in ms between two queries.
* @bulk_mode: device supports bulk mode for RC (disable polling mode)
+ * @scancode_mask: scancode mask
*/
struct dvb_rc {
char *rc_codes;
@@ -219,6 +223,9 @@ struct dvb_rc {
* based on rc-core
* This is initialized/used only inside dvb-usb-remote.c.
* It shouldn't be set by the drivers.
+ *
+ * @DVB_RC_LEGACY: legacy driver
+ * @DVB_RC_CORE: rc-core driver
*/
enum dvb_usb_mode {
DVB_RC_LEGACY,
@@ -227,6 +234,7 @@ enum dvb_usb_mode {
/**
* struct dvb_usb_device_properties - properties of a dvb-usb-device
+ * @caps: capabilities
* @usb_ctrl: which USB device-side controller is in use. Needed for firmware
* download.
* @firmware: name of the firmware file.
@@ -243,6 +251,8 @@ enum dvb_usb_mode {
* @priv_destroy: just like priv_init, only called before deallocating
* the memory pointed by private field of struct dvb_usb_device.
*
+ * @num_adapters: the number of adapters in @adapters
+ * @adapter: the adapters
* @power_ctrl: called to enable/disable power of the device.
* @read_mac_address: called to read the MAC address of the device.
* @identify_state: called to determine the state (cold or warm), when it
@@ -267,9 +277,8 @@ enum dvb_usb_mode {
* @devices: array of struct dvb_usb_device_description compatibles with these
* properties.
*/
-#define MAX_NO_OF_ADAPTER_PER_DEVICE 2
struct dvb_usb_device_properties {
-
+#define MAX_NO_OF_ADAPTER_PER_DEVICE 2
#define DVB_USB_IS_AN_I2C_ADAPTER 0x01
int caps;
@@ -313,6 +322,11 @@ struct dvb_usb_device_properties {
/**
* struct usb_data_stream - generic object of an USB stream
+ * @udev: the USB device
+ * @props: data stream properties
+ * @state: state of the stream
+ * @complete: complete callback
+ * @urb_list: list of URBs
* @buf_num: number of buffer allocated.
* @buf_size: size of each buffer in buf_list.
* @buf_list: array containing all allocate buffers for streaming.
@@ -320,9 +334,10 @@ struct dvb_usb_device_properties {
*
* @urbs_initialized: number of URBs initialized.
* @urbs_submitted: number of URBs submitted.
+ * @user_priv: for private use.
*/
-#define MAX_NO_URBS_FOR_DATA_STREAM 10
struct usb_data_stream {
+#define MAX_NO_URBS_FOR_DATA_STREAM 10
struct usb_device *udev;
struct usb_data_stream_properties props;
@@ -345,29 +360,15 @@ struct usb_data_stream {
};
/**
- * struct dvb_usb_adapter - a DVB adapter on a USB device
- * @id: index of this adapter (starting with 0).
- *
- * @feedcount: number of requested feeds (used for streaming-activation)
- * @pid_filtering: is hardware pid_filtering used or not.
- *
- * @pll_addr: I2C address of the tuner for programming
- * @pll_init: array containing the initialization buffer
- * @pll_desc: pointer to the appropriate struct dvb_pll_desc
- * @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod or the board
- *
- * @dvb_adap: device's dvb_adapter.
- * @dmxdev: device's dmxdev.
- * @demux: device's software demuxer.
- * @dvb_net: device's dvb_net interfaces.
- * @dvb_frontend: device's frontend.
- * @max_feed_count: how many feeds can be handled simultaneously by this
- * device
- *
+ * struct dvb_usb_fe_adapter - a DVB adapter on a USB device
+ * @fe: frontend
* @fe_init: rerouted frontend-init (wakeup) function.
* @fe_sleep: rerouted frontend-sleep function.
- *
* @stream: the usb data stream.
+ * @pid_filtering: is hardware pid_filtering used or not.
+ * @max_feed_count: how many feeds can be handled simultaneously by this
+ * device
+ * @priv: private pointer
*/
struct dvb_usb_fe_adapter {
struct dvb_frontend *fe;
@@ -383,6 +384,25 @@ struct dvb_usb_fe_adapter {
void *priv;
};
+/**
+ * struct dvb_usb_adapter - a DVB adapter on a USB device
+ * @dev: DVB USB device pointer
+ * @props: properties
+ * @state: status
+ * @id: index of this adapter (starting with 0).
+ *
+ * @feedcount: number of requested feeds (used for streaming-activation)
+ *
+ * @dvb_adap: device's dvb_adapter.
+ * @dmxdev: device's dmxdev.
+ * @demux: device's software demuxer.
+ * @dvb_net: device's dvb_net interfaces.
+ *
+ * @fe_adap: frontend adapters
+ * @active_fe: active frontend
+ * @num_frontends_initialized: number of initialized frontends
+ * @priv: private pointer
+ */
struct dvb_usb_adapter {
struct dvb_usb_device *dev;
struct dvb_usb_adapter_properties props;
@@ -427,8 +447,12 @@ struct dvb_usb_adapter {
*
* @i2c_adap: device's i2c_adapter if it uses I2CoverUSB
*
+ * @num_adapters_initialized: number of initialized adapters
+ * @adapter: adapters
+ *
* @rc_dev: rc device for the remote control (rc-core mode)
* @input_dev: input device for the remote control (legacy mode)
+ * @rc_phys: rc device path
* @rc_query_work: struct work_struct frequent rc queries
* @last_event: last triggered event
* @last_state: last state (no, pressed, repeat)
@@ -487,7 +511,8 @@ extern int __must_check
dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
/* commonly used remote control parsing */
-extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
+int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, u8 keybuf[5],
+ u32 *event, int *state);
/* commonly used firmware download types and function */
struct hexline {
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index d6c8ae213914..ba9292e2a587 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -2778,8 +2778,12 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM2765_BOARD_SPEEDLINK_VAD_LAPLACE },
{ USB_DEVICE(0x2013, 0x0258),
.driver_info = EM28178_BOARD_PCTV_461E },
+ { USB_DEVICE(0x2013, 0x8258), /* Bulk transport 461e */
+ .driver_info = EM28178_BOARD_PCTV_461E },
{ USB_DEVICE(0x2013, 0x0461),
.driver_info = EM28178_BOARD_PCTV_461E_V2 },
+ { USB_DEVICE(0x2013, 0x8461), /* Bulk transport 461e v2 */
+ .driver_info = EM28178_BOARD_PCTV_461E_V2 },
{ USB_DEVICE(0x2013, 0x0259),
.driver_info = EM28178_BOARD_PCTV_461E_V2 },
{ USB_DEVICE(0x2013, 0x025f),
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index 526424279637..471bd74667e3 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -2010,6 +2010,7 @@ ret:
return result;
out_free:
+ em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE);
kfree(dvb);
dev->dvb = NULL;
goto ret;
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 6648e11f1271..ab167cd1f400 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -335,7 +335,7 @@ enum em28xx_usb_audio_type {
};
/**
- * em28xx_amux - describes the type of audio input used by em28xx
+ * enum em28xx_amux - describes the type of audio input used by em28xx
*
* @EM28XX_AMUX_UNUSED:
* Used only on em28xx dev->map field, in order to mark an entry
@@ -628,8 +628,6 @@ struct em28xx_audio {
atomic_t stream_started; /* stream should be running if true */
};
-struct em28xx;
-
enum em28xx_i2c_algo_type {
EM28XX_I2C_ALGO_EM28XX = 0,
EM28XX_I2C_ALGO_EM2800,
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index 158c8e28ed2c..47d8f28bfdfc 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -1576,6 +1576,8 @@ out:
#endif
v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
v4l2_device_unregister(&gspca_dev->v4l2_dev);
+ if (sd_desc->probe_error)
+ sd_desc->probe_error(gspca_dev);
kfree(gspca_dev->usb_buf);
kfree(gspca_dev);
return ret;
diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h
index b0ced2e14006..a6554d5e9e1a 100644
--- a/drivers/media/usb/gspca/gspca.h
+++ b/drivers/media/usb/gspca/gspca.h
@@ -105,6 +105,7 @@ struct sd_desc {
cam_cf_op config; /* called on probe */
cam_op init; /* called on probe and resume */
cam_op init_controls; /* called on probe */
+ cam_v_op probe_error; /* called if probe failed, do cleanup here */
cam_op start; /* called on stream on after URBs creation */
cam_pkt_op pkt_scan;
/* optional operations */
diff --git a/drivers/media/usb/gspca/sq905.c b/drivers/media/usb/gspca/sq905.c
index 97799cfb832e..949111070971 100644
--- a/drivers/media/usb/gspca/sq905.c
+++ b/drivers/media/usb/gspca/sq905.c
@@ -158,7 +158,7 @@ static int
sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
{
int ret;
- int act_len;
+ int act_len = 0;
gspca_dev->usb_buf[0] = '\0';
if (need_lock)
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c
index 95673fc0a99c..d9bc2aacc885 100644
--- a/drivers/media/usb/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c
@@ -529,12 +529,21 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
static int stv06xx_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id);
+static void stv06xx_probe_error(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *)gspca_dev;
+
+ kfree(sd->sensor_priv);
+ sd->sensor_priv = NULL;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
.config = stv06xx_config,
.init = stv06xx_init,
.init_controls = stv06xx_init_controls,
+ .probe_error = stv06xx_probe_error,
.start = stv06xx_start,
.stopN = stv06xx_stopN,
.pkt_scan = stv06xx_pkt_scan,
diff --git a/drivers/media/usb/gspca/w996Xcf.c b/drivers/media/usb/gspca/w996Xcf.c
index a8350ee9712f..79baa0c1a031 100644
--- a/drivers/media/usb/gspca/w996Xcf.c
+++ b/drivers/media/usb/gspca/w996Xcf.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-or-later
-/**
- *
+/*
* GSPCA sub driver for W996[78]CF JPEG USB Dual Mode Camera Chip.
*
* Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
diff --git a/drivers/media/usb/pwc/pwc-dec23.c b/drivers/media/usb/pwc/pwc-dec23.c
index 4e26ada87f7b..a3aa8c7174b9 100644
--- a/drivers/media/usb/pwc/pwc-dec23.c
+++ b/drivers/media/usb/pwc/pwc-dec23.c
@@ -637,7 +637,7 @@ static void DecompressBand23(struct pwc_dec23_private *pdec,
}
/**
- * Uncompress a pwc23 buffer.
+ * pwc_dec23_decompress - Uncompress a pwc23 buffer.
* @pdev: pointer to pwc device's internal struct
* @src: raw data
* @dst: image output
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index 5e3339cc31c0..e342199711d3 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -861,7 +861,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
break;
default:
return -ENODEV;
- break;
}
}
else if (vendor_id == 0x069A) {
@@ -873,7 +872,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
break;
default:
return -ENODEV;
- break;
}
}
else if (vendor_id == 0x046d) {
@@ -932,7 +930,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
break;
default:
return -ENODEV;
- break;
}
}
else if (vendor_id == 0x055d) {
@@ -958,7 +955,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
break;
default:
return -ENODEV;
- break;
}
}
else if (vendor_id == 0x041e) {
@@ -977,7 +973,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
break;
default:
return -ENODEV;
- break;
}
}
else if (vendor_id == 0x04cc) {
@@ -989,7 +984,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
break;
default:
return -ENODEV;
- break;
}
}
else if (vendor_id == 0x06be) {
@@ -1002,7 +996,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
break;
default:
return -ENODEV;
- break;
}
}
@@ -1020,7 +1013,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
break;
default:
return -ENODEV;
- break;
}
}
else
diff --git a/drivers/media/usb/pwc/pwc-uncompress.c b/drivers/media/usb/pwc/pwc-uncompress.c
index abfc88391036..68bc3829c6b3 100644
--- a/drivers/media/usb/pwc/pwc-uncompress.c
+++ b/drivers/media/usb/pwc/pwc-uncompress.c
@@ -9,9 +9,6 @@
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
-
-
- vim: set ts=8:
*/
#include <asm/current.h>
diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c
index df6c5e4a0f05..a852ee5f7ac9 100644
--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c
@@ -1102,11 +1102,9 @@ static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
case DMX_TYPE_TS:
return ttusb_dec_start_ts_feed(dvbdmxfeed);
- break;
case DMX_TYPE_SEC:
return ttusb_dec_start_sec_feed(dvbdmxfeed);
- break;
default:
dprintk(" type: unknown (%d)\n", dvbdmxfeed->type);
@@ -1157,11 +1155,9 @@ static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
switch (dvbdmxfeed->type) {
case DMX_TYPE_TS:
return ttusb_dec_stop_ts_feed(dvbdmxfeed);
- break;
case DMX_TYPE_SEC:
return ttusb_dec_stop_sec_feed(dvbdmxfeed);
- break;
}
return 0;
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index 3b4a2e769230..a714ad77ca8e 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -47,7 +47,7 @@
#include "usbtv.h"
-static struct usbtv_norm_params norm_params[] = {
+static const struct usbtv_norm_params norm_params[] = {
{
.norm = V4L2_STD_525_60,
.cap_width = 720,
@@ -63,7 +63,7 @@ static struct usbtv_norm_params norm_params[] = {
static int usbtv_configure_for_norm(struct usbtv *usbtv, v4l2_std_id norm)
{
int i, ret = 0;
- struct usbtv_norm_params *params = NULL;
+ const struct usbtv_norm_params *params = NULL;
for (i = 0; i < ARRAY_SIZE(norm_params); i++) {
if (norm_params[i].norm & norm) {
@@ -685,7 +685,7 @@ static int usbtv_s_input(struct file *file, void *priv, unsigned int i)
return usbtv_select_input(usbtv, i);
}
-static struct v4l2_ioctl_ops usbtv_ioctl_ops = {
+static const struct v4l2_ioctl_ops usbtv_ioctl_ops = {
.vidioc_querycap = usbtv_querycap,
.vidioc_enum_input = usbtv_enum_input,
.vidioc_enum_fmt_vid_cap = usbtv_enum_fmt_vid_cap,
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 30ef2a3110f7..9a791d8ef200 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1712,10 +1712,35 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
if (forward->bNrInPins != 1) {
uvc_dbg(chain->dev, DESCR,
"Extension unit %d has more than 1 input pin\n",
- entity->id);
+ forward->id);
return -EINVAL;
}
+ /*
+ * Some devices reference an output terminal as the
+ * source of extension units. This is incorrect, as
+ * output terminals only have an input pin, and thus
+ * can't be connected to any entity in the forward
+ * direction. The resulting topology would cause issues
+ * when registering the media controller graph. To
+ * avoid this problem, connect the extension unit to
+ * the source of the output terminal instead.
+ */
+ if (UVC_ENTITY_IS_OTERM(entity)) {
+ struct uvc_entity *source;
+
+ source = uvc_entity_by_id(chain->dev,
+ entity->baSourceID[0]);
+ if (!source) {
+ uvc_dbg(chain->dev, DESCR,
+ "Can't connect extension unit %u in chain\n",
+ forward->id);
+ break;
+ }
+
+ forward->baSourceID[0] = source->id;
+ }
+
list_add_tail(&forward->chain, &chain->entities);
if (!found)
uvc_dbg_cont(PROBE, " (->");
@@ -1735,6 +1760,13 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
return -EINVAL;
}
+ if (UVC_ENTITY_IS_OTERM(entity)) {
+ uvc_dbg(chain->dev, DESCR,
+ "Unsupported connection between output terminals %u and %u\n",
+ entity->id, forward->id);
+ break;
+ }
+
list_add_tail(&forward->chain, &chain->entities);
if (!found)
uvc_dbg_cont(PROBE, " (->");
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index f2f565281e63..a777b389a66e 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -6,11 +6,14 @@
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*/
+#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/usb.h>
+#include <linux/usb/hcd.h>
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
@@ -1096,6 +1099,29 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
return data[0];
}
+static inline enum dma_data_direction uvc_stream_dir(
+ struct uvc_streaming *stream)
+{
+ if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return DMA_FROM_DEVICE;
+ else
+ return DMA_TO_DEVICE;
+}
+
+static inline struct device *uvc_stream_to_dmadev(struct uvc_streaming *stream)
+{
+ return bus_to_hcd(stream->dev->udev->bus)->self.sysdev;
+}
+
+static int uvc_submit_urb(struct uvc_urb *uvc_urb, gfp_t mem_flags)
+{
+ /* Sync DMA. */
+ dma_sync_sgtable_for_device(uvc_stream_to_dmadev(uvc_urb->stream),
+ uvc_urb->sgt,
+ uvc_stream_dir(uvc_urb->stream));
+ return usb_submit_urb(uvc_urb->urb, mem_flags);
+}
+
/*
* uvc_video_decode_data_work: Asynchronous memcpy processing
*
@@ -1117,7 +1143,7 @@ static void uvc_video_copy_data_work(struct work_struct *work)
uvc_queue_buffer_release(op->buf);
}
- ret = usb_submit_urb(uvc_urb->urb, GFP_KERNEL);
+ ret = uvc_submit_urb(uvc_urb, GFP_KERNEL);
if (ret < 0)
dev_err(&uvc_urb->stream->intf->dev,
"Failed to resubmit video URB (%d).\n", ret);
@@ -1537,6 +1563,12 @@ static void uvc_video_complete(struct urb *urb)
/* Re-initialise the URB async work. */
uvc_urb->async_operations = 0;
+ /* Sync DMA and invalidate vmap range. */
+ dma_sync_sgtable_for_cpu(uvc_stream_to_dmadev(uvc_urb->stream),
+ uvc_urb->sgt, uvc_stream_dir(stream));
+ invalidate_kernel_vmap_range(uvc_urb->buffer,
+ uvc_urb->stream->urb_size);
+
/*
* Process the URB headers, and optionally queue expensive memcpy tasks
* to be deferred to a work queue.
@@ -1545,7 +1577,7 @@ static void uvc_video_complete(struct urb *urb)
/* If no async work is needed, resubmit the URB immediately. */
if (!uvc_urb->async_operations) {
- ret = usb_submit_urb(uvc_urb->urb, GFP_ATOMIC);
+ ret = uvc_submit_urb(uvc_urb, GFP_ATOMIC);
if (ret < 0)
dev_err(&stream->intf->dev,
"Failed to resubmit video URB (%d).\n", ret);
@@ -1560,24 +1592,49 @@ static void uvc_video_complete(struct urb *urb)
*/
static void uvc_free_urb_buffers(struct uvc_streaming *stream)
{
+ struct device *dma_dev = uvc_stream_to_dmadev(stream);
struct uvc_urb *uvc_urb;
for_each_uvc_urb(uvc_urb, stream) {
if (!uvc_urb->buffer)
continue;
-#ifndef CONFIG_DMA_NONCOHERENT
- usb_free_coherent(stream->dev->udev, stream->urb_size,
- uvc_urb->buffer, uvc_urb->dma);
-#else
- kfree(uvc_urb->buffer);
-#endif
+ dma_vunmap_noncontiguous(dma_dev, uvc_urb->buffer);
+ dma_free_noncontiguous(dma_dev, stream->urb_size, uvc_urb->sgt,
+ uvc_stream_dir(stream));
+
uvc_urb->buffer = NULL;
+ uvc_urb->sgt = NULL;
}
stream->urb_size = 0;
}
+static bool uvc_alloc_urb_buffer(struct uvc_streaming *stream,
+ struct uvc_urb *uvc_urb, gfp_t gfp_flags)
+{
+ struct device *dma_dev = uvc_stream_to_dmadev(stream);
+
+ uvc_urb->sgt = dma_alloc_noncontiguous(dma_dev, stream->urb_size,
+ uvc_stream_dir(stream),
+ gfp_flags, 0);
+ if (!uvc_urb->sgt)
+ return false;
+ uvc_urb->dma = uvc_urb->sgt->sgl->dma_address;
+
+ uvc_urb->buffer = dma_vmap_noncontiguous(dma_dev, stream->urb_size,
+ uvc_urb->sgt);
+ if (!uvc_urb->buffer) {
+ dma_free_noncontiguous(dma_dev, stream->urb_size,
+ uvc_urb->sgt,
+ uvc_stream_dir(stream));
+ uvc_urb->sgt = NULL;
+ return false;
+ }
+
+ return true;
+}
+
/*
* Allocate transfer buffers. This function can be called with buffers
* already allocated when resuming from suspend, in which case it will
@@ -1608,19 +1665,12 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
/* Retry allocations until one succeed. */
for (; npackets > 1; npackets /= 2) {
+ stream->urb_size = psize * npackets;
+
for (i = 0; i < UVC_URBS; ++i) {
struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
- stream->urb_size = psize * npackets;
-#ifndef CONFIG_DMA_NONCOHERENT
- uvc_urb->buffer = usb_alloc_coherent(
- stream->dev->udev, stream->urb_size,
- gfp_flags | __GFP_NOWARN, &uvc_urb->dma);
-#else
- uvc_urb->buffer =
- kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN);
-#endif
- if (!uvc_urb->buffer) {
+ if (!uvc_alloc_urb_buffer(stream, uvc_urb, gfp_flags)) {
uvc_free_urb_buffers(stream);
break;
}
@@ -1730,12 +1780,8 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
urb->context = uvc_urb;
urb->pipe = usb_rcvisocpipe(stream->dev->udev,
ep->desc.bEndpointAddress);
-#ifndef CONFIG_DMA_NONCOHERENT
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
urb->transfer_dma = uvc_urb->dma;
-#else
- urb->transfer_flags = URB_ISO_ASAP;
-#endif
urb->interval = ep->desc.bInterval;
urb->transfer_buffer = uvc_urb->buffer;
urb->complete = uvc_video_complete;
@@ -1795,10 +1841,8 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream,
usb_fill_bulk_urb(urb, stream->dev->udev, pipe, uvc_urb->buffer,
size, uvc_video_complete, uvc_urb);
-#ifndef CONFIG_DMA_NONCOHERENT
urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
urb->transfer_dma = uvc_urb->dma;
-#endif
uvc_urb->urb = urb;
}
@@ -1895,7 +1939,7 @@ static int uvc_video_start_transfer(struct uvc_streaming *stream,
/* Submit the URBs. */
for_each_uvc_urb(uvc_urb, stream) {
- ret = usb_submit_urb(uvc_urb->urb, gfp_flags);
+ ret = uvc_submit_urb(uvc_urb, gfp_flags);
if (ret < 0) {
dev_err(&stream->intf->dev,
"Failed to submit URB %u (%d).\n",
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 97df5ecd66c9..cce5e38133cd 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -219,6 +219,7 @@
*/
struct gpio_desc;
+struct sg_table;
struct uvc_device;
/* TODO: Put the most frequently accessed fields at the beginning of
@@ -545,7 +546,8 @@ struct uvc_copy_op {
* @urb: the URB described by this context structure
* @stream: UVC streaming context
* @buffer: memory storage for the URB
- * @dma: DMA coherent addressing for the urb_buffer
+ * @dma: Allocated DMA handle
+ * @sgt: sgt_table with the urb locations in memory
* @async_operations: counter to indicate the number of copy operations
* @copy_operations: work descriptors for asynchronous copy operations
* @work: work queue entry for asynchronous decode
@@ -556,6 +558,7 @@ struct uvc_urb {
char *buffer;
dma_addr_t dma;
+ struct sg_table *sgt;
unsigned int async_operations;
struct uvc_copy_op copy_operations[UVC_MAX_PACKETS];
diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
index d29b861367ea..1ef611e08323 100644
--- a/drivers/media/usb/zr364xx/zr364xx.c
+++ b/drivers/media/usb/zr364xx/zr364xx.c
@@ -1430,7 +1430,7 @@ static int zr364xx_probe(struct usb_interface *intf,
if (hdl->error) {
err = hdl->error;
dev_err(&udev->dev, "couldn't register control\n");
- goto unregister;
+ goto free_hdlr_and_unreg_dev;
}
/* save the init method used by this camera */
cam->method = id->driver_info;
@@ -1503,7 +1503,7 @@ static int zr364xx_probe(struct usb_interface *intf,
if (!cam->read_endpoint) {
err = -ENOMEM;
dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
- goto unregister;
+ goto free_hdlr_and_unreg_dev;
}
/* v4l */
@@ -1515,7 +1515,7 @@ static int zr364xx_probe(struct usb_interface *intf,
/* load zr364xx board specific */
err = zr364xx_board_init(cam);
if (err)
- goto unregister;
+ goto free_hdlr_and_unreg_dev;
err = v4l2_ctrl_handler_setup(hdl);
if (err)
goto board_uninit;
@@ -1533,7 +1533,7 @@ static int zr364xx_probe(struct usb_interface *intf,
err = video_register_device(&cam->vdev, VFL_TYPE_VIDEO, -1);
if (err) {
dev_err(&udev->dev, "video_register_device failed\n");
- goto free_handler;
+ goto board_uninit;
}
cam->v4l2_dev.release = zr364xx_release;
@@ -1541,11 +1541,10 @@ static int zr364xx_probe(struct usb_interface *intf,
video_device_node_name(&cam->vdev));
return 0;
-free_handler:
- v4l2_ctrl_handler_free(hdl);
board_uninit:
zr364xx_board_uninit(cam);
-unregister:
+free_hdlr_and_unreg_dev:
+ v4l2_ctrl_handler_free(hdl);
v4l2_device_unregister(&cam->v4l2_dev);
free_cam:
kfree(cam);