* [PATCH] usb: gadget: uvc: Fix deadlock in uvcg_extension_bm_controls_store
@ 2026-11-05 5:39 Saad Varshani
2026-11-05 6:05 ` sashiko-bot
2026-11-06 2:07 ` [PATCH v2] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks Saad Varshani
0 siblings, 2 replies; 7+ messages in thread
From: Saad Varshani @ 2026-11-05 5:39 UTC (permalink / raw)
To: nkapron, gregkh
Cc: linux-usb, linux-kernel, Saad Varshani,
syzbot+300213c2b5b55c0244f4
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.
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 | 5 -----
1 file changed, 5 deletions(-)
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 70a1415ea401..78588366f656 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -1114,16 +1114,12 @@ static ssize_t uvcg_extension_bm_controls_show(struct config_item *item,
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 +1153,6 @@ static ssize_t uvcg_extension_bm_controls_store(struct config_item *item,
unlock:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] usb: gadget: uvc: Fix deadlock in uvcg_extension_bm_controls_store
2026-11-05 5:39 [PATCH] usb: gadget: uvc: Fix deadlock in uvcg_extension_bm_controls_store Saad Varshani
@ 2026-11-05 6:05 ` sashiko-bot
2026-11-06 2:07 ` [PATCH v2] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks Saad Varshani
1 sibling, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-11-05 6:05 UTC (permalink / raw)
To: Saad Varshani; +Cc: linux-usb
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] usb: gadget: uvc: incomplete su_mutex deadlock fix across sibling configfs attributes
--
commit 352b1b2da8cde195be417fe376d9490d718f3b87
Author: Saad Varshani <varshanisaad@gmail.com>
usb: gadget: uvc: Fix deadlock in uvcg_extension_bm_controls_store
This commit removes the acquisition of group->cg_subsys->su_mutex from
uvcg_extension_bm_controls_store() to avoid a circular locking dependency
reported by syzbot in configfs_write_iter().
> diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
> index 70a1415ea4014..78588366f656f 100644
> --- a/drivers/usb/gadget/function/uvc_configfs.c
> +++ b/drivers/usb/gadget/function/uvc_configfs.c
> @@ -1114,16 +1114,12 @@ static ssize_t uvcg_extension_bm_controls_show(struct config_item *item,
> 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 +1153,6 @@ static ssize_t uvcg_extension_bm_controls_store(struct config_item *item,
>
> unlock:
> mutex_unlock(&opts->lock);
> - mutex_unlock(su_mutex);
[Severity: High]
Does removing su_mutex only from uvcg_extension_bm_controls_store() leave the
exact same deadlock present in all sibling configfs attribute callbacks in
drivers/usb/gadget/function/uvc_configfs.c?
When configfs_write_iter() -> flush_write_buffer() or configfs_read_iter() ->
fill_read_buffer() invokes an attribute callback, it already holds
buffer->mutex and down_read(&frag->frag_sem), which prevents configfs_rmdir()
from unlinking the item or its ci_parent hierarchy.
However, the sibling store and show callbacks on struct uvcg_extension still
acquire group->cg_subsys->su_mutex before opts->lock in the same way:
drivers/usb/gadget/function/uvc_configfs.c:uvcg_extension_ba_source_id_store() {
struct config_group *group = to_config_group(item->ci_parent);
struct mutex *su_mutex = &group->cg_subsys->su_mutex;
...
mutex_lock(su_mutex);
opts_item = item->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
mutex_lock(&opts->lock);
}
The same locking pattern remains in uvcg_extension_b_control_size_store(),
uvcg_extension_b_nr_in_pins_store(), uvcg_extension_b_num_controls_store(),
uvcg_extension_guid_extension_code_store(), uvcg_extension_bm_controls_show(),
uvcg_extension_ba_source_id_show(), uvcg_extension_guid_extension_code_show(),
and the other configfs attribute show/store callbacks throughout
drivers/usb/gadget/function/uvc_configfs.c (such as
uvcg_default_processing_bm_controls_store(),
uvcg_default_camera_bm_controls_store(), and
uvcg_frame_dw_frame_interval_store()).
Should su_mutex be removed consistently across these configfs attribute
callbacks, and could the commit message also describe the lock dependency
chain and why traversing item->ci_parent is safe without su_mutex?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261105053900.20082-1-varshanisaad@gmail.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks
2026-11-05 5:39 [PATCH] usb: gadget: uvc: Fix deadlock in uvcg_extension_bm_controls_store Saad Varshani
2026-11-05 6:05 ` sashiko-bot
@ 2026-11-06 2:07 ` Saad Varshani
2026-11-06 2:21 ` sashiko-bot
` (2 more replies)
1 sibling, 3 replies; 7+ messages in thread
From: Saad Varshani @ 2026-11-06 2:07 UTC (permalink / raw)
To: varshanisaad
Cc: gregkh, linux-kernel, linux-usb, nkapron,
syzbot+300213c2b5b55c0244f4
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
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 | 235 ---------------------
1 file changed, 235 deletions(-)
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 70a1415ea401..6a4f17b925e7 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);
@@ -1077,8 +983,6 @@ static ssize_t uvcg_extension_ba_source_id_store(struct config_item *item,
ret = len;
unlock:
- mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
UVC_ATTR(uvcg_extension_, ba_source_id, baSourceID);
@@ -1086,16 +990,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 +1006,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 +1051,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 +1360,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 +1371,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 +1379,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 +1390,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 +1405,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 +1412,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);
@@ -1674,12 +1549,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 +1563,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 +1571,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 +1591,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 +1719,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 +1798,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 +1807,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 +1817,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 +1824,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 +1838,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,11 +1851,8 @@ 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);
@@ -2019,7 +1869,6 @@ static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
mutex_unlock(&opts->lock);
out:
- mutex_unlock(su_mutex);
return result;
}
@@ -2042,12 +1891,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 +1903,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 +1913,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 +1951,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 +2112,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 +2120,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 +2129,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 +2157,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 +2169,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 +2178,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 +2190,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 +2208,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 +2234,6 @@ uvcg_uncompressed_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2536,19 +2354,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 +2373,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 +2382,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 +2392,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 +2418,6 @@ uvcg_mjpeg_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2727,11 +2532,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 +2541,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 +2553,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 +2562,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 +2572,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 +2596,6 @@ uvcg_framebased_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2824,9 +2617,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 +2625,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 +2634,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 +2651,6 @@ static ssize_t uvcg_framebased_guid_format_store(struct config_item *item,
end:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
@@ -2979,11 +2763,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 +2773,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 +2780,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,8 +2791,6 @@ 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; \
@@ -3029,8 +2806,6 @@ static ssize_t uvcg_color_matching_##cname##_store( \
\
mutex_unlock(&opts->lock); \
unlock_su: \
- mutex_unlock(su_mutex); \
- \
return ret; \
} \
UVC_ATTR(uvcg_color_matching_, cname, aname)
@@ -3583,14 +3358,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 +3369,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;
}
@@ -3642,14 +3411,11 @@ static void uvc_func_item_release(struct config_item *item)
static int uvc_func_allow_link(struct config_item *src, struct config_item *tgt)
{
- struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
struct gadget_string *string;
struct config_item *strings;
struct f_uvc_opts *opts;
int ret = 0;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
/* Validate that the target is an entry in strings/<langid> */
strings = config_group_find_item(to_config_group(src->ci_parent->ci_parent),
"strings");
@@ -3676,7 +3442,6 @@ 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
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks
2026-11-06 2:07 ` [PATCH v2] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks Saad Varshani
@ 2026-11-06 2:21 ` sashiko-bot
2026-11-06 3:50 ` [PATCH v3] " Saad Varshani
2026-11-06 3:57 ` [PATCH v4] " Saad Varshani
2 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-11-06 2:21 UTC (permalink / raw)
To: Saad Varshani; +Cc: linux-usb
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] usb: gadget: uvc: missing mutex_unlock() in uvcg_extension_ba_source_id_store()
- [High] usb: gadget: uvc: unlocked hierarchy traversal in uvc_func_allow_link()
- [Medium] usb: gadget: uvc: unsynchronized refcnt check in uvcg_color_matching store
- [Medium] usb: gadget: uvc: unlocked fmt->linked check in uvcg_frame_b_frame_index_show()
--
commit 79cf2a23edc28ab90194ff7fd9c348a2fe889c55
Author: Saad Varshani <varshanisaad@gmail.com>
usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks
This commit removes su_mutex locking from configfs callbacks in
drivers/usb/gadget/function/uvc_configfs.c to avoid a lock ordering
deadlock between configfs frag_sem and su_mutex.
> diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
> index 70a1415ea4014..6a4f17b925e75 100644
> --- a/drivers/usb/gadget/function/uvc_configfs.c
> +++ b/drivers/usb/gadget/function/uvc_configfs.c
[ ... ]
> @@ -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);
>
> @@ -1077,8 +983,6 @@ static ssize_t uvcg_extension_ba_source_id_store(struct config_item *item,
> ret = len;
>
> unlock:
> - mutex_unlock(&opts->lock);
> - mutex_unlock(su_mutex);
> return ret;
> }
> UVC_ATTR(uvcg_extension_, ba_source_id, baSourceID);
[Severity: High]
Was mutex_unlock(&opts->lock) removed by mistake at the unlock label in
uvcg_extension_ba_source_id_store()?
The function still acquires mutex_lock(&opts->lock) after resolving opts,
and both the normal path and all error paths go through the unlock label.
Writing to the baSourceID configfs attribute via configfs_write_iter() ->
flush_write_buffer() -> uvcg_extension_ba_source_id_store() will now return
to userspace with opts->lock still held, permanently deadlocking subsequent
operations on the UVC function instance.
[ ... ]
> @@ -1998,11 +1851,8 @@ 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);
>
> @@ -2019,7 +1869,6 @@ static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
> mutex_unlock(&opts->lock);
>
> out:
> - mutex_unlock(su_mutex);
> return result;
> }
[Severity: Medium]
With su_mutex removed from uvcg_frame_b_frame_index_show(), should the
check on fmt->linked be moved inside mutex_lock(&opts->lock)?
In uvcg_frame_b_frame_index_show():
fmt_item = f->item.ci_parent;
fmt = to_uvcg_format(fmt_item);
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);
Both fmt->linked and f->frame.b_frame_index (via uvcg_format_set_indices())
are updated under su_mutex and opts->lock in
uvcg_streaming_header_allow_link() and uvcg_streaming_header_drop_link().
Checking fmt->linked before acquiring opts->lock leaves a race window when
reading bFrameIndex concurrently with linking or unlinking a format.
[ ... ]
> @@ -3000,7 +2780,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,8 +2791,6 @@ 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; \
> @@ -3029,8 +2806,6 @@ static ssize_t uvcg_color_matching_##cname##_store( \
> \
> mutex_unlock(&opts->lock); \
> unlock_su: \
> - mutex_unlock(su_mutex); \
> - \
> return ret; \
> } \
> UVC_ATTR(uvcg_color_matching_, cname, aname)
[Severity: Medium]
What protects color_match->refcnt in uvcg_color_matching_##cname##_store()
now that su_mutex is no longer held here?
color_match->refcnt is checked before mutex_lock(&opts->lock) is acquired,
and the callers that modify color_match->refcnt (uvcg_format_allow_link(),
uvcg_format_drop_link(), uvcg_uncompressed_make(), uvcg_mjpeg_make(), and
uvcg_framebased_make()) update it under su_mutex without taking opts->lock:
color_matching_desc->refcnt--;
color_matching_desc = to_uvcg_color_matching(to_config_group(tgt));
fmt->color_matching = color_matching_desc;
color_matching_desc->refcnt++;
Without synchronization between uvcg_color_matching_##cname##_store() and
those refcnt updates, can a concurrent mkdir, symlink, or unlink race with
attribute writes and allow modifying an active color_matching descriptor?
[ ... ]
> @@ -3642,14 +3411,11 @@ static void uvc_func_item_release(struct config_item *item)
>
> static int uvc_func_allow_link(struct config_item *src, struct config_item *tgt)
> {
> - struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
> struct gadget_string *string;
> struct config_item *strings;
> struct f_uvc_opts *opts;
> int ret = 0;
>
> - mutex_lock(su_mutex); /* for navigating configfs hierarchy */
> -
> /* Validate that the target is an entry in strings/<langid> */
> strings = config_group_find_item(to_config_group(src->ci_parent->ci_parent),
> "strings");
> @@ -3676,7 +3442,6 @@ 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;
> }
[Severity: High]
Is it safe to remove su_mutex from uvc_func_allow_link()?
Unlike attribute show and store callbacks, uvc_func_allow_link() is an
allow_link callback invoked from configfs_symlink(), which does not hold
frag_sem or su_mutex:
if (!ret)
ret = type->ct_item_ops->allow_link(parent_item, target_item);
if (!ret) {
mutex_lock(&configfs_symlink_mutex);
ret = create_link(parent_item, target_item, target_sd, dentry);
mutex_unlock(&configfs_symlink_mutex);
uvc_func_allow_link() calls config_group_find_item(), which walks
group->cg_children and requires group->cg_subsys->su_mutex to be held
against concurrent configfs_mkdir() and configfs_rmdir() modifications.
In addition, before create_link() increments target_sd->s_links, a
concurrent configfs_rmdir() on tgt can run unlink_obj() under su_mutex:
group = item->ci_group;
if (group) {
list_del_init(&item->ci_entry);
item->ci_group = NULL;
item->ci_parent = NULL;
/* Drop the reference for ci_entry */
config_item_put(item);
/* Drop the reference for ci_parent */
config_group_put(group);
}
Without su_mutex, couldn't evaluating tgt->ci_parent->ci_parent != strings
in uvc_func_allow_link() race with unlink_obj(tgt) and dereference a NULL
or freed ci_parent?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261106020727.6055-1-varshanisaad@gmail.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks
2026-11-06 2:07 ` [PATCH v2] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks Saad Varshani
2026-11-06 2:21 ` sashiko-bot
@ 2026-11-06 3:50 ` Saad Varshani
2026-11-06 3:57 ` [PATCH v4] " Saad Varshani
2 siblings, 0 replies; 7+ messages in thread
From: Saad Varshani @ 2026-11-06 3:50 UTC (permalink / raw)
To: nkapron, gregkh
Cc: linux-usb, linux-kernel, Saad Varshani,
syzbot+300213c2b5b55c0244f4
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.
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 | 235 ---------------------
1 file changed, 235 deletions(-)
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 70a1415ea401..6a4f17b925e7 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);
@@ -1077,8 +983,6 @@ static ssize_t uvcg_extension_ba_source_id_store(struct config_item *item,
ret = len;
unlock:
- mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
UVC_ATTR(uvcg_extension_, ba_source_id, baSourceID);
@@ -1086,16 +990,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 +1006,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 +1051,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 +1360,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 +1371,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 +1379,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 +1390,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 +1405,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 +1412,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);
@@ -1674,12 +1549,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 +1563,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 +1571,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 +1591,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 +1719,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 +1798,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 +1807,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 +1817,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 +1824,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 +1838,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,11 +1851,8 @@ 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);
@@ -2019,7 +1869,6 @@ static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
mutex_unlock(&opts->lock);
out:
- mutex_unlock(su_mutex);
return result;
}
@@ -2042,12 +1891,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 +1903,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 +1913,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 +1951,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 +2112,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 +2120,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 +2129,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 +2157,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 +2169,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 +2178,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 +2190,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 +2208,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 +2234,6 @@ uvcg_uncompressed_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2536,19 +2354,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 +2373,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 +2382,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 +2392,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 +2418,6 @@ uvcg_mjpeg_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2727,11 +2532,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 +2541,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 +2553,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 +2562,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 +2572,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 +2596,6 @@ uvcg_framebased_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2824,9 +2617,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 +2625,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 +2634,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 +2651,6 @@ static ssize_t uvcg_framebased_guid_format_store(struct config_item *item,
end:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
@@ -2979,11 +2763,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 +2773,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 +2780,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,8 +2791,6 @@ 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; \
@@ -3029,8 +2806,6 @@ static ssize_t uvcg_color_matching_##cname##_store( \
\
mutex_unlock(&opts->lock); \
unlock_su: \
- mutex_unlock(su_mutex); \
- \
return ret; \
} \
UVC_ATTR(uvcg_color_matching_, cname, aname)
@@ -3583,14 +3358,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 +3369,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;
}
@@ -3642,14 +3411,11 @@ static void uvc_func_item_release(struct config_item *item)
static int uvc_func_allow_link(struct config_item *src, struct config_item *tgt)
{
- struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
struct gadget_string *string;
struct config_item *strings;
struct f_uvc_opts *opts;
int ret = 0;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
-
/* Validate that the target is an entry in strings/<langid> */
strings = config_group_find_item(to_config_group(src->ci_parent->ci_parent),
"strings");
@@ -3676,7 +3442,6 @@ 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
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v4] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks
2026-11-06 2:07 ` [PATCH v2] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks Saad Varshani
2026-11-06 2:21 ` sashiko-bot
2026-11-06 3:50 ` [PATCH v3] " Saad Varshani
@ 2026-11-06 3:57 ` Saad Varshani
2026-11-06 4:09 ` sashiko-bot
2 siblings, 1 reply; 7+ messages in thread
From: Saad Varshani @ 2026-11-06 3:57 UTC (permalink / raw)
To: nkapron, gregkh
Cc: linux-usb, linux-kernel, Saad Varshani,
syzbot+300213c2b5b55c0244f4
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.
---
v4 changes:
- Forgot to properly commit the codebase, and thus resent old
patch
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 | 254 ++-------------------
1 file changed, 13 insertions(+), 241 deletions(-)
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 70a1415ea401..606c02214c8c 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);
@@ -1674,12 +1550,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 +1564,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 +1572,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 +1592,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 +1720,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 +1799,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 +1808,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 +1818,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 +1825,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 +1839,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 +1852,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 +1893,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 +1905,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 +1915,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 +1953,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 +2114,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 +2122,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 +2131,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 +2159,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 +2171,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 +2180,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 +2192,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 +2210,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 +2236,6 @@ uvcg_uncompressed_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2536,19 +2356,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 +2375,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 +2384,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 +2394,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 +2420,6 @@ uvcg_mjpeg_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2727,11 +2534,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 +2543,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 +2555,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 +2564,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 +2574,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 +2598,6 @@ uvcg_framebased_##cname##_store(struct config_item *item, \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
- mutex_unlock(su_mutex); \
return ret; \
} \
\
@@ -2824,9 +2619,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 +2627,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 +2636,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 +2653,6 @@ static ssize_t uvcg_framebased_guid_format_store(struct config_item *item,
end:
mutex_unlock(&opts->lock);
- mutex_unlock(su_mutex);
return ret;
}
@@ -2979,11 +2765,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 +2775,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 +2782,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 +2793,21 @@ static ssize_t uvcg_color_matching_##cname##_store( \
if (ret) \
return ret; \
\
- 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); \
+ \
+ mutex_lock(&opts->lock); \
\
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); \
- \
color_match->desc.aname = num; \
ret = len; \
\
- mutex_unlock(&opts->lock); \
unlock_su: \
- mutex_unlock(su_mutex); \
- \
+ mutex_unlock(&opts->lock); \
return ret; \
} \
UVC_ATTR(uvcg_color_matching_, cname, aname)
@@ -3583,14 +3360,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 +3371,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 +3419,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 +3447,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
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v4] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks
2026-11-06 3:57 ` [PATCH v4] " Saad Varshani
@ 2026-11-06 4:09 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-11-06 4:09 UTC (permalink / raw)
To: Saad Varshani; +Cc: linux-usb
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] usb: gadget: uvc: unsynchronized refcnt check in uvcg_color_matching store
--
commit 52f34f2adcf8a7a6589075037a07a9887a733e9b
Author: Saad Varshani <varshanisaad@gmail.com>
usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks
This commit removes su_mutex locking from uvcg_configfs attribute show and
store callbacks to resolve a circular lock dependency with configfs
frag_sem, and moves the fmt->linked and color_match->refcnt checks under
opts->lock.
> diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
> index 70a1415ea4014..606c02214c8ce 100644
> --- a/drivers/usb/gadget/function/uvc_configfs.c
> +++ b/drivers/usb/gadget/function/uvc_configfs.c
[ ... ]
> @@ -3000,7 +2782,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 +2793,21 @@ static ssize_t uvcg_color_matching_##cname##_store( \
> if (ret) \
> return ret; \
> \
> - 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); \
> + \
> + mutex_lock(&opts->lock); \
> \
> 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); \
> - \
> color_match->desc.aname = num; \
> ret = len; \
> \
> - mutex_unlock(&opts->lock); \
> unlock_su: \
> - mutex_unlock(su_mutex); \
> - \
> + mutex_unlock(&opts->lock); \
> return ret; \
> } \
> UVC_ATTR(uvcg_color_matching_, cname, aname)
[Severity: Medium]
As reported by Sashiko on v2 [1], does moving the color_match->refcnt check
under opts->lock after dropping su_mutex in UVCG_COLOR_MATCHING_ATTR leave
color_match->refcnt and color_match->desc unsynchronized against concurrent
modifications?
Unlike fmt->linked in uvcg_frame_b_frame_index_show(), all functions that
modify color_match->refcnt execute under su_mutex without acquiring
opts->lock. Specifically, uvcg_format_allow_link() and
uvcg_format_drop_link() update color_matching_desc->refcnt while holding
only su_mutex:
drivers/usb/gadget/function/uvc_configfs.c:uvcg_format_allow_link() {
...
color_matching_desc->refcnt--;
color_matching_desc = to_uvcg_color_matching(to_config_group(tgt));
fmt->color_matching = color_matching_desc;
color_matching_desc->refcnt++;
...
}
drivers/usb/gadget/function/uvc_configfs.c:uvcg_format_drop_link() {
...
color_matching_desc = to_uvcg_color_matching(to_config_group(tgt));
color_matching_desc->refcnt--;
streaming = src->ci_parent->ci_parent;
color_matching_desc = uvcg_format_get_default_color_match(streaming);
fmt = to_uvcg_format(src);
fmt->color_matching = color_matching_desc;
color_matching_desc->refcnt++;
...
}
Similarly, uvcg_uncompressed_make(), uvcg_mjpeg_make(), and
uvcg_framebased_make() increment the default color_match->refcnt under
su_mutex (held by configfs_mkdir()) without holding opts->lock:
drivers/usb/gadget/function/uvc_configfs.c:uvcg_uncompressed_make() {
...
h->fmt.color_matching = color_match;
color_match->refcnt++;
...
}
Can a concurrent symlink, unlink, or mkdir operation increment
color_match->refcnt and link color_match to a format while
uvcg_color_matching_##cname##_store() observes color_match->refcnt == 0 and
mutates color_match->desc.aname?
(Also, the error label in uvcg_color_matching_##cname##_store() is still
named unlock_su even though it now unlocks opts->lock.)
[1] https://lore.kernel.org/r/20261106020727.6055-1-varshanisaad@gmail.com
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261106035732.27338-1-varshanisaad@gmail.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-11-06 4:09 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-05 5:39 [PATCH] usb: gadget: uvc: Fix deadlock in uvcg_extension_bm_controls_store Saad Varshani
2026-11-05 6:05 ` sashiko-bot
2026-11-06 2:07 ` [PATCH v2] usb: gadget: uvc: Fix deadlocks in uvcg_configfs attribute callbacks Saad Varshani
2026-11-06 2:21 ` sashiko-bot
2026-11-06 3:50 ` [PATCH v3] " Saad Varshani
2026-11-06 3:57 ` [PATCH v4] " Saad Varshani
2026-11-06 4:09 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox