From: Saad Varshani <varshanisaad@gmail.com>
To: nkapron@google.com, gregkh@linuxfoundation.org
Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
Saad Varshani <varshanisaad@gmail.com>,
syzbot+300213c2b5b55c0244f4@syzkaller.appspotmail.com
Subject: [PATCH v5] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks
Date: Fri, 6 Nov 2026 20:45:53 -0800 [thread overview]
Message-ID: <20261107044553.24277-1-varshanisaad@gmail.com> (raw)
In-Reply-To: <20261106020727.6055-1-varshanisaad@gmail.com>
Removed su_mutex locking in the function uvcg_extension_bm_controls_store.
Done this due to the deadlock caused by the mutex conflict in
fs/configfs_write_iter. Validated commit with the C repro provided by
syzbot. No other conficts observed.
Also removed the su_mutex in the other attribute extension functions.
Such as uvcg_extension_b_control_size_store. This applies to all
uvcg_configfs attribute store/show functions.
The deadlock was happening due to a circular mutex dependency between
configfs (frag_sem) and uvcg_extension su_mutex. The reason it is safe
to traverse item->ci_parent without su_mutex is because
configfs_write_iter() calls flush_write_buffer() which calls the
attribute function, holding frag_sem. Which prevents configfs_rmdir()
from unlinking the item or its ci_parent hierarchy
Also reordered fmt->linked in uvcg_frame_b_frame_index_show() to be
under the &opts->lock. As well as reorder refcnt in uvcg_color_matching
store to be under &opts->lock.
Applied opts->lock mutex, to functions uvcg_format_allow_link(),
uvcg_format_drop_link(), uvcg_uncompressed_make(), uvcg_mjpeg_make(),
and uvcg_framebased_make() due to them also modifying
color_match->refcnt, to avoid concurrency issues.
---
v5 changes:
- Synchronised color_match->refcnt changes with the opts->lock
mutex in the functions uvcg_format_allow_link(),
uvcg_format_drop_link(), uvcg_uncompressed_make(),
uvcg_mjpeg_make(), and uvcg_framebased_make()
Reported-by: syzbot+300213c2b5b55c0244f4@syzkaller.appspotmail.com
Closes: https://syzbot.org/bug?extid=300213c2b5b55c0244f4
Signed-off-by: Saad Varshani <varshanisaad@gmail.com>
---
drivers/usb/gadget/function/uvc_configfs.c | 283 +++------------------
1 file changed, 41 insertions(+), 242 deletions(-)
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 70a1415ea401..4f775efe24b6 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -191,11 +191,8 @@ static ssize_t uvcg_control_header_##cname##_show( \
struct uvcg_control_header *ch = to_uvcg_control_header(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item); \
\
@@ -203,7 +200,6 @@ static ssize_t uvcg_control_header_##cname##_show( \
result = sprintf(page, "%u\n", le##bits##_to_cpu(ch->desc.aname));\
mutex_unlock(&opts->lock); \
\
- mutex_unlock(su_mutex); \
return result; \
} \
\
@@ -214,12 +210,9 @@ uvcg_control_header_##cname##_store(struct config_item *item, \
struct uvcg_control_header *ch = to_uvcg_control_header(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
int ret; \
u##bits num; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item); \
\
@@ -241,7 +234,6 @@ uvcg_control_header_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -309,12 +301,9 @@ static ssize_t uvcg_default_processing_##cname##_show( \
struct config_group *group = to_config_group(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
struct uvc_processing_unit_descriptor *pd; \
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item); \
pd = &opts->uvc_processing; \
@@ -323,7 +312,6 @@ static ssize_t uvcg_default_processing_##cname##_show( \
result = sprintf(page, "%u\n", le##bits##_to_cpu(pd->aname)); \
mutex_unlock(&opts->lock); \
\
- mutex_unlock(su_mutex); \
return result; \
} \
\
@@ -340,7 +328,6 @@ static ssize_t uvcg_default_processing_bm_controls_store(
struct config_item *item, const char *page, size_t len)
{
struct config_group *group = to_config_group(item);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvc_processing_unit_descriptor *pd;
struct config_item *opts_item;
struct f_uvc_opts *opts;
@@ -348,8 +335,6 @@ static ssize_t uvcg_default_processing_bm_controls_store(
unsigned int i;
int ret, n = 0;
- mutex_lock(su_mutex);
-
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
pd = &opts->uvc_processing;
@@ -390,7 +375,6 @@ static ssize_t uvcg_default_processing_bm_controls_store(
kfree(bm_controls);
unlock:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
@@ -400,13 +384,10 @@ static ssize_t uvcg_default_processing_bm_controls_show(
struct config_group *group = to_config_group(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvc_processing_unit_descriptor *pd;
int result, i;
char *pg = page;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
pd = &opts->uvc_processing;
@@ -418,8 +399,6 @@ static ssize_t uvcg_default_processing_bm_controls_show(
}
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return result;
}
@@ -470,12 +449,9 @@ static ssize_t uvcg_default_camera_##cname##_show( \
struct config_group *group = to_config_group(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
struct uvc_camera_terminal_descriptor *cd; \
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent-> \
ci_parent; \
opts = to_f_uvc_opts(opts_item); \
@@ -485,8 +461,6 @@ static ssize_t uvcg_default_camera_##cname##_show( \
result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
mutex_unlock(&opts->lock); \
\
- mutex_unlock(su_mutex); \
- \
return result; \
} \
\
@@ -509,7 +483,6 @@ static ssize_t uvcg_default_camera_bm_controls_store(
struct config_item *item, const char *page, size_t len)
{
struct config_group *group = to_config_group(item);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvc_camera_terminal_descriptor *cd;
struct config_item *opts_item;
struct f_uvc_opts *opts;
@@ -517,8 +490,6 @@ static ssize_t uvcg_default_camera_bm_controls_store(
unsigned int i;
int ret, n = 0;
- mutex_lock(su_mutex);
-
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent->
ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -560,7 +531,6 @@ static ssize_t uvcg_default_camera_bm_controls_store(
kfree(bm_controls);
unlock:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
@@ -570,13 +540,10 @@ static ssize_t uvcg_default_camera_bm_controls_show(
struct config_group *group = to_config_group(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvc_camera_terminal_descriptor *cd;
int result, i;
char *pg = page;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent->
ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -588,8 +555,6 @@ static ssize_t uvcg_default_camera_bm_controls_show(
pg = page + result;
}
mutex_unlock(&opts->lock);
-
- mutex_unlock(su_mutex);
return result;
}
@@ -643,12 +608,9 @@ static ssize_t uvcg_default_output_##cname##_show( \
struct config_group *group = to_config_group(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
struct uvc_output_terminal_descriptor *cd; \
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = group->cg_item.ci_parent->ci_parent-> \
ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item); \
@@ -658,8 +620,6 @@ static ssize_t uvcg_default_output_##cname##_show( \
result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
mutex_unlock(&opts->lock); \
\
- mutex_unlock(su_mutex); \
- \
return result; \
} \
\
@@ -678,12 +638,9 @@ static ssize_t uvcg_default_output_b_source_id_show(struct config_item *item,
struct config_group *group = to_config_group(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvc_output_terminal_descriptor *cd;
int result;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = group->cg_item.ci_parent->ci_parent->
ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -693,8 +650,6 @@ static ssize_t uvcg_default_output_b_source_id_show(struct config_item *item,
result = sprintf(page, "%u\n", le8_to_cpu(cd->bSourceID));
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return result;
}
@@ -704,7 +659,6 @@ static ssize_t uvcg_default_output_b_source_id_store(struct config_item *item,
struct config_group *group = to_config_group(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvc_output_terminal_descriptor *cd;
int result;
u8 num;
@@ -713,8 +667,6 @@ static ssize_t uvcg_default_output_b_source_id_store(struct config_item *item,
if (result)
return result;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = group->cg_item.ci_parent->ci_parent->
ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -724,8 +676,6 @@ static ssize_t uvcg_default_output_b_source_id_store(struct config_item *item,
cd->bSourceID = num;
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return len;
}
UVC_ATTR(uvcg_default_output_, b_source_id, bSourceID);
@@ -789,15 +739,11 @@ static const struct uvcg_config_group_type uvcg_terminal_grp_type = {
static ssize_t uvcg_extension_##cname##_show(struct config_item *item, \
char *page) \
{ \
- struct config_group *group = to_config_group(item->ci_parent); \
- struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
struct uvcg_extension *xu = to_uvcg_extension(item); \
struct config_item *opts_item; \
struct f_uvc_opts *opts; \
int ret; \
\
- mutex_lock(su_mutex); \
- \
opts_item = item->ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item); \
\
@@ -805,8 +751,6 @@ static ssize_t uvcg_extension_##cname##_show(struct config_item *item, \
ret = sprintf(page, "%u\n", xu->desc.aname); \
mutex_unlock(&opts->lock); \
\
- mutex_unlock(su_mutex); \
- \
return ret; \
} \
UVC_ATTR##ro(uvcg_extension_, cname, aname)
@@ -818,8 +762,6 @@ UVCG_EXTENSION_ATTR(i_extension, iExtension, _RO);
static ssize_t uvcg_extension_b_num_controls_store(struct config_item *item,
const char *page, size_t len)
{
- struct config_group *group = to_config_group(item->ci_parent);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvcg_extension *xu = to_uvcg_extension(item);
struct config_item *opts_item;
struct f_uvc_opts *opts;
@@ -830,8 +772,6 @@ static ssize_t uvcg_extension_b_num_controls_store(struct config_item *item,
if (ret)
return ret;
- mutex_lock(su_mutex);
-
opts_item = item->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -839,8 +779,6 @@ static ssize_t uvcg_extension_b_num_controls_store(struct config_item *item,
xu->desc.bNumControls = num;
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return len;
}
UVCG_EXTENSION_ATTR(b_num_controls, bNumControls);
@@ -852,8 +790,6 @@ UVCG_EXTENSION_ATTR(b_num_controls, bNumControls);
static ssize_t uvcg_extension_b_nr_in_pins_store(struct config_item *item,
const char *page, size_t len)
{
- struct config_group *group = to_config_group(item->ci_parent);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvcg_extension *xu = to_uvcg_extension(item);
struct config_item *opts_item;
struct f_uvc_opts *opts;
@@ -865,8 +801,6 @@ static ssize_t uvcg_extension_b_nr_in_pins_store(struct config_item *item,
if (ret)
return ret;
- mutex_lock(su_mutex);
-
opts_item = item->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -893,7 +827,6 @@ static ssize_t uvcg_extension_b_nr_in_pins_store(struct config_item *item,
unlock:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
UVCG_EXTENSION_ATTR(b_nr_in_pins, bNrInPins);
@@ -905,8 +838,6 @@ UVCG_EXTENSION_ATTR(b_nr_in_pins, bNrInPins);
static ssize_t uvcg_extension_b_control_size_store(struct config_item *item,
const char *page, size_t len)
{
- struct config_group *group = to_config_group(item->ci_parent);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvcg_extension *xu = to_uvcg_extension(item);
struct config_item *opts_item;
struct f_uvc_opts *opts;
@@ -918,8 +849,6 @@ static ssize_t uvcg_extension_b_control_size_store(struct config_item *item,
if (ret)
return ret;
- mutex_lock(su_mutex);
-
opts_item = item->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -946,7 +875,6 @@ static ssize_t uvcg_extension_b_control_size_store(struct config_item *item,
unlock:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
@@ -955,14 +883,10 @@ UVCG_EXTENSION_ATTR(b_control_size, bControlSize);
static ssize_t uvcg_extension_guid_extension_code_show(struct config_item *item,
char *page)
{
- struct config_group *group = to_config_group(item->ci_parent);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvcg_extension *xu = to_uvcg_extension(item);
struct config_item *opts_item;
struct f_uvc_opts *opts;
- mutex_lock(su_mutex);
-
opts_item = item->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -970,23 +894,17 @@ static ssize_t uvcg_extension_guid_extension_code_show(struct config_item *item,
memcpy(page, xu->desc.guidExtensionCode, sizeof(xu->desc.guidExtensionCode));
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return sizeof(xu->desc.guidExtensionCode);
}
static ssize_t uvcg_extension_guid_extension_code_store(struct config_item *item,
const char *page, size_t len)
{
- struct config_group *group = to_config_group(item->ci_parent);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvcg_extension *xu = to_uvcg_extension(item);
struct config_item *opts_item;
struct f_uvc_opts *opts;
int ret;
- mutex_lock(su_mutex);
-
opts_item = item->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -995,8 +913,6 @@ static ssize_t uvcg_extension_guid_extension_code_store(struct config_item *item
min(sizeof(xu->desc.guidExtensionCode), len));
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
ret = sizeof(xu->desc.guidExtensionCode);
return ret;
@@ -1007,16 +923,12 @@ UVC_ATTR(uvcg_extension_, guid_extension_code, guidExtensionCode);
static ssize_t uvcg_extension_ba_source_id_show(struct config_item *item,
char *page)
{
- struct config_group *group = to_config_group(item->ci_parent);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvcg_extension *xu = to_uvcg_extension(item);
struct config_item *opts_item;
struct f_uvc_opts *opts;
char *pg = page;
int ret, i;
- mutex_lock(su_mutex);
-
opts_item = item->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -1027,24 +939,18 @@ static ssize_t uvcg_extension_ba_source_id_show(struct config_item *item,
}
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return ret;
}
static ssize_t uvcg_extension_ba_source_id_store(struct config_item *item,
const char *page, size_t len)
{
- struct config_group *group = to_config_group(item->ci_parent);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvcg_extension *xu = to_uvcg_extension(item);
struct config_item *opts_item;
struct f_uvc_opts *opts;
u8 *source_ids, *iter;
int ret, n = 0;
- mutex_lock(su_mutex);
-
opts_item = item->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -1078,7 +984,6 @@ static ssize_t uvcg_extension_ba_source_id_store(struct config_item *item,
unlock:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
UVC_ATTR(uvcg_extension_, ba_source_id, baSourceID);
@@ -1086,16 +991,12 @@ UVC_ATTR(uvcg_extension_, ba_source_id, baSourceID);
static ssize_t uvcg_extension_bm_controls_show(struct config_item *item,
char *page)
{
- struct config_group *group = to_config_group(item->ci_parent);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvcg_extension *xu = to_uvcg_extension(item);
struct config_item *opts_item;
struct f_uvc_opts *opts;
char *pg = page;
int ret, i;
- mutex_lock(su_mutex);
-
opts_item = item->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -1106,24 +1007,18 @@ static ssize_t uvcg_extension_bm_controls_show(struct config_item *item,
}
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return ret;
}
static ssize_t uvcg_extension_bm_controls_store(struct config_item *item,
const char *page, size_t len)
{
- struct config_group *group = to_config_group(item->ci_parent);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct uvcg_extension *xu = to_uvcg_extension(item);
struct config_item *opts_item;
struct f_uvc_opts *opts;
u8 *bm_controls, *iter;
int ret, n = 0;
- mutex_lock(su_mutex);
-
opts_item = item->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -1157,7 +1052,6 @@ static ssize_t uvcg_extension_bm_controls_store(struct config_item *item,
unlock:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
@@ -1467,14 +1361,10 @@ static const struct uvcg_config_group_type uvcg_control_class_grp_type = {
static ssize_t uvcg_default_control_b_interface_number_show(
struct config_item *item, char *page)
{
- struct config_group *group = to_config_group(item);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct config_item *opts_item;
struct f_uvc_opts *opts;
int result = 0;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = item->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -1482,8 +1372,6 @@ static ssize_t uvcg_default_control_b_interface_number_show(
result += sprintf(page, "%u\n", opts->control_interface);
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return result;
}
@@ -1492,14 +1380,10 @@ UVC_ATTR_RO(uvcg_default_control_, b_interface_number, bInterfaceNumber);
static ssize_t uvcg_default_control_enable_interrupt_ep_show(
struct config_item *item, char *page)
{
- struct config_group *group = to_config_group(item);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct config_item *opts_item;
struct f_uvc_opts *opts;
int result = 0;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = item->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -1507,16 +1391,12 @@ static ssize_t uvcg_default_control_enable_interrupt_ep_show(
result += sprintf(page, "%u\n", opts->enable_interrupt_ep);
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return result;
}
static ssize_t uvcg_default_control_enable_interrupt_ep_store(
struct config_item *item, const char *page, size_t len)
{
- struct config_group *group = to_config_group(item);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct config_item *opts_item;
struct f_uvc_opts *opts;
ssize_t ret;
@@ -1526,8 +1406,6 @@ static ssize_t uvcg_default_control_enable_interrupt_ep_store(
if (ret)
return ret;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = item->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -1535,8 +1413,6 @@ static ssize_t uvcg_default_control_enable_interrupt_ep_store(
opts->enable_interrupt_ep = num;
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return len;
}
UVC_ATTR(uvcg_default_control_, enable_interrupt_ep, enable_interrupt_ep);
@@ -1609,6 +1485,11 @@ static int uvcg_format_allow_link(struct config_item *src, struct config_item *t
mutex_lock(su_mutex);
+ opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
+
streaming = src->ci_parent->ci_parent;
color_matching = config_group_find_item(to_config_group(streaming), "color_matching");
if (!color_matching || color_matching != tgt->ci_parent) {
@@ -1637,6 +1518,7 @@ static int uvcg_format_allow_link(struct config_item *src, struct config_item *t
out_put_cm:
config_item_put(color_matching);
+ mutex_unlock(&opts->lock);
mutex_unlock(su_mutex);
return ret;
@@ -1651,6 +1533,11 @@ static void uvcg_format_drop_link(struct config_item *src, struct config_item *t
mutex_lock(su_mutex);
+ opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
+
color_matching_desc = to_uvcg_color_matching(to_config_group(tgt));
color_matching_desc->refcnt--;
@@ -1661,6 +1548,7 @@ static void uvcg_format_drop_link(struct config_item *src, struct config_item *t
fmt->color_matching = color_matching_desc;
color_matching_desc->refcnt++;
+ mutex_unlock(&opts->lock);
mutex_unlock(su_mutex);
}
@@ -1674,12 +1562,9 @@ static ssize_t uvcg_format_bma_controls_show(struct uvcg_format *f, char *page)
{
struct f_uvc_opts *opts;
struct config_item *opts_item;
- struct mutex *su_mutex = &f->group.cg_subsys->su_mutex;
int result, i;
char *pg = page;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -1691,8 +1576,6 @@ static ssize_t uvcg_format_bma_controls_show(struct uvcg_format *f, char *page)
pg = page + result;
}
mutex_unlock(&opts->lock);
-
- mutex_unlock(su_mutex);
return result;
}
@@ -1701,11 +1584,8 @@ static ssize_t uvcg_format_bma_controls_store(struct uvcg_format *ch,
{
struct f_uvc_opts *opts;
struct config_item *opts_item;
- struct mutex *su_mutex = &ch->group.cg_subsys->su_mutex;
int ret = -EINVAL;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = ch->group.cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -1724,7 +1604,6 @@ static ssize_t uvcg_format_bma_controls_store(struct uvcg_format *ch,
ret = len;
end:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
@@ -1853,19 +1732,14 @@ static ssize_t uvcg_streaming_header_##cname##_show( \
struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = sh->item.ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item); \
\
mutex_lock(&opts->lock); \
result = sprintf(page, "%u\n", le##bits##_to_cpu(sh->desc.aname));\
mutex_unlock(&opts->lock); \
- \
- mutex_unlock(su_mutex); \
return result; \
} \
\
@@ -1937,11 +1811,8 @@ static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
struct uvcg_frame *f = to_uvcg_frame(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item); \
\
@@ -1949,7 +1820,6 @@ static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
result = sprintf(page, "%u\n", f->frame.cname); \
mutex_unlock(&opts->lock); \
\
- mutex_unlock(su_mutex); \
return result; \
} \
\
@@ -1960,7 +1830,6 @@ static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct uvcg_format *fmt; \
- struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
typeof(f->frame.cname) num; \
int ret; \
\
@@ -1968,8 +1837,6 @@ static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
if (ret) \
return ret; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item); \
fmt = to_uvcg_format(f->item.ci_parent); \
@@ -1984,7 +1851,6 @@ static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -1998,28 +1864,25 @@ static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct config_item *fmt_item;
- struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;
int result;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
fmt_item = f->item.ci_parent;
fmt = to_uvcg_format(fmt_item);
+ opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
+
if (!fmt->linked) {
result = -EBUSY;
goto out;
}
- opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
- opts = to_f_uvc_opts(opts_item);
-
- mutex_lock(&opts->lock);
result = sprintf(page, "%u\n", f->frame.b_frame_index);
- mutex_unlock(&opts->lock);
out:
- mutex_unlock(su_mutex);
+ mutex_unlock(&opts->lock);
return result;
}
@@ -2042,12 +1905,9 @@ static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
struct uvcg_frame *frm = to_uvcg_frame(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
- struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex;
int result, i;
char *pg = page;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = frm->item.ci_parent->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -2057,8 +1917,6 @@ static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
pg = page + result;
}
mutex_unlock(&opts->lock);
-
- mutex_unlock(su_mutex);
return result;
}
@@ -2069,12 +1927,9 @@ static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct uvcg_format *fmt;
- struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;
int ret = 0, n = 0;
u32 *frm_intrv, *tmp;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = ch->item.ci_parent->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
fmt = to_uvcg_format(ch->item.ci_parent);
@@ -2110,7 +1965,6 @@ static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
end:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
@@ -2272,9 +2126,6 @@ static ssize_t uvcg_uncompressed_guid_format_show(struct config_item *item,
struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
- struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
-
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -2283,8 +2134,6 @@ static ssize_t uvcg_uncompressed_guid_format_show(struct config_item *item,
memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat));
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return sizeof(ch->desc.guidFormat);
}
@@ -2294,13 +2143,10 @@ static ssize_t uvcg_uncompressed_guid_format_store(struct config_item *item,
struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
- struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
const struct uvc_format_desc *format;
u8 tmpguidFormat[sizeof(ch->desc.guidFormat)];
int ret;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -2325,7 +2171,6 @@ static ssize_t uvcg_uncompressed_guid_format_store(struct config_item *item,
end:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
@@ -2338,11 +2183,8 @@ static ssize_t uvcg_uncompressed_##cname##_show( \
struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
opts = to_f_uvc_opts(opts_item); \
\
@@ -2350,7 +2192,6 @@ static ssize_t uvcg_uncompressed_##cname##_show( \
result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
mutex_unlock(&opts->lock); \
\
- mutex_unlock(su_mutex); \
return result; \
} \
\
@@ -2363,19 +2204,14 @@ static ssize_t uvcg_uncompressed_##cname##_show( \
struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
opts = to_f_uvc_opts(opts_item); \
\
mutex_lock(&opts->lock); \
result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
mutex_unlock(&opts->lock); \
- \
- mutex_unlock(su_mutex); \
return result; \
} \
\
@@ -2386,12 +2222,9 @@ uvcg_uncompressed_##cname##_store(struct config_item *item, \
struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int ret; \
u8 num; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
opts = to_f_uvc_opts(opts_item); \
\
@@ -2415,7 +2248,6 @@ uvcg_uncompressed_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2498,12 +2330,17 @@ static struct config_group *uvcg_uncompressed_make(struct config_group *group,
h->desc.bmInterlaceFlags = 0;
h->desc.bCopyProtect = 0;
+ opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
INIT_LIST_HEAD(&h->fmt.frames);
h->fmt.type = UVCG_UNCOMPRESSED;
h->fmt.color_matching = color_match;
color_match->refcnt++;
config_group_init_type_name(&h->fmt.group, name,
&uvcg_uncompressed_type);
+ mutex_unlock(&opts->lock);
return &h->fmt.group;
}
@@ -2536,19 +2373,14 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
opts = to_f_uvc_opts(opts_item); \
\
mutex_lock(&opts->lock); \
result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
mutex_unlock(&opts->lock); \
- \
- mutex_unlock(su_mutex); \
return result; \
} \
\
@@ -2560,11 +2392,8 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
opts = to_f_uvc_opts(opts_item); \
\
@@ -2572,7 +2401,6 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
mutex_unlock(&opts->lock); \
\
- mutex_unlock(su_mutex); \
return result; \
} \
\
@@ -2583,12 +2411,9 @@ uvcg_mjpeg_##cname##_store(struct config_item *item, \
struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int ret; \
u8 num; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
opts = to_f_uvc_opts(opts_item); \
\
@@ -2612,7 +2437,6 @@ uvcg_mjpeg_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2688,12 +2512,17 @@ static struct config_group *uvcg_mjpeg_make(struct config_group *group,
h->desc.bmInterlaceFlags = 0;
h->desc.bCopyProtect = 0;
+ opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
INIT_LIST_HEAD(&h->fmt.frames);
h->fmt.type = UVCG_MJPEG;
h->fmt.color_matching = color_match;
color_match->refcnt++;
config_group_init_type_name(&h->fmt.group, name,
&uvcg_mjpeg_type);
+ mutex_unlock(&opts->lock);
return &h->fmt.group;
}
@@ -2727,11 +2556,8 @@ static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \
struct uvcg_framebased *u = to_uvcg_framebased(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
opts = to_f_uvc_opts(opts_item); \
\
@@ -2739,7 +2565,6 @@ static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \
result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
mutex_unlock(&opts->lock); \
\
- mutex_unlock(su_mutex); \
return result; \
} \
\
@@ -2752,11 +2577,8 @@ static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \
struct uvcg_framebased *u = to_uvcg_framebased(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
opts = to_f_uvc_opts(opts_item); \
\
@@ -2764,7 +2586,6 @@ static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \
result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
mutex_unlock(&opts->lock); \
\
- mutex_unlock(su_mutex); \
return result; \
} \
\
@@ -2775,12 +2596,9 @@ uvcg_framebased_##cname##_store(struct config_item *item, \
struct uvcg_framebased *u = to_uvcg_framebased(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int ret; \
u8 num; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
opts = to_f_uvc_opts(opts_item); \
\
@@ -2802,7 +2620,6 @@ uvcg_framebased_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2824,9 +2641,6 @@ static ssize_t uvcg_framebased_guid_format_show(struct config_item *item,
struct uvcg_framebased *ch = to_uvcg_framebased(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
- struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
-
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -2835,8 +2649,6 @@ static ssize_t uvcg_framebased_guid_format_show(struct config_item *item,
memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat));
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return sizeof(ch->desc.guidFormat);
}
@@ -2846,11 +2658,8 @@ static ssize_t uvcg_framebased_guid_format_store(struct config_item *item,
struct uvcg_framebased *ch = to_uvcg_framebased(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
- struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
int ret;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -2866,7 +2675,6 @@ static ssize_t uvcg_framebased_guid_format_store(struct config_item *item,
end:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
@@ -2945,10 +2753,15 @@ static struct config_group *uvcg_framebased_make(struct config_group *group,
INIT_LIST_HEAD(&h->fmt.frames);
h->fmt.type = UVCG_FRAMEBASED;
+ opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
h->fmt.color_matching = color_match;
color_match->refcnt++;
config_group_init_type_name(&h->fmt.group, name,
&uvcg_framebased_type);
+ mutex_unlock(&opts->lock);
return &h->fmt.group;
}
@@ -2979,11 +2792,8 @@ static ssize_t uvcg_color_matching_##cname##_show( \
to_uvcg_color_matching(group); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
- struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
int result; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item); \
\
@@ -2992,7 +2802,6 @@ static ssize_t uvcg_color_matching_##cname##_show( \
le##bits##_to_cpu(color_match->desc.aname)); \
mutex_unlock(&opts->lock); \
\
- mutex_unlock(su_mutex); \
return result; \
} \
\
@@ -3000,7 +2809,6 @@ static ssize_t uvcg_color_matching_##cname##_store( \
struct config_item *item, const char *page, size_t len) \
{ \
struct config_group *group = to_config_group(item); \
- struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
struct uvcg_color_matching *color_match = \
to_uvcg_color_matching(group); \
struct f_uvc_opts *opts; \
@@ -3012,25 +2820,21 @@ static ssize_t uvcg_color_matching_##cname##_store( \
if (ret) \
return ret; \
\
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
- \
- if (color_match->refcnt) { \
- ret = -EBUSY; \
- goto unlock_su; \
- } \
- \
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item); \
\
mutex_lock(&opts->lock); \
\
+ if (color_match->refcnt) { \
+ ret = -EBUSY; \
+ goto unlock_opts_lock; \
+ } \
+ \
color_match->desc.aname = num; \
ret = len; \
\
+unlock_opts_lock: \
mutex_unlock(&opts->lock); \
-unlock_su: \
- mutex_unlock(su_mutex); \
- \
return ret; \
} \
UVC_ATTR(uvcg_color_matching_, cname, aname)
@@ -3583,14 +3387,10 @@ static const struct uvcg_config_group_type uvcg_streaming_class_grp_type = {
static ssize_t uvcg_default_streaming_b_interface_number_show(
struct config_item *item, char *page)
{
- struct config_group *group = to_config_group(item);
- struct mutex *su_mutex = &group->cg_subsys->su_mutex;
struct config_item *opts_item;
struct f_uvc_opts *opts;
int result = 0;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
opts_item = item->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -3598,8 +3398,6 @@ static ssize_t uvcg_default_streaming_b_interface_number_show(
result += sprintf(page, "%u\n", opts->streaming_interface);
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
-
return result;
}
@@ -3648,7 +3446,7 @@ static int uvc_func_allow_link(struct config_item *src, struct config_item *tgt)
struct f_uvc_opts *opts;
int ret = 0;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+ mutex_lock(su_mutex);
/* Validate that the target is an entry in strings/<langid> */
strings = config_group_find_item(to_config_group(src->ci_parent->ci_parent),
@@ -3676,6 +3474,7 @@ static int uvc_func_allow_link(struct config_item *src, struct config_item *tgt)
put_strings:
config_item_put(strings);
+
mutex_unlock(su_mutex);
return ret;
--
2.55.0
prev parent reply other threads:[~2026-11-07 4:46 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 5:39 [PATCH] usb: gadget: uvc: Fix deadlock in uvcg_extension_bm_controls_store Saad Varshani
2026-11-06 2:07 ` [PATCH v2] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks Saad Varshani
2026-11-06 3:50 ` [PATCH v3] " Saad Varshani
2026-11-06 3:57 ` [PATCH v4] " Saad Varshani
2026-11-07 4:45 ` Saad Varshani [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261107044553.24277-1-varshanisaad@gmail.com \
--to=varshanisaad@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=nkapron@google.com \
--cc=syzbot+300213c2b5b55c0244f4@syzkaller.appspotmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®