* [PATCH 0/2][RFC] Refactor snd primitives refcounters
@ 2023-08-24 21:02 cujomalainey
2023-08-24 21:02 ` [PATCH 1/2] ALSA: core: add snd_device_init cujomalainey
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: cujomalainey @ 2023-08-24 21:02 UTC (permalink / raw)
To: alsa-devel; +Cc: Curtis Malainey
From: Curtis Malainey <cujomalainey@chromium.org>
As previously identified in [1] there are some issues with how kobjs are
handled in sound/core. The solution provided in [2] is a workaround for
the issues to fix the failures.
This series is a first attempt at the larger refactor needed to properly
handle the objects.
[1] https://mailman.alsa-project.org/hyperkitty/list/alsa-devel@alsa-project.org/message/3B2VMPFATCJCRD76DM36LZAICPDP2R6A/
[2] https://mailman.alsa-project.org/hyperkitty/list/alsa-devel@alsa-project.org/message/JZIPB4OIC3OK6YAGTPMAEKXMLUWM5PTA/
Curtis Malainey (2):
ALSA: core: add snd_device_init
ALSA: core: split control primitives out of snd_card
include/sound/control.h | 1 +
include/sound/core.h | 34 +--
sound/core/control.c | 330 +++++++++++++----------
sound/core/control_compat.c | 8 +-
sound/core/control_led.c | 18 +-
sound/core/init.c | 33 +--
sound/pci/hda/hda_codec.c | 3 +-
sound/soc/intel/atom/sst-atom-controls.c | 8 +-
sound/soc/soc-card.c | 2 +-
sound/usb/media.c | 2 +-
10 files changed, 249 insertions(+), 190 deletions(-)
--
2.42.0.rc1.204.g551eb34607-goog
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/2] ALSA: core: add snd_device_init
2023-08-24 21:02 [PATCH 0/2][RFC] Refactor snd primitives refcounters cujomalainey
@ 2023-08-24 21:02 ` cujomalainey
2023-08-24 22:23 ` kernel test robot
2023-08-25 10:46 ` Takashi Iwai
2023-08-24 21:02 ` [PATCH 2/2] ALSA: core: split control primitives out of snd_card cujomalainey
2023-08-25 11:15 ` [PATCH 0/2][RFC] Refactor snd primitives refcounters Takashi Iwai
2 siblings, 2 replies; 10+ messages in thread
From: cujomalainey @ 2023-08-24 21:02 UTC (permalink / raw)
To: alsa-devel
Cc: Curtis Malainey, Jaroslav Kysela, Takashi Iwai, Thierry Reding,
Uwe Kleine-König, Ivan Orlov
From: Curtis Malainey <cujomalainey@chromium.org>
Begin allowing refactored modules to allocate their own device but use a
common initialization procedure for their devices.
Signed-off-by: Curtis Malainey <cujomalainey@chromium.org>
---
include/sound/core.h | 1 +
sound/core/init.c | 19 ++++++++++++++++---
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/include/sound/core.h b/include/sound/core.h
index dfef0c9d4b9f7..a4744e142c7e3 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -240,6 +240,7 @@ extern struct dentry *sound_debugfs_root;
void snd_request_card(int card);
int snd_device_alloc(struct device **dev_p, struct snd_card *card);
+void snd_device_init(struct device *dev, struct snd_card *card);
int snd_register_device(int type, struct snd_card *card, int dev,
const struct file_operations *f_ops,
diff --git a/sound/core/init.c b/sound/core/init.c
index d61bde1225f23..37a8e4791f781 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -132,15 +132,28 @@ int snd_device_alloc(struct device **dev_p, struct snd_card *card)
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
+ snd_device_init(dev, card);
+ *dev_p = dev;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_device_alloc);
+
+/**
+ * snd_device_init - Initialize struct device for sound devices
+ * @dev_p: pointer to store the allocated device
+ * @card: card to assign, optional
+ *
+ * For releasing the allocated device, call put_device().
+ */
+void snd_device_init(struct device *dev, struct snd_card *card)
+{
device_initialize(dev);
if (card)
dev->parent = &card->card_dev;
dev->class = &sound_class;
dev->release = default_release_alloc;
- *dev_p = dev;
- return 0;
}
-EXPORT_SYMBOL_GPL(snd_device_alloc);
+EXPORT_SYMBOL_GPL(snd_device_init);
static int snd_card_init(struct snd_card *card, struct device *parent,
int idx, const char *xid, struct module *module,
--
2.42.0.rc1.204.g551eb34607-goog
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/2] ALSA: core: split control primitives out of snd_card
2023-08-24 21:02 [PATCH 0/2][RFC] Refactor snd primitives refcounters cujomalainey
2023-08-24 21:02 ` [PATCH 1/2] ALSA: core: add snd_device_init cujomalainey
@ 2023-08-24 21:02 ` cujomalainey
2023-08-24 21:15 ` Mark Brown
` (2 more replies)
2023-08-25 11:15 ` [PATCH 0/2][RFC] Refactor snd primitives refcounters Takashi Iwai
2 siblings, 3 replies; 10+ messages in thread
From: cujomalainey @ 2023-08-24 21:02 UTC (permalink / raw)
To: alsa-devel
Cc: Curtis Malainey, Jaroslav Kysela, Takashi Iwai, Cezary Rojewski,
Pierre-Louis Bossart, Liam Girdwood, Peter Ujfalusi, Bard Liao,
Ranjani Sridharan, Kai Vehmanen, Mark Brown, Dan Carpenter,
Maciej S. Szmigiero, Clement Lecigne, Min-Hua Chen, Ivan Orlov,
Greg Kroah-Hartman, Thierry Reding, Geoff Levand,
Uwe Kleine-König, Kuninori Morimoto
From: Curtis Malainey <cujomalainey@chromium.org>
Having two kobj in the same struct is broken at its core. This splits
card_dev from ctl_dev so they can properly refcount and release on their
own schedules without the workaround of having them being just a
pointer.
Signed-off-by: Curtis Malainey <cujomalainey@chromium.org>
---
include/sound/control.h | 1 +
include/sound/core.h | 33 +--
sound/core/control.c | 330 +++++++++++++----------
sound/core/control_compat.c | 8 +-
sound/core/control_led.c | 18 +-
sound/core/init.c | 14 +-
sound/pci/hda/hda_codec.c | 3 +-
sound/soc/intel/atom/sst-atom-controls.c | 8 +-
sound/soc/soc-card.c | 2 +-
sound/usb/media.c | 2 +-
10 files changed, 232 insertions(+), 187 deletions(-)
diff --git a/include/sound/control.h b/include/sound/control.h
index 9a4f4f7138da8..32920f33eb47e 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -128,6 +128,7 @@ typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card,
struct snd_ctl_file * control,
unsigned int cmd, unsigned long arg);
+int snd_control_new(struct snd_card * card);
void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id);
void snd_ctl_notify_one(struct snd_card * card, unsigned int mask, struct snd_kcontrol * kctl, unsigned int ioff);
diff --git a/include/sound/core.h b/include/sound/core.h
index a4744e142c7e3..93048a7a800f4 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -95,21 +95,7 @@ struct snd_card {
void (*private_free) (struct snd_card *card); /* callback for freeing of
private data */
struct list_head devices; /* devices */
-
- struct device *ctl_dev; /* control device */
- unsigned int last_numid; /* last used numeric ID */
- struct rw_semaphore controls_rwsem; /* controls lock (list and values) */
- rwlock_t ctl_files_rwlock; /* ctl_files list lock */
- int controls_count; /* count of all controls */
- size_t user_ctl_alloc_size; // current memory allocation by user controls.
- struct list_head controls; /* all controls for this card */
- struct list_head ctl_files; /* active control files */
-#ifdef CONFIG_SND_CTL_FAST_LOOKUP
- struct xarray ctl_numids; /* hash table for numids */
- struct xarray ctl_hash; /* hash table for ctl id matching */
- bool ctl_hash_collision; /* ctl_hash collision seen? */
-#endif
-
+ struct snd_control *ctl; /* control devices */
struct snd_info_entry *proc_root; /* root for soundcard specific files */
struct proc_dir_entry *proc_root_link; /* number link to real id */
@@ -147,6 +133,23 @@ struct snd_card {
#endif
};
+struct snd_control
+{
+ struct device dev; /* control device */
+ struct rw_semaphore controls_rwsem; /* controls lock (list and values) */
+ rwlock_t files_rwlock; /* ctl_files list lock */
+ int controls_count; /* count of all controls */
+ size_t user_ctl_alloc_size; // current memory allocation by user controls.
+ struct list_head controls; /* all controls for this card */
+ struct list_head files; /* active control files */
+ unsigned int last_numid; /* last used numeric ID */
+#ifdef CONFIG_SND_CTL_FAST_LOOKUP
+ struct xarray numids; /* hash table for numids */
+ struct xarray hash; /* hash table for ctl id matching */
+ bool hash_collision; /* ctl_hash collision seen? */
+#endif
+};
+
#define dev_to_snd_card(p) container_of(p, struct snd_card, card_dev)
#ifdef CONFIG_PM
diff --git a/sound/core/control.c b/sound/core/control.c
index 59c8658966d4c..09066d05a8800 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -41,12 +41,49 @@ static struct snd_ctl_layer_ops *snd_ctl_layer;
static int snd_ctl_remove_locked(struct snd_card *card,
struct snd_kcontrol *kcontrol);
+/**
+ * snd_control_new - Allocate and initialize snd_control
+ * @card: the card to be initialized
+ *
+ * This function creates and initializes snd_control
+ */
+int snd_control_new(struct snd_card *card)
+{
+ struct snd_control *ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
+ int err;
+
+ if (snd_BUG_ON(!card))
+ return -EINVAL;
+ if (!ctl)
+ return -ENOMEM;
+
+ init_rwsem(&ctl->controls_rwsem);
+ rwlock_init(&ctl->files_rwlock);
+ INIT_LIST_HEAD(&ctl->controls);
+ INIT_LIST_HEAD(&ctl->files);
+#ifdef CONFIG_SND_CTL_FAST_LOOKUP
+ xa_init(&ctl->numids);
+ xa_init(&ctl->hash);
+#endif
+ card->ctl = ctl;
+ /* the control interface cannot be accessed from the user space until */
+ /* snd_cards_bitmask and snd_cards are set with snd_card_register */
+ err = snd_ctl_create(card);
+ if (err < 0) {
+ dev_err(card->dev, "unable to register control minors\n");
+ kfree(ctl);
+ return err;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(snd_control_new);
static int snd_ctl_open(struct inode *inode, struct file *file)
{
unsigned long flags;
struct snd_card *card;
- struct snd_ctl_file *ctl;
+ struct snd_control *ctl;
+ struct snd_ctl_file *ctlf;
int i, err;
err = stream_open(inode, file);
@@ -58,6 +95,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
err = -ENODEV;
goto __error1;
}
+ ctl = card->ctl;
err = snd_card_file_add(card, file);
if (err < 0) {
err = -ENODEV;
@@ -67,22 +105,22 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
err = -EFAULT;
goto __error2;
}
- ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
- if (ctl == NULL) {
+ ctlf = kzalloc(sizeof(*ctlf), GFP_KERNEL);
+ if (ctlf == NULL) {
err = -ENOMEM;
goto __error;
}
- INIT_LIST_HEAD(&ctl->events);
- init_waitqueue_head(&ctl->change_sleep);
- spin_lock_init(&ctl->read_lock);
- ctl->card = card;
+ INIT_LIST_HEAD(&ctlf->events);
+ init_waitqueue_head(&ctlf->change_sleep);
+ spin_lock_init(&ctlf->read_lock);
+ ctlf->card = card;
for (i = 0; i < SND_CTL_SUBDEV_ITEMS; i++)
- ctl->preferred_subdevice[i] = -1;
- ctl->pid = get_pid(task_pid(current));
- file->private_data = ctl;
- write_lock_irqsave(&card->ctl_files_rwlock, flags);
- list_add_tail(&ctl->list, &card->ctl_files);
- write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
+ ctlf->preferred_subdevice[i] = -1;
+ ctlf->pid = get_pid(task_pid(current));
+ file->private_data = ctlf;
+ write_lock_irqsave(&ctl->files_rwlock, flags);
+ list_add_tail(&ctlf->list, &ctl->files);
+ write_unlock_irqrestore(&ctl->files_rwlock, flags);
snd_card_unref(card);
return 0;
@@ -113,27 +151,26 @@ static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl)
static int snd_ctl_release(struct inode *inode, struct file *file)
{
unsigned long flags;
- struct snd_card *card;
- struct snd_ctl_file *ctl;
+ struct snd_ctl_file *ctlf = file->private_data;
+ struct snd_card *card = ctlf->card;
+ struct snd_control *ctl = card->ctl;
struct snd_kcontrol *control;
unsigned int idx;
- ctl = file->private_data;
file->private_data = NULL;
- card = ctl->card;
- write_lock_irqsave(&card->ctl_files_rwlock, flags);
- list_del(&ctl->list);
- write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
- down_write(&card->controls_rwsem);
- list_for_each_entry(control, &card->controls, list)
+ write_lock_irqsave(&ctl->files_rwlock, flags);
+ list_del(&ctlf->list);
+ write_unlock_irqrestore(&ctl->files_rwlock, flags);
+ down_write(&ctl->controls_rwsem);
+ list_for_each_entry(control, &ctl->controls, list)
for (idx = 0; idx < control->count; idx++)
- if (control->vd[idx].owner == ctl)
+ if (control->vd[idx].owner == ctlf)
control->vd[idx].owner = NULL;
- up_write(&card->controls_rwsem);
- snd_fasync_free(ctl->fasync);
- snd_ctl_empty_read_queue(ctl);
- put_pid(ctl->pid);
- kfree(ctl);
+ up_write(&ctl->controls_rwsem);
+ snd_fasync_free(ctlf->fasync);
+ snd_ctl_empty_read_queue(ctlf);
+ put_pid(ctlf->pid);
+ kfree(ctlf);
module_put(card->module);
snd_card_file_remove(card, file);
return 0;
@@ -160,11 +197,11 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
return;
if (card->shutdown)
return;
- read_lock_irqsave(&card->ctl_files_rwlock, flags);
+ read_lock_irqsave(&card->ctl->files_rwlock, flags);
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
card->mixer_oss_change_count++;
#endif
- list_for_each_entry(ctl, &card->ctl_files, list) {
+ list_for_each_entry(ctl, &card->ctl->files, list) {
if (!ctl->subscribed)
continue;
spin_lock(&ctl->read_lock);
@@ -187,7 +224,7 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
spin_unlock(&ctl->read_lock);
snd_kill_fasync(ctl->fasync, SIGIO, POLL_IN);
}
- read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
+ read_unlock_irqrestore(&card->ctl->files_rwlock, flags);
}
EXPORT_SYMBOL(snd_ctl_notify);
@@ -341,13 +378,13 @@ static bool snd_ctl_remove_numid_conflict(struct snd_card *card,
struct snd_kcontrol *kctl;
/* Make sure that the ids assigned to the control do not wrap around */
- if (card->last_numid >= UINT_MAX - count)
- card->last_numid = 0;
+ if (card->ctl->last_numid >= UINT_MAX - count)
+ card->ctl->last_numid = 0;
- list_for_each_entry(kctl, &card->controls, list) {
- if (kctl->id.numid < card->last_numid + 1 + count &&
- kctl->id.numid + kctl->count > card->last_numid + 1) {
- card->last_numid = kctl->id.numid + kctl->count - 1;
+ list_for_each_entry(kctl, &card->ctl->controls, list) {
+ if (kctl->id.numid < card->ctl->last_numid + 1 + count &&
+ kctl->id.numid + kctl->count > card->ctl->last_numid + 1) {
+ card->ctl->last_numid = kctl->id.numid + kctl->count - 1;
return true;
}
}
@@ -406,18 +443,19 @@ static void add_hash_entries(struct snd_card *card,
struct snd_kcontrol *kcontrol)
{
struct snd_ctl_elem_id id = kcontrol->id;
+ struct snd_control *ctl = card->ctl;
int i;
- xa_store_range(&card->ctl_numids, kcontrol->id.numid,
+ xa_store_range(&ctl->numids, kcontrol->id.numid,
kcontrol->id.numid + kcontrol->count - 1,
kcontrol, GFP_KERNEL);
for (i = 0; i < kcontrol->count; i++) {
id.index = kcontrol->id.index + i;
- if (xa_insert(&card->ctl_hash, get_ctl_id_hash(&id),
+ if (xa_insert(&ctl->hash, get_ctl_id_hash(&id),
kcontrol, GFP_KERNEL)) {
/* skip hash for this entry, noting we had collision */
- card->ctl_hash_collision = true;
+ ctl->hash_collision = true;
dev_dbg(card->dev, "ctl_hash collision %d:%s:%d\n",
id.iface, id.name, id.index);
}
@@ -429,17 +467,18 @@ static void remove_hash_entries(struct snd_card *card,
struct snd_kcontrol *kcontrol)
{
struct snd_ctl_elem_id id = kcontrol->id;
+ struct snd_control *ctl = card->ctl;
struct snd_kcontrol *matched;
unsigned long h;
int i;
for (i = 0; i < kcontrol->count; i++) {
- xa_erase(&card->ctl_numids, id.numid);
+ xa_erase(&ctl->numids, id.numid);
h = get_ctl_id_hash(&id);
- matched = xa_load(&card->ctl_hash, h);
+ matched = xa_load(&ctl->hash, h);
if (matched && (matched == kcontrol ||
elem_id_matches(matched, &id)))
- xa_erase(&card->ctl_hash, h);
+ xa_erase(&ctl->hash, h);
id.index++;
id.numid++;
}
@@ -469,7 +508,7 @@ static int __snd_ctl_add_replace(struct snd_card *card,
struct snd_kcontrol *old;
int err;
- lockdep_assert_held_write(&card->controls_rwsem);
+ lockdep_assert_held_write(&card->ctl->controls_rwsem);
id = kcontrol->id;
if (id.index > UINT_MAX - kcontrol->count)
@@ -496,10 +535,10 @@ static int __snd_ctl_add_replace(struct snd_card *card,
if (snd_ctl_find_hole(card, kcontrol->count) < 0)
return -ENOMEM;
- list_add_tail(&kcontrol->list, &card->controls);
- card->controls_count += kcontrol->count;
- kcontrol->id.numid = card->last_numid + 1;
- card->last_numid += kcontrol->count;
+ list_add_tail(&kcontrol->list, &card->ctl->controls);
+ card->ctl->controls_count += kcontrol->count;
+ kcontrol->id.numid = card->ctl->last_numid + 1;
+ card->ctl->last_numid += kcontrol->count;
add_hash_entries(card, kcontrol);
@@ -520,9 +559,9 @@ static int snd_ctl_add_replace(struct snd_card *card,
if (snd_BUG_ON(!card || !kcontrol->info))
goto error;
- down_write(&card->controls_rwsem);
+ down_write(&card->ctl->controls_rwsem);
err = __snd_ctl_add_replace(card, kcontrol, mode);
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
if (err < 0)
goto error;
return 0;
@@ -580,7 +619,7 @@ static int __snd_ctl_remove(struct snd_card *card,
{
unsigned int idx;
- lockdep_assert_held_write(&card->controls_rwsem);
+ lockdep_assert_held_write(&card->ctl->controls_rwsem);
if (snd_BUG_ON(!card || !kcontrol))
return -EINVAL;
@@ -589,7 +628,7 @@ static int __snd_ctl_remove(struct snd_card *card,
if (remove_hash)
remove_hash_entries(card, kcontrol);
- card->controls_count -= kcontrol->count;
+ card->ctl->controls_count -= kcontrol->count;
for (idx = 0; idx < kcontrol->count; idx++)
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_REMOVE, kcontrol, idx);
snd_ctl_free_one(kcontrol);
@@ -618,9 +657,9 @@ int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
{
int ret;
- down_write(&card->controls_rwsem);
+ down_write(&card->ctl->controls_rwsem);
ret = snd_ctl_remove_locked(card, kcontrol);
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return ret;
}
EXPORT_SYMBOL(snd_ctl_remove);
@@ -640,14 +679,14 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
struct snd_kcontrol *kctl;
int ret;
- down_write(&card->controls_rwsem);
+ down_write(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, id);
if (kctl == NULL) {
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return -ENOENT;
}
ret = snd_ctl_remove_locked(card, kctl);
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return ret;
}
EXPORT_SYMBOL(snd_ctl_remove_id);
@@ -669,7 +708,7 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
struct snd_kcontrol *kctl;
int idx, ret;
- down_write(&card->controls_rwsem);
+ down_write(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, id);
if (kctl == NULL) {
ret = -ENOENT;
@@ -686,7 +725,7 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
}
ret = snd_ctl_remove_locked(card, kctl);
error:
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return ret;
}
@@ -710,7 +749,7 @@ int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
unsigned int index_offset;
int ret;
- down_write(&card->controls_rwsem);
+ down_write(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, id);
if (kctl == NULL) {
ret = -ENOENT;
@@ -729,13 +768,13 @@ int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
}
snd_ctl_build_ioff(id, kctl, index_offset);
- downgrade_write(&card->controls_rwsem);
+ downgrade_write(&card->ctl->controls_rwsem);
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_INFO, kctl, index_offset);
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
return 1;
unlock:
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return ret;
}
EXPORT_SYMBOL_GPL(snd_ctl_activate_id);
@@ -764,10 +803,10 @@ int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
struct snd_kcontrol *kctl;
int saved_numid;
- down_write(&card->controls_rwsem);
+ down_write(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, src_id);
if (kctl == NULL) {
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return -ENOENT;
}
saved_numid = kctl->id.numid;
@@ -775,7 +814,7 @@ int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
kctl->id = *dst_id;
kctl->id.numid = saved_numid;
add_hash_entries(card, kctl);
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return 0;
}
EXPORT_SYMBOL(snd_ctl_rename_id);
@@ -793,7 +832,7 @@ EXPORT_SYMBOL(snd_ctl_rename_id);
void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl,
const char *name)
{
- down_write(&card->controls_rwsem);
+ down_write(&card->ctl->controls_rwsem);
remove_hash_entries(card, kctl);
if (strscpy(kctl->id.name, name, sizeof(kctl->id.name)) < 0)
@@ -801,7 +840,7 @@ void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl,
name, kctl->id.name);
add_hash_entries(card, kctl);
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
}
EXPORT_SYMBOL(snd_ctl_rename);
@@ -836,9 +875,9 @@ snd_ctl_find_numid_locked(struct snd_card *card, unsigned int numid)
{
if (snd_BUG_ON(!card || !numid))
return NULL;
- lockdep_assert_held(&card->controls_rwsem);
+ lockdep_assert_held(&card->ctl->controls_rwsem);
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
- return xa_load(&card->ctl_numids, numid);
+ return xa_load(&card->ctl->numids, numid);
#else
return snd_ctl_find_numid_slow(card, numid);
#endif
@@ -861,9 +900,9 @@ struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card,
{
struct snd_kcontrol *kctl;
- down_read(&card->controls_rwsem);
+ down_read(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_numid_locked(card, numid);
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
return kctl;
}
EXPORT_SYMBOL(snd_ctl_find_numid);
@@ -887,18 +926,18 @@ struct snd_kcontrol *snd_ctl_find_id_locked(struct snd_card *card,
if (snd_BUG_ON(!card || !id))
return NULL;
- lockdep_assert_held(&card->controls_rwsem);
+ lockdep_assert_held(&card->ctl->controls_rwsem);
if (id->numid != 0)
return snd_ctl_find_numid_locked(card, id->numid);
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
- kctl = xa_load(&card->ctl_hash, get_ctl_id_hash(id));
+ kctl = xa_load(&card->ctl->hash, get_ctl_id_hash(id));
if (kctl && elem_id_matches(kctl, id))
return kctl;
- if (!card->ctl_hash_collision)
+ if (!card->ctl->hash_collision)
return NULL; /* we can rely on only hash table */
#endif
/* no matching in hash table - try all as the last resort */
- list_for_each_entry(kctl, &card->controls, list)
+ list_for_each_entry(kctl, &card->ctl->controls, list)
if (elem_id_matches(kctl, id))
return kctl;
@@ -922,9 +961,9 @@ struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
{
struct snd_kcontrol *kctl;
- down_read(&card->controls_rwsem);
+ down_read(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, id);
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
return kctl;
}
EXPORT_SYMBOL(snd_ctl_find_id);
@@ -965,11 +1004,11 @@ static int snd_ctl_elem_list(struct snd_card *card,
offset = list->offset;
space = list->space;
- down_read(&card->controls_rwsem);
- list->count = card->controls_count;
+ down_read(&card->ctl->controls_rwsem);
+ list->count = card->ctl->controls_count;
list->used = 0;
if (space > 0) {
- list_for_each_entry(kctl, &card->controls, list) {
+ list_for_each_entry(kctl, &card->ctl->controls, list) {
if (offset >= kctl->count) {
offset -= kctl->count;
continue;
@@ -989,7 +1028,7 @@ static int snd_ctl_elem_list(struct snd_card *card,
}
}
out:
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
return err;
}
@@ -1240,13 +1279,13 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
struct snd_kcontrol *kctl;
int result;
- down_read(&card->controls_rwsem);
+ down_read(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, &info->id);
if (kctl == NULL)
result = -ENOENT;
else
result = __snd_ctl_elem_info(card, kctl, info, ctl);
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
return result;
}
@@ -1279,7 +1318,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
const u32 pattern = 0xdeadbeef;
int ret;
- down_read(&card->controls_rwsem);
+ down_read(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, &control->id);
if (kctl == NULL) {
ret = -ENOENT;
@@ -1323,7 +1362,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
goto unlock;
}
unlock:
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
return ret;
}
@@ -1356,10 +1395,10 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
unsigned int index_offset;
int result;
- down_write(&card->controls_rwsem);
+ down_write(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, &control->id);
if (kctl == NULL) {
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return -ENOENT;
}
@@ -1367,7 +1406,7 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
vd = &kctl->vd[index_offset];
if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || kctl->put == NULL ||
(file && vd->owner && vd->owner != file)) {
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return -EPERM;
}
@@ -1388,16 +1427,16 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
result = kctl->put(kctl, control);
snd_power_unref(card);
if (result < 0) {
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return result;
}
if (result > 0) {
- downgrade_write(&card->controls_rwsem);
+ downgrade_write(&card->ctl->controls_rwsem);
snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_VALUE, kctl, index_offset);
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
} else {
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
}
return 0;
@@ -1437,7 +1476,7 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file,
if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
- down_write(&card->controls_rwsem);
+ down_write(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, &id);
if (kctl == NULL) {
result = -ENOENT;
@@ -1450,7 +1489,7 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file,
result = 0;
}
}
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return result;
}
@@ -1465,7 +1504,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
- down_write(&card->controls_rwsem);
+ down_write(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, &id);
if (kctl == NULL) {
result = -ENOENT;
@@ -1480,7 +1519,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
result = 0;
}
}
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return result;
}
@@ -1497,7 +1536,7 @@ struct user_element {
// check whether the addition (in bytes) of user ctl element may overflow the limit.
static bool check_user_elem_overflow(struct snd_card *card, ssize_t add)
{
- return (ssize_t)card->user_ctl_alloc_size + add > max_user_ctl_alloc_size;
+ return (ssize_t)card->ctl->user_ctl_alloc_size + add > max_user_ctl_alloc_size;
}
static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
@@ -1575,7 +1614,7 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
int i;
int change;
- lockdep_assert_held_write(&ue->card->controls_rwsem);
+ lockdep_assert_held_write(&ue->card->ctl->controls_rwsem);
if (size > 1024 * 128) /* sane value */
return -EINVAL;
@@ -1602,7 +1641,7 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
mask = SNDRV_CTL_EVENT_MASK_INFO;
} else {
- ue->card->user_ctl_alloc_size -= ue->tlv_data_size;
+ ue->card->ctl->user_ctl_alloc_size -= ue->tlv_data_size;
ue->tlv_data_size = 0;
kvfree(ue->tlv_data);
}
@@ -1610,7 +1649,7 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
ue->tlv_data = container;
ue->tlv_data_size = size;
// decremented at private_free.
- ue->card->user_ctl_alloc_size += size;
+ ue->card->ctl->user_ctl_alloc_size += size;
mask |= SNDRV_CTL_EVENT_MASK_TLV;
for (i = 0; i < kctl->count; ++i)
@@ -1653,7 +1692,7 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
unsigned int i;
const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr;
- lockdep_assert_held_write(&ue->card->controls_rwsem);
+ lockdep_assert_held_write(&ue->card->ctl->controls_rwsem);
buf_len = ue->info.value.enumerated.names_length;
if (buf_len > 64 * 1024)
@@ -1680,7 +1719,7 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
ue->priv_data = names;
ue->info.value.enumerated.names_ptr = 0;
// increment the allocation size; decremented again at private_free.
- ue->card->user_ctl_alloc_size += ue->info.value.enumerated.names_length;
+ ue->card->ctl->user_ctl_alloc_size += ue->info.value.enumerated.names_length;
return 0;
}
@@ -1695,10 +1734,10 @@ static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
struct user_element *ue = kcontrol->private_data;
// decrement the allocation size.
- ue->card->user_ctl_alloc_size -= compute_user_elem_size(ue->elem_data_size, kcontrol->count);
- ue->card->user_ctl_alloc_size -= ue->tlv_data_size;
+ ue->card->ctl->user_ctl_alloc_size -= compute_user_elem_size(ue->elem_data_size, kcontrol->count);
+ ue->card->ctl->user_ctl_alloc_size -= ue->tlv_data_size;
if (ue->priv_data)
- ue->card->user_ctl_alloc_size -= ue->info.value.enumerated.names_length;
+ ue->card->ctl->user_ctl_alloc_size -= ue->info.value.enumerated.names_length;
kvfree(ue->tlv_data);
kvfree(ue->priv_data);
@@ -1763,7 +1802,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
private_size = value_sizes[info->type] * info->count;
alloc_size = compute_user_elem_size(private_size, count);
- down_write(&card->controls_rwsem);
+ down_write(&card->ctl->controls_rwsem);
if (check_user_elem_overflow(card, alloc_size)) {
err = -ENOMEM;
goto unlock;
@@ -1789,7 +1828,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
kctl->private_free = snd_ctl_elem_user_free;
// increment the allocated size; decremented again at private_free.
- card->user_ctl_alloc_size += alloc_size;
+ card->ctl->user_ctl_alloc_size += alloc_size;
/* Set private data for this userspace control. */
ue->card = card;
@@ -1833,7 +1872,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
* which locks the element.
*/
unlock:
- up_write(&card->controls_rwsem);
+ up_write(&card->ctl->controls_rwsem);
return err;
}
@@ -1959,7 +1998,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
struct snd_ctl_elem_id id;
struct snd_kcontrol_volatile *vd;
- lockdep_assert_held(&file->card->controls_rwsem);
+ lockdep_assert_held(&file->card->ctl->controls_rwsem);
if (copy_from_user(&header, buf, sizeof(header)))
return -EFAULT;
@@ -2036,19 +2075,19 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
return snd_ctl_subscribe_events(ctl, ip);
case SNDRV_CTL_IOCTL_TLV_READ:
- down_read(&ctl->card->controls_rwsem);
+ down_read(&ctl->card->ctl->controls_rwsem);
err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
- up_read(&ctl->card->controls_rwsem);
+ up_read(&ctl->card->ctl->controls_rwsem);
return err;
case SNDRV_CTL_IOCTL_TLV_WRITE:
- down_write(&ctl->card->controls_rwsem);
+ down_write(&ctl->card->ctl->controls_rwsem);
err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
- up_write(&ctl->card->controls_rwsem);
+ up_write(&ctl->card->ctl->controls_rwsem);
return err;
case SNDRV_CTL_IOCTL_TLV_COMMAND:
- down_write(&ctl->card->controls_rwsem);
+ down_write(&ctl->card->ctl->controls_rwsem);
err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
- up_write(&ctl->card->controls_rwsem);
+ up_write(&ctl->card->ctl->controls_rwsem);
return err;
case SNDRV_CTL_IOCTL_POWER:
return -ENOPROTOOPT;
@@ -2258,15 +2297,15 @@ int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type)
int subdevice = -1;
unsigned long flags;
- read_lock_irqsave(&card->ctl_files_rwlock, flags);
- list_for_each_entry(kctl, &card->ctl_files, list) {
+ read_lock_irqsave(&card->ctl->files_rwlock, flags);
+ list_for_each_entry(kctl, &card->ctl->files, list) {
if (kctl->pid == task_pid(current)) {
subdevice = kctl->preferred_subdevice[type];
if (subdevice != -1)
break;
}
}
- read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
+ read_unlock_irqrestore(&card->ctl->files_rwlock, flags);
return subdevice;
}
EXPORT_SYMBOL_GPL(snd_ctl_get_preferred_subdevice);
@@ -2326,9 +2365,9 @@ void snd_ctl_register_layer(struct snd_ctl_layer_ops *lops)
for (card_number = 0; card_number < SNDRV_CARDS; card_number++) {
card = snd_card_ref(card_number);
if (card) {
- down_read(&card->controls_rwsem);
+ down_read(&card->ctl->controls_rwsem);
lops->lregister(card);
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
snd_card_unref(card);
}
}
@@ -2389,15 +2428,15 @@ static int snd_ctl_dev_register(struct snd_device *device)
int err;
err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
- &snd_ctl_f_ops, card, card->ctl_dev);
+ &snd_ctl_f_ops, card, &card->ctl->dev);
if (err < 0)
return err;
- down_read(&card->controls_rwsem);
+ down_read(&card->ctl->controls_rwsem);
down_read(&snd_ctl_layer_rwsem);
for (lops = snd_ctl_layer; lops; lops = lops->next)
lops->lregister(card);
up_read(&snd_ctl_layer_rwsem);
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
return 0;
}
@@ -2411,21 +2450,21 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
struct snd_ctl_layer_ops *lops;
unsigned long flags;
- read_lock_irqsave(&card->ctl_files_rwlock, flags);
- list_for_each_entry(ctl, &card->ctl_files, list) {
+ read_lock_irqsave(&card->ctl->files_rwlock, flags);
+ list_for_each_entry(ctl, &card->ctl->files, list) {
wake_up(&ctl->change_sleep);
snd_kill_fasync(ctl->fasync, SIGIO, POLL_ERR);
}
- read_unlock_irqrestore(&card->ctl_files_rwlock, flags);
+ read_unlock_irqrestore(&card->ctl->files_rwlock, flags);
- down_read(&card->controls_rwsem);
+ down_read(&card->ctl->controls_rwsem);
down_read(&snd_ctl_layer_rwsem);
for (lops = snd_ctl_layer; lops; lops = lops->next)
lops->ldisconnect(card);
up_read(&snd_ctl_layer_rwsem);
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
- return snd_unregister_device(card->ctl_dev);
+ return snd_unregister_device(&card->ctl->dev);
}
/*
@@ -2436,21 +2475,28 @@ static int snd_ctl_dev_free(struct snd_device *device)
struct snd_card *card = device->device_data;
struct snd_kcontrol *control;
- down_write(&card->controls_rwsem);
- while (!list_empty(&card->controls)) {
- control = snd_kcontrol(card->controls.next);
+ down_write(&card->ctl->controls_rwsem);
+ while (!list_empty(&card->ctl->controls)) {
+ control = snd_kcontrol(card->ctl->controls.next);
__snd_ctl_remove(card, control, false);
}
#ifdef CONFIG_SND_CTL_FAST_LOOKUP
- xa_destroy(&card->ctl_numids);
- xa_destroy(&card->ctl_hash);
+ xa_destroy(&card->ctl->numids);
+ xa_destroy(&card->ctl->hash);
#endif
- up_write(&card->controls_rwsem);
- put_device(card->ctl_dev);
+ up_write(&card->ctl->controls_rwsem);
+ put_device(&card->ctl->dev);
return 0;
}
+static void release_control_device(struct device *dev)
+{
+ struct snd_control *ctl = container_of(dev, struct snd_control, dev);
+
+ kfree(ctl);
+}
+
/*
* create control core:
* called from init.c
@@ -2462,6 +2508,7 @@ int snd_ctl_create(struct snd_card *card)
.dev_register = snd_ctl_dev_register,
.dev_disconnect = snd_ctl_dev_disconnect,
};
+ struct snd_control *ctl = card->ctl;
int err;
if (snd_BUG_ON(!card))
@@ -2469,14 +2516,13 @@ int snd_ctl_create(struct snd_card *card)
if (snd_BUG_ON(card->number < 0 || card->number >= SNDRV_CARDS))
return -ENXIO;
- err = snd_device_alloc(&card->ctl_dev, card);
- if (err < 0)
- return err;
- dev_set_name(card->ctl_dev, "controlC%d", card->number);
+ snd_device_init(&ctl->dev, card);
+ dev_set_name(&ctl->dev, "controlC%d", card->number);
+ ctl->dev.release = release_control_device;
err = snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
if (err < 0)
- put_device(card->ctl_dev);
+ put_device(&ctl->dev);
return err;
}
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 0e8b1bfb040e0..0e0b555f71537 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -172,15 +172,15 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
struct snd_ctl_elem_info *info;
int err;
- down_read(&card->controls_rwsem);
+ down_read(&card->ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, id);
if (! kctl) {
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
return -ENOENT;
}
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL) {
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
return -ENOMEM;
}
info->id = *id;
@@ -188,7 +188,7 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
if (!err)
err = kctl->info(kctl, info);
snd_power_unref(card);
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
if (err >= 0) {
err = info->type;
*countp = info->count;
diff --git a/sound/core/control_led.c b/sound/core/control_led.c
index a78eb48927c7b..6b53de7660438 100644
--- a/sound/core/control_led.c
+++ b/sound/core/control_led.c
@@ -243,6 +243,7 @@ static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id,
unsigned int group, bool set)
{
struct snd_card *card;
+ struct snd_control *ctl;
struct snd_kcontrol *kctl;
struct snd_kcontrol_volatile *vd;
unsigned int ioff, access, new_access;
@@ -250,7 +251,8 @@ static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id,
card = snd_card_ref(card_number);
if (card) {
- down_write(&card->controls_rwsem);
+ ctl = card->ctl;
+ down_write(&ctl->controls_rwsem);
kctl = snd_ctl_find_id_locked(card, id);
if (kctl) {
ioff = snd_ctl_get_ioff(kctl, id);
@@ -271,7 +273,7 @@ static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id,
err = -ENOENT;
}
unlock:
- up_write(&card->controls_rwsem);
+ up_write(&ctl->controls_rwsem);
snd_card_unref(card);
} else {
err = -ENXIO;
@@ -357,7 +359,7 @@ static void snd_ctl_led_register(struct snd_card *card)
snd_ctl_led_card_valid[card->number] = true;
mutex_unlock(&snd_ctl_led_mutex);
/* the register callback is already called with held card->controls_rwsem */
- list_for_each_entry(kctl, &card->controls, list)
+ list_for_each_entry(kctl, &card->ctl->controls, list)
for (ioff = 0; ioff < kctl->count; ioff++)
snd_ctl_led_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, kctl, ioff);
snd_ctl_led_refresh();
@@ -617,12 +619,14 @@ static ssize_t list_show(struct device *dev,
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
struct snd_card *card;
struct snd_ctl_led_ctl *lctl;
+ struct snd_control *ctl;
size_t l = 0;
card = snd_card_ref(led_card->number);
if (!card)
return -ENXIO;
- down_read(&card->controls_rwsem);
+ ctl = card->ctl;
+ down_read(&ctl->controls_rwsem);
mutex_lock(&snd_ctl_led_mutex);
if (snd_ctl_led_card_valid[led_card->number]) {
list_for_each_entry(lctl, &led_card->led->controls, list) {
@@ -635,7 +639,7 @@ static ssize_t list_show(struct device *dev,
}
}
mutex_unlock(&snd_ctl_led_mutex);
- up_read(&card->controls_rwsem);
+ up_read(&ctl->controls_rwsem);
snd_card_unref(card);
return l;
}
@@ -688,7 +692,7 @@ static void snd_ctl_led_sysfs_add(struct snd_card *card)
goto cerr;
led->cards[card->number] = led_card;
snprintf(link_name, sizeof(link_name), "led-%s", led->name);
- WARN(sysfs_create_link(&card->ctl_dev->kobj, &led_card->dev.kobj, link_name),
+ WARN(sysfs_create_link(&card->ctl->dev.kobj, &led_card->dev.kobj, link_name),
"can't create symlink to controlC%i device\n", card->number);
WARN(sysfs_create_link(&led_card->dev.kobj, &card->card_dev.kobj, "card"),
"can't create symlink to card%i\n", card->number);
@@ -714,7 +718,7 @@ static void snd_ctl_led_sysfs_remove(struct snd_card *card)
if (!led_card)
continue;
snprintf(link_name, sizeof(link_name), "led-%s", led->name);
- sysfs_remove_link(&card->ctl_dev->kobj, link_name);
+ sysfs_remove_link(&card->ctl->dev.kobj, link_name);
sysfs_remove_link(&led_card->dev.kobj, "card");
device_unregister(&led_card->dev);
led->cards[card->number] = NULL;
diff --git a/sound/core/init.c b/sound/core/init.c
index 37a8e4791f781..695b080603e93 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -331,14 +331,6 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
card->module = module;
#endif
INIT_LIST_HEAD(&card->devices);
- init_rwsem(&card->controls_rwsem);
- rwlock_init(&card->ctl_files_rwlock);
- INIT_LIST_HEAD(&card->controls);
- INIT_LIST_HEAD(&card->ctl_files);
-#ifdef CONFIG_SND_CTL_FAST_LOOKUP
- xa_init(&card->ctl_numids);
- xa_init(&card->ctl_hash);
-#endif
spin_lock_init(&card->files_lock);
INIT_LIST_HEAD(&card->files_list);
mutex_init(&card->memory_mutex);
@@ -363,11 +355,9 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
snprintf(card->irq_descr, sizeof(card->irq_descr), "%s:%s",
dev_driver_string(card->dev), dev_name(&card->card_dev));
- /* the control interface cannot be accessed from the user space until */
- /* snd_cards_bitmask and snd_cards are set with snd_card_register */
- err = snd_ctl_create(card);
+ err = snd_control_new(card);
if (err < 0) {
- dev_err(parent, "unable to register control minors\n");
+ dev_err(parent, "unable to create controls and register\n");
goto __error;
}
err = snd_info_card_create(card);
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 33af707a65ab1..7afc9a29ea9ec 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1784,13 +1784,14 @@ void snd_hda_ctls_clear(struct hda_codec *codec)
int snd_hda_lock_devices(struct hda_bus *bus)
{
struct snd_card *card = bus->card;
+ struct snd_control *ctl = card->ctl;
struct hda_codec *codec;
spin_lock(&card->files_lock);
if (card->shutdown)
goto err_unlock;
card->shutdown = 1;
- if (!list_empty(&card->ctl_files))
+ if (!list_empty(&ctl->files))
goto err_clear;
list_for_each_codec(codec, bus) {
diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c
index 38116c7587174..8cd5681de9fbd 100644
--- a/sound/soc/intel/atom/sst-atom-controls.c
+++ b/sound/soc/intel/atom/sst-atom-controls.c
@@ -1434,9 +1434,9 @@ static int sst_fill_widget_module_info(struct snd_soc_dapm_widget *w,
struct snd_card *card = component->card->snd_card;
char *idx;
- down_read(&card->controls_rwsem);
+ down_read(&card->ctl->controls_rwsem);
- list_for_each_entry(kctl, &card->controls, list) {
+ list_for_each_entry(kctl, &card->ctl->controls, list) {
idx = strchr(kctl->id.name, ' ');
if (idx == NULL)
continue;
@@ -1469,12 +1469,12 @@ static int sst_fill_widget_module_info(struct snd_soc_dapm_widget *w,
}
if (ret < 0) {
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
return ret;
}
}
- up_read(&card->controls_rwsem);
+ up_read(&card->ctl->controls_rwsem);
return 0;
}
diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c
index 285ab4c9c7168..1129eb33f78c9 100644
--- a/sound/soc/soc-card.c
+++ b/sound/soc/soc-card.c
@@ -35,7 +35,7 @@ struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
if (unlikely(!name))
return NULL;
- list_for_each_entry(kctl, &card->controls, list)
+ list_for_each_entry(kctl, &card->ctl->controls, list)
if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name)))
return kctl;
return NULL;
diff --git a/sound/usb/media.c b/sound/usb/media.c
index d48db6f3ae659..5298c2f49a164 100644
--- a/sound/usb/media.c
+++ b/sound/usb/media.c
@@ -163,7 +163,7 @@ void snd_media_stop_pipeline(struct snd_usb_substream *subs)
static int snd_media_mixer_init(struct snd_usb_audio *chip)
{
- struct device *ctl_dev = chip->card->ctl_dev;
+ struct device *ctl_dev = &chip->card->ctl->dev;
struct media_intf_devnode *ctl_intf;
struct usb_mixer_interface *mixer;
struct media_device *mdev = chip->media_dev;
--
2.42.0.rc1.204.g551eb34607-goog
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] ALSA: core: split control primitives out of snd_card
2023-08-24 21:02 ` [PATCH 2/2] ALSA: core: split control primitives out of snd_card cujomalainey
@ 2023-08-24 21:15 ` Mark Brown
2023-08-25 10:57 ` Takashi Iwai
2023-09-03 22:38 ` kernel test robot
2 siblings, 0 replies; 10+ messages in thread
From: Mark Brown @ 2023-08-24 21:15 UTC (permalink / raw)
To: cujomalainey
Cc: alsa-devel, Jaroslav Kysela, Takashi Iwai, Cezary Rojewski,
Pierre-Louis Bossart, Liam Girdwood, Peter Ujfalusi, Bard Liao,
Ranjani Sridharan, Kai Vehmanen, Dan Carpenter,
Maciej S. Szmigiero, Clement Lecigne, Min-Hua Chen, Ivan Orlov,
Greg Kroah-Hartman, Thierry Reding, Geoff Levand,
Uwe Kleine-König, Kuninori Morimoto
[-- Attachment #1: Type: text/plain, Size: 407 bytes --]
On Thu, Aug 24, 2023 at 02:02:53PM -0700, cujomalainey@chromium.org wrote:
> From: Curtis Malainey <cujomalainey@chromium.org>
>
> Having two kobj in the same struct is broken at its core. This splits
> card_dev from ctl_dev so they can properly refcount and release on their
> own schedules without the workaround of having them being just a
> pointer.
Acked-by: Mark Brown <broonie@kernel.org>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] ALSA: core: add snd_device_init
2023-08-24 21:02 ` [PATCH 1/2] ALSA: core: add snd_device_init cujomalainey
@ 2023-08-24 22:23 ` kernel test robot
2023-08-25 10:46 ` Takashi Iwai
1 sibling, 0 replies; 10+ messages in thread
From: kernel test robot @ 2023-08-24 22:23 UTC (permalink / raw)
To: cujomalainey, alsa-devel
Cc: oe-kbuild-all, Curtis Malainey, Jaroslav Kysela, Takashi Iwai,
Thierry Reding, Uwe Kleine-König, Ivan Orlov
Hi,
kernel test robot noticed the following build warnings:
[auto build test WARNING on tiwai-sound/for-next]
[also build test WARNING on next-20230824]
[cannot apply to tiwai-sound/for-linus broonie-sound/for-next linus/master v6.5-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/cujomalainey-chromium-org/ALSA-core-add-snd_device_init/20230825-050745
base: https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git for-next
patch link: https://lore.kernel.org/r/20230824210339.1126993-2-cujomalainey%40chromium.org
patch subject: [PATCH 1/2] ALSA: core: add snd_device_init
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20230825/202308250609.8A2yaCZs-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20230825/202308250609.8A2yaCZs-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202308250609.8A2yaCZs-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> sound/core/init.c:149: warning: Function parameter or member 'dev' not described in 'snd_device_init'
>> sound/core/init.c:149: warning: Excess function parameter 'dev_p' description in 'snd_device_init'
vim +149 sound/core/init.c
140
141 /**
142 * snd_device_init - Initialize struct device for sound devices
143 * @dev_p: pointer to store the allocated device
144 * @card: card to assign, optional
145 *
146 * For releasing the allocated device, call put_device().
147 */
148 void snd_device_init(struct device *dev, struct snd_card *card)
> 149 {
150 device_initialize(dev);
151 if (card)
152 dev->parent = &card->card_dev;
153 dev->class = &sound_class;
154 dev->release = default_release_alloc;
155 }
156 EXPORT_SYMBOL_GPL(snd_device_init);
157
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] ALSA: core: add snd_device_init
2023-08-24 21:02 ` [PATCH 1/2] ALSA: core: add snd_device_init cujomalainey
2023-08-24 22:23 ` kernel test robot
@ 2023-08-25 10:46 ` Takashi Iwai
1 sibling, 0 replies; 10+ messages in thread
From: Takashi Iwai @ 2023-08-25 10:46 UTC (permalink / raw)
To: cujomalainey
Cc: alsa-devel, Jaroslav Kysela, Takashi Iwai, Thierry Reding,
Uwe Kleine-König, Ivan Orlov
On Thu, 24 Aug 2023 23:02:52 +0200,
cujomalainey@chromium.org wrote:
>
> From: Curtis Malainey <cujomalainey@chromium.org>
>
> Begin allowing refactored modules to allocate their own device but use a
> common initialization procedure for their devices.
>
> Signed-off-by: Curtis Malainey <cujomalainey@chromium.org>
> ---
> include/sound/core.h | 1 +
> sound/core/init.c | 19 ++++++++++++++++---
> 2 files changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/include/sound/core.h b/include/sound/core.h
> index dfef0c9d4b9f7..a4744e142c7e3 100644
> --- a/include/sound/core.h
> +++ b/include/sound/core.h
> @@ -240,6 +240,7 @@ extern struct dentry *sound_debugfs_root;
> void snd_request_card(int card);
>
> int snd_device_alloc(struct device **dev_p, struct snd_card *card);
> +void snd_device_init(struct device *dev, struct snd_card *card);
>
> int snd_register_device(int type, struct snd_card *card, int dev,
> const struct file_operations *f_ops,
> diff --git a/sound/core/init.c b/sound/core/init.c
> index d61bde1225f23..37a8e4791f781 100644
> --- a/sound/core/init.c
> +++ b/sound/core/init.c
> @@ -132,15 +132,28 @@ int snd_device_alloc(struct device **dev_p, struct snd_card *card)
> dev = kzalloc(sizeof(*dev), GFP_KERNEL);
> if (!dev)
> return -ENOMEM;
> + snd_device_init(dev, card);
> + *dev_p = dev;
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(snd_device_alloc);
> +
> +/**
> + * snd_device_init - Initialize struct device for sound devices
> + * @dev_p: pointer to store the allocated device
> + * @card: card to assign, optional
> + *
> + * For releasing the allocated device, call put_device().
> + */
> +void snd_device_init(struct device *dev, struct snd_card *card)
> +{
> device_initialize(dev);
> if (card)
> dev->parent = &card->card_dev;
> dev->class = &sound_class;
> dev->release = default_release_alloc;
> - *dev_p = dev;
> - return 0;
> }
> -EXPORT_SYMBOL_GPL(snd_device_alloc);
> +EXPORT_SYMBOL_GPL(snd_device_init);
This will call kfree() at the default release. It should be avoided
for this case, no?
Also, it's worth that this practically a kind of revive of the old API
that was dropped in the commit 01ed7f3535a2.
thanks,
Takashi
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] ALSA: core: split control primitives out of snd_card
2023-08-24 21:02 ` [PATCH 2/2] ALSA: core: split control primitives out of snd_card cujomalainey
2023-08-24 21:15 ` Mark Brown
@ 2023-08-25 10:57 ` Takashi Iwai
2023-09-03 22:38 ` kernel test robot
2 siblings, 0 replies; 10+ messages in thread
From: Takashi Iwai @ 2023-08-25 10:57 UTC (permalink / raw)
To: cujomalainey
Cc: alsa-devel, Jaroslav Kysela, Takashi Iwai, Cezary Rojewski,
Pierre-Louis Bossart, Liam Girdwood, Peter Ujfalusi, Bard Liao,
Ranjani Sridharan, Kai Vehmanen, Mark Brown, Dan Carpenter,
Maciej S. Szmigiero, Clement Lecigne, Min-Hua Chen, Ivan Orlov,
Greg Kroah-Hartman, Thierry Reding, Geoff Levand,
Uwe Kleine-König, Kuninori Morimoto
On Thu, 24 Aug 2023 23:02:53 +0200,
cujomalainey@chromium.org wrote:
>
> +struct snd_control
> +{
The open brace should be at the line above.
> + struct device dev; /* control device */
> + struct rw_semaphore controls_rwsem; /* controls lock (list and values) */
> + rwlock_t files_rwlock; /* ctl_files list lock */
> + int controls_count; /* count of all controls */
> + size_t user_ctl_alloc_size; // current memory allocation by user controls.
Better to have the same comment style if we move the whole stuff.
> +int snd_control_new(struct snd_card *card)
....
> +{
> + struct snd_control *ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
> + int err;
> +
> + if (snd_BUG_ON(!card))
> + return -EINVAL;
This may leak the memory allocated in the above.
> + /* the control interface cannot be accessed from the user space until */
> + /* snd_cards_bitmask and snd_cards are set with snd_card_register */
> + err = snd_ctl_create(card);
> + if (err < 0) {
> + dev_err(card->dev, "unable to register control minors\n");
> + kfree(ctl);
> + return err;
This needs a more care. snd_ctl_create() calls put_device() when
snd_device_new() fails, and this already does kfree(). OTOH, the
error path before that point doesn't release the object.
> + }
> + return 0;
> +}
> +EXPORT_SYMBOL(snd_control_new);
This is never called from the driver but only from snd_card_new() &
co, so no need to export.
thanks,
Takashi
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2][RFC] Refactor snd primitives refcounters
2023-08-24 21:02 [PATCH 0/2][RFC] Refactor snd primitives refcounters cujomalainey
2023-08-24 21:02 ` [PATCH 1/2] ALSA: core: add snd_device_init cujomalainey
2023-08-24 21:02 ` [PATCH 2/2] ALSA: core: split control primitives out of snd_card cujomalainey
@ 2023-08-25 11:15 ` Takashi Iwai
2023-08-25 17:42 ` Curtis Malainey
2 siblings, 1 reply; 10+ messages in thread
From: Takashi Iwai @ 2023-08-25 11:15 UTC (permalink / raw)
To: cujomalainey; +Cc: alsa-devel
On Thu, 24 Aug 2023 23:02:51 +0200,
cujomalainey@chromium.org wrote:
>
> From: Curtis Malainey <cujomalainey@chromium.org>
>
> As previously identified in [1] there are some issues with how kobjs are
> handled in sound/core. The solution provided in [2] is a workaround for
> the issues to fix the failures.
>
> This series is a first attempt at the larger refactor needed to properly
> handle the objects.
>
> [1] https://mailman.alsa-project.org/hyperkitty/list/alsa-devel@alsa-project.org/message/3B2VMPFATCJCRD76DM36LZAICPDP2R6A/
> [2] https://mailman.alsa-project.org/hyperkitty/list/alsa-devel@alsa-project.org/message/JZIPB4OIC3OK6YAGTPMAEKXMLUWM5PTA/
>
> Curtis Malainey (2):
> ALSA: core: add snd_device_init
> ALSA: core: split control primitives out of snd_card
Thanks for the patches. But, as the 6.6 merge window open is pretty
close, I'd postpone those unless it's urgently needed.
Also, before moving the resource tied with the device object, we'll
need a refcount to the ctl dev from pcm dev, as PCM does release chmap
at its free path (calling free_chmap()). Otherwise it'll lead to
another UAF, if both objects releases are done asynchronously without
dependency.
BTW, the cover letter and the subject prefix of the patches don't
match, and also the cover letter didn't include Cc. Please try to
make both cover letter and patches sent properly.
thanks,
Takashi
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2][RFC] Refactor snd primitives refcounters
2023-08-25 11:15 ` [PATCH 0/2][RFC] Refactor snd primitives refcounters Takashi Iwai
@ 2023-08-25 17:42 ` Curtis Malainey
0 siblings, 0 replies; 10+ messages in thread
From: Curtis Malainey @ 2023-08-25 17:42 UTC (permalink / raw)
To: Takashi Iwai; +Cc: cujomalainey, alsa-devel
On Fri, Aug 25, 2023 at 4:16 AM Takashi Iwai <tiwai@suse.de> wrote:
>
> Thanks for the patches. But, as the 6.6 merge window open is pretty
> close, I'd postpone those unless it's urgently needed.
I have no timeline since we have the workaround in, hence the RFC
>
> Also, before moving the resource tied with the device object, we'll
> need a refcount to the ctl dev from pcm dev, as PCM does release chmap
> at its free path (calling free_chmap()). Otherwise it'll lead to
> another UAF, if both objects releases are done asynchronously without
> dependency.
Got it, thanks.
>
>
> BTW, the cover letter and the subject prefix of the patches don't
> match, and also the cover letter didn't include Cc. Please try to
> make both cover letter and patches sent properly.
Thanks for catching that, I was struggling getting cc to copy across
with git from get_maintainers. I will give it another shot with v2.
Curtis
>
>
> thanks,
>
>
> Takashi
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] ALSA: core: split control primitives out of snd_card
2023-08-24 21:02 ` [PATCH 2/2] ALSA: core: split control primitives out of snd_card cujomalainey
2023-08-24 21:15 ` Mark Brown
2023-08-25 10:57 ` Takashi Iwai
@ 2023-09-03 22:38 ` kernel test robot
2 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2023-09-03 22:38 UTC (permalink / raw)
To: cujomalainey, alsa-devel
Cc: oe-kbuild-all, Curtis Malainey, Jaroslav Kysela, Takashi Iwai,
Cezary Rojewski, Pierre-Louis Bossart, Liam Girdwood,
Peter Ujfalusi, Bard Liao, Ranjani Sridharan, Kai Vehmanen,
Mark Brown, Dan Carpenter, Maciej S. Szmigiero, Clement Lecigne,
Min-Hua Chen, Ivan Orlov, Greg Kroah-Hartman, Thierry Reding,
Geoff Levand, Uwe Kleine-König, Kuninori Morimoto
Hi,
kernel test robot noticed the following build errors:
[auto build test ERROR on tiwai-sound/for-next]
[also build test ERROR on tiwai-sound/for-linus linus/master next-20230831]
[cannot apply to broonie-sound/for-next v6.5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/cujomalainey-chromium-org/ALSA-core-add-snd_device_init/20230825-050745
base: https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git for-next
patch link: https://lore.kernel.org/r/20230824210339.1126993-3-cujomalainey%40chromium.org
patch subject: [PATCH 2/2] ALSA: core: split control primitives out of snd_card
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20230904/202309040658.LwLeCNwY-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230904/202309040658.LwLeCNwY-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202309040658.LwLeCNwY-lkp@intel.com/
All errors (new ones prefixed by >>):
sound/core/oss/mixer_oss.c: In function 'snd_mixer_oss_get_volume1_vol':
>> sound/core/oss/mixer_oss.c:542:24: error: 'struct snd_card' has no member named 'controls_rwsem'
542 | down_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:545:30: error: 'struct snd_card' has no member named 'controls_rwsem'
545 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:563:22: error: 'struct snd_card' has no member named 'controls_rwsem'
563 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c: In function 'snd_mixer_oss_get_volume1_sw':
sound/core/oss/mixer_oss.c:581:24: error: 'struct snd_card' has no member named 'controls_rwsem'
581 | down_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:584:30: error: 'struct snd_card' has no member named 'controls_rwsem'
584 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:603:22: error: 'struct snd_card' has no member named 'controls_rwsem'
603 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c: In function 'snd_mixer_oss_put_volume1_vol':
sound/core/oss/mixer_oss.c:647:24: error: 'struct snd_card' has no member named 'controls_rwsem'
647 | down_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:650:30: error: 'struct snd_card' has no member named 'controls_rwsem'
650 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:671:22: error: 'struct snd_card' has no member named 'controls_rwsem'
671 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c: In function 'snd_mixer_oss_put_volume1_sw':
sound/core/oss/mixer_oss.c:690:24: error: 'struct snd_card' has no member named 'controls_rwsem'
690 | down_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:693:30: error: 'struct snd_card' has no member named 'controls_rwsem'
693 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:718:22: error: 'struct snd_card' has no member named 'controls_rwsem'
718 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c: In function 'snd_mixer_oss_get_recsrc2':
sound/core/oss/mixer_oss.c:835:24: error: 'struct snd_card' has no member named 'controls_rwsem'
835 | down_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:863:22: error: 'struct snd_card' has no member named 'controls_rwsem'
863 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c: In function 'snd_mixer_oss_put_recsrc2':
sound/core/oss/mixer_oss.c:888:24: error: 'struct snd_card' has no member named 'controls_rwsem'
888 | down_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:919:22: error: 'struct snd_card' has no member named 'controls_rwsem'
919 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c: In function 'snd_mixer_oss_build_test':
sound/core/oss/mixer_oss.c:939:24: error: 'struct snd_card' has no member named 'controls_rwsem'
939 | down_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:942:30: error: 'struct snd_card' has no member named 'controls_rwsem'
942 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:947:30: error: 'struct snd_card' has no member named 'controls_rwsem'
947 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:952:30: error: 'struct snd_card' has no member named 'controls_rwsem'
952 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:957:22: error: 'struct snd_card' has no member named 'controls_rwsem'
957 | up_read(&card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c: In function 'snd_mixer_oss_build_input':
sound/core/oss/mixer_oss.c:1071:31: error: 'struct snd_card' has no member named 'controls_rwsem'
1071 | down_read(&mixer->card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:1080:45: error: 'struct snd_card' has no member named 'controls_rwsem'
1080 | up_read(&mixer->card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:1085:45: error: 'struct snd_card' has no member named 'controls_rwsem'
1085 | up_read(&mixer->card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:1101:61: error: 'struct snd_card' has no member named 'controls_rwsem'
1101 | up_read(&mixer->card->controls_rwsem);
| ^~
sound/core/oss/mixer_oss.c:1113:29: error: 'struct snd_card' has no member named 'controls_rwsem'
1113 | up_read(&mixer->card->controls_rwsem);
| ^~
--
In file included from include/linux/kernel.h:21,
from arch/x86/include/asm/percpu.h:27,
from arch/x86/include/asm/current.h:10,
from include/linux/sched.h:12,
from include/linux/ratelimit.h:6,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from include/linux/pm_runtime.h:11,
from sound/soc/intel/catpt/pcm.c:8:
sound/soc/intel/catpt/pcm.c: In function 'catpt_dai_apply_usettings':
>> sound/soc/intel/catpt/pcm.c:357:60: error: 'struct snd_card' has no member named 'controls'
357 | list_for_each_entry(pos, &component->card->snd_card->controls, list) {
| ^~
include/linux/container_of.h:19:33: note: in definition of macro 'container_of'
19 | void *__mptr = (void *)(ptr); \
| ^~~
include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
531 | list_entry((ptr)->next, type, member)
| ^~~~~~~~~~
include/linux/list.h:689:20: note: in expansion of macro 'list_first_entry'
689 | for (pos = list_first_entry(head, typeof(*pos), member); \
| ^~~~~~~~~~~~~~~~
sound/soc/intel/catpt/pcm.c:357:9: note: in expansion of macro 'list_for_each_entry'
357 | list_for_each_entry(pos, &component->card->snd_card->controls, list) {
| ^~~~~~~~~~~~~~~~~~~
In file included from include/linux/bits.h:21,
from include/linux/ratelimit_types.h:5,
from include/linux/ratelimit.h:5:
>> sound/soc/intel/catpt/pcm.c:357:60: error: 'struct snd_card' has no member named 'controls'
357 | list_for_each_entry(pos, &component->card->snd_card->controls, list) {
| ^~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
include/linux/list.h:520:9: note: in expansion of macro 'container_of'
520 | container_of(ptr, type, member)
| ^~~~~~~~~~~~
include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
531 | list_entry((ptr)->next, type, member)
| ^~~~~~~~~~
include/linux/list.h:689:20: note: in expansion of macro 'list_first_entry'
689 | for (pos = list_first_entry(head, typeof(*pos), member); \
| ^~~~~~~~~~~~~~~~
sound/soc/intel/catpt/pcm.c:357:9: note: in expansion of macro 'list_for_each_entry'
357 | list_for_each_entry(pos, &component->card->snd_card->controls, list) {
| ^~~~~~~~~~~~~~~~~~~
>> sound/soc/intel/catpt/pcm.c:357:60: error: 'struct snd_card' has no member named 'controls'
357 | list_for_each_entry(pos, &component->card->snd_card->controls, list) {
| ^~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:21:23: note: in expansion of macro '__same_type'
21 | __same_type(*(ptr), void), \
| ^~~~~~~~~~~
include/linux/list.h:520:9: note: in expansion of macro 'container_of'
520 | container_of(ptr, type, member)
| ^~~~~~~~~~~~
include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
531 | list_entry((ptr)->next, type, member)
| ^~~~~~~~~~
include/linux/list.h:689:20: note: in expansion of macro 'list_first_entry'
689 | for (pos = list_first_entry(head, typeof(*pos), member); \
| ^~~~~~~~~~~~~~~~
sound/soc/intel/catpt/pcm.c:357:9: note: in expansion of macro 'list_for_each_entry'
357 | list_for_each_entry(pos, &component->card->snd_card->controls, list) {
| ^~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:338:27: error: expression in static assertion is not an integer
338 | #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
include/linux/list.h:520:9: note: in expansion of macro 'container_of'
520 | container_of(ptr, type, member)
| ^~~~~~~~~~~~
include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
531 | list_entry((ptr)->next, type, member)
| ^~~~~~~~~~
include/linux/list.h:689:20: note: in expansion of macro 'list_first_entry'
689 | for (pos = list_first_entry(head, typeof(*pos), member); \
| ^~~~~~~~~~~~~~~~
sound/soc/intel/catpt/pcm.c:357:9: note: in expansion of macro 'list_for_each_entry'
357 | list_for_each_entry(pos, &component->card->snd_card->controls, list) {
| ^~~~~~~~~~~~~~~~~~~
In file included from include/linux/rculist.h:10,
from include/linux/pid.h:5,
from include/linux/sched.h:14:
>> sound/soc/intel/catpt/pcm.c:357:60: error: 'struct snd_card' has no member named 'controls'
357 | list_for_each_entry(pos, &component->card->snd_card->controls, list) {
| ^~
include/linux/list.h:680:27: note: in definition of macro 'list_entry_is_head'
680 | (&pos->member == (head))
| ^~~~
sound/soc/intel/catpt/pcm.c:357:9: note: in expansion of macro 'list_for_each_entry'
357 | list_for_each_entry(pos, &component->card->snd_card->controls, list) {
| ^~~~~~~~~~~~~~~~~~~
sound/soc/intel/catpt/pcm.c:362:63: error: 'struct snd_card' has no member named 'controls'
362 | if (list_entry_is_head(pos, &component->card->snd_card->controls, list))
| ^~
include/linux/list.h:680:27: note: in definition of macro 'list_entry_is_head'
680 | (&pos->member == (head))
| ^~~~
--
In file included from include/linux/kernel.h:21,
from arch/x86/include/asm/percpu.h:27,
from arch/x86/include/asm/current.h:10,
from include/linux/sched.h:12,
from include/linux/ratelimit.h:6,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from include/linux/pm_runtime.h:11,
from sound/soc/sh/rcar/core.c:93:
sound/soc/sh/rcar/core.c: In function 'rsnd_kctrl_new':
>> sound/soc/sh/rcar/core.c:1813:41: error: 'struct snd_card' has no member named 'controls'
1813 | list_for_each_entry(kctrl, &card->controls, list) {
| ^~
include/linux/container_of.h:19:33: note: in definition of macro 'container_of'
19 | void *__mptr = (void *)(ptr); \
| ^~~
include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
531 | list_entry((ptr)->next, type, member)
| ^~~~~~~~~~
include/linux/list.h:689:20: note: in expansion of macro 'list_first_entry'
689 | for (pos = list_first_entry(head, typeof(*pos), member); \
| ^~~~~~~~~~~~~~~~
sound/soc/sh/rcar/core.c:1813:9: note: in expansion of macro 'list_for_each_entry'
1813 | list_for_each_entry(kctrl, &card->controls, list) {
| ^~~~~~~~~~~~~~~~~~~
In file included from include/linux/bits.h:21,
from include/linux/ratelimit_types.h:5,
from include/linux/ratelimit.h:5:
>> sound/soc/sh/rcar/core.c:1813:41: error: 'struct snd_card' has no member named 'controls'
1813 | list_for_each_entry(kctrl, &card->controls, list) {
| ^~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
include/linux/list.h:520:9: note: in expansion of macro 'container_of'
520 | container_of(ptr, type, member)
| ^~~~~~~~~~~~
include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
531 | list_entry((ptr)->next, type, member)
| ^~~~~~~~~~
include/linux/list.h:689:20: note: in expansion of macro 'list_first_entry'
689 | for (pos = list_first_entry(head, typeof(*pos), member); \
| ^~~~~~~~~~~~~~~~
sound/soc/sh/rcar/core.c:1813:9: note: in expansion of macro 'list_for_each_entry'
1813 | list_for_each_entry(kctrl, &card->controls, list) {
| ^~~~~~~~~~~~~~~~~~~
>> sound/soc/sh/rcar/core.c:1813:41: error: 'struct snd_card' has no member named 'controls'
1813 | list_for_each_entry(kctrl, &card->controls, list) {
| ^~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:21:23: note: in expansion of macro '__same_type'
21 | __same_type(*(ptr), void), \
| ^~~~~~~~~~~
include/linux/list.h:520:9: note: in expansion of macro 'container_of'
520 | container_of(ptr, type, member)
| ^~~~~~~~~~~~
include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
531 | list_entry((ptr)->next, type, member)
| ^~~~~~~~~~
include/linux/list.h:689:20: note: in expansion of macro 'list_first_entry'
689 | for (pos = list_first_entry(head, typeof(*pos), member); \
| ^~~~~~~~~~~~~~~~
sound/soc/sh/rcar/core.c:1813:9: note: in expansion of macro 'list_for_each_entry'
1813 | list_for_each_entry(kctrl, &card->controls, list) {
| ^~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:338:27: error: expression in static assertion is not an integer
338 | #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
include/linux/list.h:520:9: note: in expansion of macro 'container_of'
520 | container_of(ptr, type, member)
| ^~~~~~~~~~~~
include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
531 | list_entry((ptr)->next, type, member)
| ^~~~~~~~~~
include/linux/list.h:689:20: note: in expansion of macro 'list_first_entry'
689 | for (pos = list_first_entry(head, typeof(*pos), member); \
| ^~~~~~~~~~~~~~~~
sound/soc/sh/rcar/core.c:1813:9: note: in expansion of macro 'list_for_each_entry'
1813 | list_for_each_entry(kctrl, &card->controls, list) {
| ^~~~~~~~~~~~~~~~~~~
In file included from include/linux/rculist.h:10,
from include/linux/pid.h:5,
from include/linux/sched.h:14:
>> sound/soc/sh/rcar/core.c:1813:41: error: 'struct snd_card' has no member named 'controls'
1813 | list_for_each_entry(kctrl, &card->controls, list) {
| ^~
include/linux/list.h:680:27: note: in definition of macro 'list_entry_is_head'
680 | (&pos->member == (head))
| ^~~~
sound/soc/sh/rcar/core.c:1813:9: note: in expansion of macro 'list_for_each_entry'
1813 | list_for_each_entry(kctrl, &card->controls, list) {
| ^~~~~~~~~~~~~~~~~~~
vim +542 sound/core/oss/mixer_oss.c
^1da177e4c3f41 Linus Torvalds 2005-04-16 529
f956b4a3ae790e Takashi Iwai 2005-11-17 530 static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
f956b4a3ae790e Takashi Iwai 2005-11-17 531 struct snd_mixer_oss_slot *pslot,
^1da177e4c3f41 Linus Torvalds 2005-04-16 532 unsigned int numid,
^1da177e4c3f41 Linus Torvalds 2005-04-16 533 int *left, int *right)
^1da177e4c3f41 Linus Torvalds 2005-04-16 534 {
f956b4a3ae790e Takashi Iwai 2005-11-17 535 struct snd_ctl_elem_info *uinfo;
f956b4a3ae790e Takashi Iwai 2005-11-17 536 struct snd_ctl_elem_value *uctl;
f956b4a3ae790e Takashi Iwai 2005-11-17 537 struct snd_kcontrol *kctl;
f956b4a3ae790e Takashi Iwai 2005-11-17 538 struct snd_card *card = fmixer->card;
^1da177e4c3f41 Linus Torvalds 2005-04-16 539
^1da177e4c3f41 Linus Torvalds 2005-04-16 540 if (numid == ID_UNKNOWN)
^1da177e4c3f41 Linus Torvalds 2005-04-16 541 return;
^1da177e4c3f41 Linus Torvalds 2005-04-16 @542 down_read(&card->controls_rwsem);
b1e055f67611da Takashi Iwai 2023-07-18 543 kctl = snd_ctl_find_numid_locked(card, numid);
51c816fdd17c63 Takashi Iwai 2021-06-08 544 if (!kctl) {
^1da177e4c3f41 Linus Torvalds 2005-04-16 545 up_read(&card->controls_rwsem);
^1da177e4c3f41 Linus Torvalds 2005-04-16 546 return;
^1da177e4c3f41 Linus Torvalds 2005-04-16 547 }
ca2c0966562cfb Takashi Iwai 2005-09-09 548 uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
ca2c0966562cfb Takashi Iwai 2005-09-09 549 uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
^1da177e4c3f41 Linus Torvalds 2005-04-16 550 if (uinfo == NULL || uctl == NULL)
^1da177e4c3f41 Linus Torvalds 2005-04-16 551 goto __unalloc;
7c22f1aaa23370 Takashi Iwai 2005-10-10 552 if (kctl->info(kctl, uinfo))
7c22f1aaa23370 Takashi Iwai 2005-10-10 553 goto __unalloc;
7c22f1aaa23370 Takashi Iwai 2005-10-10 554 if (kctl->get(kctl, uctl))
7c22f1aaa23370 Takashi Iwai 2005-10-10 555 goto __unalloc;
7c22f1aaa23370 Takashi Iwai 2005-10-10 556 if (uinfo->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN &&
7c22f1aaa23370 Takashi Iwai 2005-10-10 557 uinfo->value.integer.min == 0 && uinfo->value.integer.max == 1)
7c22f1aaa23370 Takashi Iwai 2005-10-10 558 goto __unalloc;
^1da177e4c3f41 Linus Torvalds 2005-04-16 559 *left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]);
^1da177e4c3f41 Linus Torvalds 2005-04-16 560 if (uinfo->count > 1)
^1da177e4c3f41 Linus Torvalds 2005-04-16 561 *right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]);
^1da177e4c3f41 Linus Torvalds 2005-04-16 562 __unalloc:
^1da177e4c3f41 Linus Torvalds 2005-04-16 563 up_read(&card->controls_rwsem);
^1da177e4c3f41 Linus Torvalds 2005-04-16 564 kfree(uctl);
^1da177e4c3f41 Linus Torvalds 2005-04-16 565 kfree(uinfo);
^1da177e4c3f41 Linus Torvalds 2005-04-16 566 }
^1da177e4c3f41 Linus Torvalds 2005-04-16 567
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2023-09-03 22:40 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-24 21:02 [PATCH 0/2][RFC] Refactor snd primitives refcounters cujomalainey
2023-08-24 21:02 ` [PATCH 1/2] ALSA: core: add snd_device_init cujomalainey
2023-08-24 22:23 ` kernel test robot
2023-08-25 10:46 ` Takashi Iwai
2023-08-24 21:02 ` [PATCH 2/2] ALSA: core: split control primitives out of snd_card cujomalainey
2023-08-24 21:15 ` Mark Brown
2023-08-25 10:57 ` Takashi Iwai
2023-09-03 22:38 ` kernel test robot
2023-08-25 11:15 ` [PATCH 0/2][RFC] Refactor snd primitives refcounters Takashi Iwai
2023-08-25 17:42 ` Curtis Malainey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).