Skip to content

Commit a70705d

Browse files
ribaldahverkuil
authored andcommitted
media: uvcvideo: Rollback non processed entities on error
If we fail to commit an entity, we need to restore the UVC_CTRL_DATA_BACKUP for the other uncommitted entities. Otherwise the control cache and the device would be out of sync. Cc: [email protected] Fixes: b401200 ("[media] uvcvideo: Add support for control events") Reported-by: Hans de Goede <[email protected]> Closes: https://lore.kernel.org/linux-media/[email protected]/ Signed-off-by: Ricardo Ribalda <[email protected]> Message-ID: <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Signed-off-by: Hans Verkuil <[email protected]>
1 parent 5c79146 commit a70705d

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

drivers/media/usb/uvc/uvc_ctrl.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2119,7 +2119,7 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
21192119
unsigned int processed_ctrls = 0;
21202120
struct uvc_control *ctrl;
21212121
unsigned int i;
2122-
int ret;
2122+
int ret = 0;
21232123

21242124
if (entity == NULL)
21252125
return 0;
@@ -2148,8 +2148,6 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
21482148
dev->intfnum, ctrl->info.selector,
21492149
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
21502150
ctrl->info.size);
2151-
else
2152-
ret = 0;
21532151

21542152
if (!ret)
21552153
processed_ctrls++;
@@ -2165,13 +2163,20 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
21652163
ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
21662164
ret = uvc_ctrl_set_handle(handle, ctrl, handle);
21672165

2168-
if (ret < 0) {
2166+
if (ret < 0 && !rollback) {
21692167
if (err_ctrl)
21702168
*err_ctrl = ctrl;
2171-
return ret;
2169+
/*
2170+
* If we fail to set a control, we need to rollback
2171+
* the next ones.
2172+
*/
2173+
rollback = 1;
21722174
}
21732175
}
21742176

2177+
if (ret)
2178+
return ret;
2179+
21752180
return processed_ctrls;
21762181
}
21772182

@@ -2202,7 +2207,8 @@ int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
22022207
struct uvc_video_chain *chain = handle->chain;
22032208
struct uvc_control *err_ctrl;
22042209
struct uvc_entity *entity;
2205-
int ret = 0;
2210+
int ret_out = 0;
2211+
int ret;
22062212

22072213
/* Find the control. */
22082214
list_for_each_entry(entity, &chain->entities, chain) {
@@ -2213,17 +2219,23 @@ int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
22132219
ctrls->error_idx =
22142220
uvc_ctrl_find_ctrl_idx(entity, ctrls,
22152221
err_ctrl);
2216-
goto done;
2222+
/*
2223+
* When we fail to commit an entity, we need to
2224+
* restore the UVC_CTRL_DATA_BACKUP for all the
2225+
* controls in the other entities, otherwise our cache
2226+
* and the hardware will be out of sync.
2227+
*/
2228+
rollback = 1;
2229+
2230+
ret_out = ret;
22172231
} else if (ret > 0 && !rollback) {
22182232
uvc_ctrl_send_events(handle, entity,
22192233
ctrls->controls, ctrls->count);
22202234
}
22212235
}
22222236

2223-
ret = 0;
2224-
done:
22252237
mutex_unlock(&chain->ctrl_mutex);
2226-
return ret;
2238+
return ret_out;
22272239
}
22282240

22292241
static int uvc_mapping_get_xctrl_compound(struct uvc_video_chain *chain,

0 commit comments

Comments
 (0)