All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] Modernize sequecner device binding
@ 2015-02-16 16:55 Takashi Iwai
  2015-02-16 16:55 ` [PATCH 1/6] ALSA: seq: Move EXPORT_SYMBOL() after each function Takashi Iwai
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Takashi Iwai @ 2015-02-16 16:55 UTC (permalink / raw)
  To: alsa-devel

Hi,

this is a series of patches for 3.21 (or whatever the next-to-next)
to sanitze and modernize the device binding code of ALSA sequencer
core.


Takashi

Takashi Iwai (6):
  ALSA: seq: Move EXPORT_SYMBOL() after each function
  ALSA: seq: Don't compile snd_seq_device_load_drivers() for built-in
  ALSA: seq: Rewrite sequencer device binding with standard bus
  ALSA: seq: Clean up device and driver structs
  ALSA: seq: Define driver object in each driver
  ALSA: seq: Drop snd_seq_autoload_lock() and _unlock()

 include/sound/seq_device.h         |  46 +--
 include/sound/seq_kernel.h         |   6 +-
 sound/core/seq/oss/seq_oss.c       |  22 +-
 sound/core/seq/oss/seq_oss_synth.c |   6 +-
 sound/core/seq/oss/seq_oss_synth.h |   4 +-
 sound/core/seq/seq_device.c        | 569 +++++++++----------------------------
 sound/core/seq/seq_dummy.c         |   6 +-
 sound/core/seq/seq_midi.c          |  36 +--
 sound/drivers/opl3/opl3_seq.c      |  34 +--
 sound/drivers/opl4/opl4_seq.c      |  33 +--
 sound/isa/sb/emu8000_synth.c       |  35 +--
 sound/pci/emu10k1/emu10k1_synth.c  |  35 +--
 12 files changed, 256 insertions(+), 576 deletions(-)

-- 
2.3.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/6] ALSA: seq: Move EXPORT_SYMBOL() after each function
  2015-02-16 16:55 [PATCH 0/6] Modernize sequecner device binding Takashi Iwai
@ 2015-02-16 16:55 ` Takashi Iwai
  2015-02-16 16:55 ` [PATCH 2/6] ALSA: seq: Don't compile snd_seq_device_load_drivers() for built-in Takashi Iwai
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Takashi Iwai @ 2015-02-16 16:55 UTC (permalink / raw)
  To: alsa-devel

... to follow the standard coding style.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/seq/seq_device.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 0631bdadd12b..a752a79a8d3a 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -133,11 +133,13 @@ void snd_seq_autoload_lock(void)
 {
 	atomic_inc(&snd_seq_in_init);
 }
+EXPORT_SYMBOL(snd_seq_autoload_lock);
 
 void snd_seq_autoload_unlock(void)
 {
 	atomic_dec(&snd_seq_in_init);
 }
+EXPORT_SYMBOL(snd_seq_autoload_unlock);
 
 static void autoload_drivers(void)
 {
@@ -195,10 +197,12 @@ void snd_seq_autoload_init(void)
 	queue_autoload_drivers();
 #endif
 }
+EXPORT_SYMBOL(snd_seq_autoload_init);
 #else
 #define try_autoload(ops) /* NOP */
 #endif
 
+
 void snd_seq_device_load_drivers(void)
 {
 #ifdef CONFIG_MODULES
@@ -206,6 +210,7 @@ void snd_seq_device_load_drivers(void)
 	flush_work(&autoload_work);
 #endif
 }
+EXPORT_SYMBOL(snd_seq_device_load_drivers);
 
 /*
  * register a sequencer device
@@ -268,6 +273,7 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
 
 	return 0;
 }
+EXPORT_SYMBOL(snd_seq_device_new);
 
 /*
  * free the existing device
@@ -326,6 +332,7 @@ static int snd_seq_device_dev_register(struct snd_device *device)
 	unlock_driver(ops);
 	return 0;
 }
+EXPORT_SYMBOL(snd_seq_device_register_driver);
 
 /*
  * disconnect the device
@@ -344,6 +351,7 @@ static int snd_seq_device_dev_disconnect(struct snd_device *device)
 	unlock_driver(ops);
 	return 0;
 }
+EXPORT_SYMBOL(snd_seq_device_unregister_driver);
 
 /*
  * register device driver
@@ -604,13 +612,3 @@ static void __exit alsa_seq_device_exit(void)
 
 module_init(alsa_seq_device_init)
 module_exit(alsa_seq_device_exit)
-
-EXPORT_SYMBOL(snd_seq_device_load_drivers);
-EXPORT_SYMBOL(snd_seq_device_new);
-EXPORT_SYMBOL(snd_seq_device_register_driver);
-EXPORT_SYMBOL(snd_seq_device_unregister_driver);
-#ifdef CONFIG_MODULES
-EXPORT_SYMBOL(snd_seq_autoload_init);
-EXPORT_SYMBOL(snd_seq_autoload_lock);
-EXPORT_SYMBOL(snd_seq_autoload_unlock);
-#endif
-- 
2.3.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/6] ALSA: seq: Don't compile snd_seq_device_load_drivers() for built-in
  2015-02-16 16:55 [PATCH 0/6] Modernize sequecner device binding Takashi Iwai
  2015-02-16 16:55 ` [PATCH 1/6] ALSA: seq: Move EXPORT_SYMBOL() after each function Takashi Iwai
@ 2015-02-16 16:55 ` Takashi Iwai
  2015-02-16 16:55 ` [PATCH 3/6] ALSA: seq: Rewrite sequencer device binding with standard bus Takashi Iwai
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Takashi Iwai @ 2015-02-16 16:55 UTC (permalink / raw)
  To: alsa-devel

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/seq_device.h  | 4 ++++
 sound/core/seq/seq_device.c | 9 +++------
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/sound/seq_device.h b/include/sound/seq_device.h
index 2b5f24cc7548..d52433563da2 100644
--- a/include/sound/seq_device.h
+++ b/include/sound/seq_device.h
@@ -67,7 +67,11 @@ struct snd_seq_dev_ops {
 /*
  * prototypes
  */
+#ifdef CONFIG_MODULES
 void snd_seq_device_load_drivers(void);
+#else
+#define snd_seq_device_load_drivers()
+#endif
 int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, struct snd_seq_device **result);
 int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, int argsize);
 int snd_seq_device_unregister_driver(char *id);
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index a752a79a8d3a..075a66c0cc6a 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -198,19 +198,16 @@ void snd_seq_autoload_init(void)
 #endif
 }
 EXPORT_SYMBOL(snd_seq_autoload_init);
-#else
-#define try_autoload(ops) /* NOP */
-#endif
-
 
 void snd_seq_device_load_drivers(void)
 {
-#ifdef CONFIG_MODULES
 	queue_autoload_drivers();
 	flush_work(&autoload_work);
-#endif
 }
 EXPORT_SYMBOL(snd_seq_device_load_drivers);
+#else
+#define try_autoload(ops) /* NOP */
+#endif
 
 /*
  * register a sequencer device
-- 
2.3.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/6] ALSA: seq: Rewrite sequencer device binding with standard bus
  2015-02-16 16:55 [PATCH 0/6] Modernize sequecner device binding Takashi Iwai
  2015-02-16 16:55 ` [PATCH 1/6] ALSA: seq: Move EXPORT_SYMBOL() after each function Takashi Iwai
  2015-02-16 16:55 ` [PATCH 2/6] ALSA: seq: Don't compile snd_seq_device_load_drivers() for built-in Takashi Iwai
@ 2015-02-16 16:55 ` Takashi Iwai
  2015-02-16 16:55 ` [PATCH 4/6] ALSA: seq: Clean up device and driver structs Takashi Iwai
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Takashi Iwai @ 2015-02-16 16:55 UTC (permalink / raw)
  To: alsa-devel

We've used the old house-made code for binding the sequencer device
and driver.  This can be far better implemented with the standard
bus nowadays.

This patch refactors the whole sequencer binding code with the bus
/sys/bus/snd_seq.  The devices appear as id-card-device on this bus
and are bound with the drivers corresponding to the given id like the
former implementation.  The module autoload is also kept like before.

There is no change in API functions by this patch, and almost all
transitions are kept inside seq_device.c.  The proc file output will
change slightly but kept compatible as much as possible.

Further integration works will follow in later patches.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/seq_device.h  |   3 +
 sound/core/seq/seq_device.c | 541 ++++++++++++++------------------------------
 2 files changed, 170 insertions(+), 374 deletions(-)

diff --git a/include/sound/seq_device.h b/include/sound/seq_device.h
index d52433563da2..ea256b825146 100644
--- a/include/sound/seq_device.h
+++ b/include/sound/seq_device.h
@@ -43,8 +43,11 @@ struct snd_seq_device {
 	void *private_data;	/* private data for the caller */
 	void (*private_free)(struct snd_seq_device *device);
 	struct list_head list;	/* link to next device */
+	struct device dev;
 };
 
+#define to_seq_dev(_dev) \
+	container_of(_dev, struct snd_seq_device, dev)
 
 /* driver operators
  * init_device:
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 075a66c0cc6a..d3320ffe43c2 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -36,6 +36,7 @@
  *
  */
 
+#include <linux/device.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <sound/core.h>
@@ -51,77 +52,57 @@ MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ALSA sequencer device management");
 MODULE_LICENSE("GPL");
 
-/* driver state */
-#define DRIVER_EMPTY		0
-#define DRIVER_LOADED		(1<<0)
-#define DRIVER_REQUESTED	(1<<1)
-#define DRIVER_LOCKED		(1<<2)
-#define DRIVER_REQUESTING	(1<<3)
+struct snd_seq_driver {
+	struct device_driver driver;
+	char id[ID_LEN];
+	int argsize;
+	struct snd_seq_dev_ops ops;
+};
 
-struct ops_list {
-	char id[ID_LEN];	/* driver id */
-	int driver;		/* driver state */
-	int used;		/* reference counter */
-	int argsize;		/* argument size */
+#define to_seq_drv(_drv) \
+	container_of(_drv, struct snd_seq_driver, driver)
 
-	/* operators */
-	struct snd_seq_dev_ops ops;
+/*
+ * bus definition
+ */
+static int snd_seq_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct snd_seq_device *sdev = to_seq_dev(dev);
+	struct snd_seq_driver *sdrv = to_seq_drv(drv);
 
-	/* registered devices */
-	struct list_head dev_list;	/* list of devices */
-	int num_devices;	/* number of associated devices */
-	int num_init_devices;	/* number of initialized devices */
-	struct mutex reg_mutex;
+	return strcmp(sdrv->id, sdev->id) == 0 &&
+		sdrv->argsize == sdev->argsize;
+}
 
-	struct list_head list;	/* next driver */
+static struct bus_type snd_seq_bus_type = {
+	.name = "snd_seq",
+	.match = snd_seq_bus_match,
 };
 
-
-static LIST_HEAD(opslist);
-static int num_ops;
-static DEFINE_MUTEX(ops_mutex);
+/*
+ * proc interface -- just for compatibility
+ */
 #ifdef CONFIG_PROC_FS
 static struct snd_info_entry *info_entry;
-#endif
 
-/*
- * prototypes
- */
-static int snd_seq_device_free(struct snd_seq_device *dev);
-static int snd_seq_device_dev_free(struct snd_device *device);
-static int snd_seq_device_dev_register(struct snd_device *device);
-static int snd_seq_device_dev_disconnect(struct snd_device *device);
-
-static int init_device(struct snd_seq_device *dev, struct ops_list *ops);
-static int free_device(struct snd_seq_device *dev, struct ops_list *ops);
-static struct ops_list *find_driver(char *id, int create_if_empty);
-static struct ops_list *create_driver(char *id);
-static void unlock_driver(struct ops_list *ops);
-static void remove_drivers(void);
+static int print_dev_info(struct device *dev, void *data)
+{
+	struct snd_seq_device *sdev = to_seq_dev(dev);
+	struct snd_info_buffer *buffer = data;
 
-/*
- * show all drivers and their status
- */
+	snd_iprintf(buffer, "snd-%s,%s,%d\n", sdev->id,
+		    dev->driver ? "loaded" : "empty",
+		    dev->driver ? 1 : 0);
+	return 0;
+}
 
-#ifdef CONFIG_PROC_FS
 static void snd_seq_device_info(struct snd_info_entry *entry,
 				struct snd_info_buffer *buffer)
 {
-	struct ops_list *ops;
-
-	mutex_lock(&ops_mutex);
-	list_for_each_entry(ops, &opslist, list) {
-		snd_iprintf(buffer, "snd-%s%s%s%s,%d\n",
-				ops->id,
-				ops->driver & DRIVER_LOADED ? ",loaded" : (ops->driver == DRIVER_EMPTY ? ",empty" : ""),
-				ops->driver & DRIVER_REQUESTED ? ",requested" : "",
-				ops->driver & DRIVER_LOCKED ? ",locked" : "",
-				ops->num_devices);
-	}
-	mutex_unlock(&ops_mutex);
+	bus_for_each_dev(&snd_seq_bus_type, NULL, buffer, print_dev_info);
 }
 #endif
- 
+
 /*
  * load all registered drivers (called from seq_clientmgr.c)
  */
@@ -141,52 +122,29 @@ void snd_seq_autoload_unlock(void)
 }
 EXPORT_SYMBOL(snd_seq_autoload_unlock);
 
-static void autoload_drivers(void)
+static int request_seq_drv(struct device *dev, void *data)
 {
-	/* avoid reentrance */
-	if (atomic_inc_return(&snd_seq_in_init) == 1) {
-		struct ops_list *ops;
-
-		mutex_lock(&ops_mutex);
-		list_for_each_entry(ops, &opslist, list) {
-			if ((ops->driver & DRIVER_REQUESTING) &&
-			    !(ops->driver & DRIVER_REQUESTED)) {
-				ops->used++;
-				mutex_unlock(&ops_mutex);
-				ops->driver |= DRIVER_REQUESTED;
-				request_module("snd-%s", ops->id);
-				mutex_lock(&ops_mutex);
-				ops->used--;
-			}
-		}
-		mutex_unlock(&ops_mutex);
-	}
-	atomic_dec(&snd_seq_in_init);
-}
+	struct snd_seq_device *sdev = to_seq_dev(dev);
 
-static void call_autoload(struct work_struct *work)
-{
-	autoload_drivers();
+	if (!dev->driver)
+		request_module("snd-%s", sdev->id);
+	return 0;
 }
 
-static DECLARE_WORK(autoload_work, call_autoload);
-
-static void try_autoload(struct ops_list *ops)
+static void autoload_drivers(struct work_struct *work)
 {
-	if (!ops->driver) {
-		ops->driver |= DRIVER_REQUESTING;
-		schedule_work(&autoload_work);
-	}
+	/* avoid reentrance */
+	if (atomic_inc_return(&snd_seq_in_init) == 1)
+		bus_for_each_dev(&snd_seq_bus_type, NULL, NULL,
+				 request_seq_drv);
+	atomic_dec(&snd_seq_in_init);
 }
 
+static DECLARE_WORK(autoload_work, autoload_drivers);
+
 static void queue_autoload_drivers(void)
 {
-	struct ops_list *ops;
-
-	mutex_lock(&ops_mutex);
-	list_for_each_entry(ops, &opslist, list)
-		try_autoload(ops);
-	mutex_unlock(&ops_mutex);
+	schedule_work(&autoload_work);
 }
 
 void snd_seq_autoload_init(void)
@@ -206,10 +164,51 @@ void snd_seq_device_load_drivers(void)
 }
 EXPORT_SYMBOL(snd_seq_device_load_drivers);
 #else
-#define try_autoload(ops) /* NOP */
+#define queue_autoload_drivers() /* NOP */
 #endif
 
 /*
+ * device management
+ */
+static int snd_seq_device_dev_free(struct snd_device *device)
+{
+	struct snd_seq_device *dev = device->device_data;
+
+	put_device(&dev->dev);
+	return 0;
+}
+
+static int snd_seq_device_dev_register(struct snd_device *device)
+{
+	struct snd_seq_device *dev = device->device_data;
+	int err;
+
+	err = device_add(&dev->dev);
+	if (err < 0)
+		return err;
+	if (!dev->dev.driver)
+		queue_autoload_drivers();
+	return 0;
+}
+
+static int snd_seq_device_dev_disconnect(struct snd_device *device)
+{
+	struct snd_seq_device *dev = device->device_data;
+
+	device_del(&dev->dev);
+	return 0;
+}
+
+static void snd_seq_dev_release(struct device *dev)
+{
+	struct snd_seq_device *sdev = to_seq_dev(dev);
+
+	if (sdev->private_free)
+		sdev->private_free(sdev);
+	kfree(sdev);
+}
+
+/*
  * register a sequencer device
  * card = card info
  * device = device number (if any)
@@ -220,7 +219,6 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
 		       struct snd_seq_device **result)
 {
 	struct snd_seq_device *dev;
-	struct ops_list *ops;
 	int err;
 	static struct snd_device_ops dops = {
 		.dev_free = snd_seq_device_dev_free,
@@ -234,15 +232,9 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
 	if (snd_BUG_ON(!id))
 		return -EINVAL;
 
-	ops = find_driver(id, 1);
-	if (ops == NULL)
-		return -ENOMEM;
-
-	dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL);
-	if (dev == NULL) {
-		unlock_driver(ops);
+	dev = kzalloc(sizeof(*dev) + argsize, GFP_KERNEL);
+	if (!dev)
 		return -ENOMEM;
-	}
 
 	/* set up device info */
 	dev->card = card;
@@ -251,20 +243,19 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
 	dev->argsize = argsize;
 	dev->status = SNDRV_SEQ_DEVICE_FREE;
 
-	/* add this device to the list */
-	mutex_lock(&ops->reg_mutex);
-	list_add_tail(&dev->list, &ops->dev_list);
-	ops->num_devices++;
-	mutex_unlock(&ops->reg_mutex);
+	device_initialize(&dev->dev);
+	dev->dev.parent = &card->card_dev;
+	dev->dev.bus = &snd_seq_bus_type;
+	dev->dev.release = snd_seq_dev_release;
+	dev_set_name(&dev->dev, "%s-%d-%d", dev->id, card->number, device);
 
-	if ((err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops)) < 0) {
-		snd_seq_device_free(dev);
+	/* add this device to the list */
+	err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops);
+	if (err < 0) {
+		put_device(&dev->dev);
 		return err;
 	}
 	
-	try_autoload(ops);
-	unlock_driver(ops);
-
 	if (result)
 		*result = dev;
 
@@ -273,82 +264,33 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
 EXPORT_SYMBOL(snd_seq_device_new);
 
 /*
- * free the existing device
- */
-static int snd_seq_device_free(struct snd_seq_device *dev)
-{
-	struct ops_list *ops;
-
-	if (snd_BUG_ON(!dev))
-		return -EINVAL;
-
-	ops = find_driver(dev->id, 0);
-	if (ops == NULL)
-		return -ENXIO;
-
-	/* remove the device from the list */
-	mutex_lock(&ops->reg_mutex);
-	list_del(&dev->list);
-	ops->num_devices--;
-	mutex_unlock(&ops->reg_mutex);
-
-	free_device(dev, ops);
-	if (dev->private_free)
-		dev->private_free(dev);
-	kfree(dev);
-
-	unlock_driver(ops);
-
-	return 0;
-}
-
-static int snd_seq_device_dev_free(struct snd_device *device)
-{
-	struct snd_seq_device *dev = device->device_data;
-	return snd_seq_device_free(dev);
-}
-
-/*
- * register the device
+ * driver binding - just pass to each driver callback
  */
-static int snd_seq_device_dev_register(struct snd_device *device)
+static int snd_seq_drv_probe(struct device *dev)
 {
-	struct snd_seq_device *dev = device->device_data;
-	struct ops_list *ops;
-
-	ops = find_driver(dev->id, 0);
-	if (ops == NULL)
-		return -ENOENT;
-
-	/* initialize this device if the corresponding driver was
-	 * already loaded
-	 */
-	if (ops->driver & DRIVER_LOADED)
-		init_device(dev, ops);
+	struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
+	struct snd_seq_device *sdev = to_seq_dev(dev);
+	int err;
 
-	unlock_driver(ops);
+	err = sdrv->ops.init_device(sdev);
+	if (err < 0)
+		return err;
+	sdev->status = SNDRV_SEQ_DEVICE_REGISTERED;
 	return 0;
 }
-EXPORT_SYMBOL(snd_seq_device_register_driver);
 
-/*
- * disconnect the device
- */
-static int snd_seq_device_dev_disconnect(struct snd_device *device)
+static int snd_seq_drv_remove(struct device *dev)
 {
-	struct snd_seq_device *dev = device->device_data;
-	struct ops_list *ops;
-
-	ops = find_driver(dev->id, 0);
-	if (ops == NULL)
-		return -ENOENT;
-
-	free_device(dev, ops);
+	struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
+	struct snd_seq_device *sdev = to_seq_dev(dev);
+	int err;
 
-	unlock_driver(ops);
+	err = sdrv->ops.free_device(sdev);
+	if (err < 0)
+		return err;
+	sdev->status = SNDRV_SEQ_DEVICE_FREE;
 	return 0;
 }
-EXPORT_SYMBOL(snd_seq_device_unregister_driver);
 
 /*
  * register device driver
@@ -358,226 +300,66 @@ EXPORT_SYMBOL(snd_seq_device_unregister_driver);
 int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
 				   int argsize)
 {
-	struct ops_list *ops;
-	struct snd_seq_device *dev;
+	struct snd_seq_driver *sdrv;
+	int err;
 
 	if (id == NULL || entry == NULL ||
 	    entry->init_device == NULL || entry->free_device == NULL)
 		return -EINVAL;
 
-	ops = find_driver(id, 1);
-	if (ops == NULL)
+	sdrv = kzalloc(sizeof(*sdrv), GFP_KERNEL);
+	if (!sdrv)
 		return -ENOMEM;
-	if (ops->driver & DRIVER_LOADED) {
-		pr_warn("ALSA: seq: driver_register: driver '%s' already exists\n", id);
-		unlock_driver(ops);
-		return -EBUSY;
-	}
-
-	mutex_lock(&ops->reg_mutex);
-	/* copy driver operators */
-	ops->ops = *entry;
-	ops->driver |= DRIVER_LOADED;
-	ops->argsize = argsize;
 
-	/* initialize existing devices if necessary */
-	list_for_each_entry(dev, &ops->dev_list, list) {
-		init_device(dev, ops);
-	}
-	mutex_unlock(&ops->reg_mutex);
-
-	unlock_driver(ops);
-
-	return 0;
+	sdrv->driver.name = id;
+	sdrv->driver.bus = &snd_seq_bus_type;
+	sdrv->driver.probe = snd_seq_drv_probe;
+	sdrv->driver.remove = snd_seq_drv_remove;
+	strlcpy(sdrv->id, id, sizeof(sdrv->id));
+	sdrv->argsize = argsize;
+	sdrv->ops = *entry;
+
+	err = driver_register(&sdrv->driver);
+	if (err < 0)
+		kfree(sdrv);
+	return err;
 }
+EXPORT_SYMBOL(snd_seq_device_register_driver);
 
-
-/*
- * create driver record
+/* callback to find a specific driver; data is a pointer to the id string ptr.
+ * when the id matches, store the driver pointer in return and break the loop.
  */
-static struct ops_list * create_driver(char *id)
+static int find_drv(struct device_driver *drv, void *data)
 {
-	struct ops_list *ops;
-
-	ops = kzalloc(sizeof(*ops), GFP_KERNEL);
-	if (ops == NULL)
-		return ops;
-
-	/* set up driver entry */
-	strlcpy(ops->id, id, sizeof(ops->id));
-	mutex_init(&ops->reg_mutex);
-	/*
-	 * The ->reg_mutex locking rules are per-driver, so we create
-	 * separate per-driver lock classes:
-	 */
-	lockdep_set_class(&ops->reg_mutex, (struct lock_class_key *)id);
-
-	ops->driver = DRIVER_EMPTY;
-	INIT_LIST_HEAD(&ops->dev_list);
-	/* lock this instance */
-	ops->used = 1;
-
-	/* register driver entry */
-	mutex_lock(&ops_mutex);
-	list_add_tail(&ops->list, &opslist);
-	num_ops++;
-	mutex_unlock(&ops_mutex);
-
-	return ops;
-}
+	struct snd_seq_driver *sdrv = to_seq_drv(drv);
+	void **ptr = (void **)data;
 
+	if (strcmp(sdrv->id, *ptr))
+		return 0; /* id don't match, continue the loop */
+	*ptr = sdrv;
+	return 1; /* break the loop */
+}
 
 /*
  * unregister the specified driver
  */
 int snd_seq_device_unregister_driver(char *id)
 {
-	struct ops_list *ops;
-	struct snd_seq_device *dev;
+	struct snd_seq_driver *sdrv = (struct snd_seq_driver *)id;
 
-	ops = find_driver(id, 0);
-	if (ops == NULL)
+	if (!bus_for_each_drv(&snd_seq_bus_type, NULL, &sdrv, find_drv))
 		return -ENXIO;
-	if (! (ops->driver & DRIVER_LOADED) ||
-	    (ops->driver & DRIVER_LOCKED)) {
-		pr_err("ALSA: seq: driver_unregister: cannot unload driver '%s': status=%x\n",
-			   id, ops->driver);
-		unlock_driver(ops);
-		return -EBUSY;
-	}
-
-	/* close and release all devices associated with this driver */
-	mutex_lock(&ops->reg_mutex);
-	ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */
-	list_for_each_entry(dev, &ops->dev_list, list) {
-		free_device(dev, ops);
-	}
-
-	ops->driver = 0;
-	if (ops->num_init_devices > 0)
-		pr_err("ALSA: seq: free_driver: init_devices > 0!! (%d)\n",
-			   ops->num_init_devices);
-	mutex_unlock(&ops->reg_mutex);
-
-	unlock_driver(ops);
-
-	/* remove empty driver entries */
-	remove_drivers();
-
+	driver_unregister(&sdrv->driver);
+	kfree(sdrv);
 	return 0;
 }
-
-
-/*
- * remove empty driver entries
- */
-static void remove_drivers(void)
-{
-	struct list_head *head;
-
-	mutex_lock(&ops_mutex);
-	head = opslist.next;
-	while (head != &opslist) {
-		struct ops_list *ops = list_entry(head, struct ops_list, list);
-		if (! (ops->driver & DRIVER_LOADED) &&
-		    ops->used == 0 && ops->num_devices == 0) {
-			head = head->next;
-			list_del(&ops->list);
-			kfree(ops);
-			num_ops--;
-		} else
-			head = head->next;
-	}
-	mutex_unlock(&ops_mutex);
-}
-
-/*
- * initialize the device - call init_device operator
- */
-static int init_device(struct snd_seq_device *dev, struct ops_list *ops)
-{
-	if (! (ops->driver & DRIVER_LOADED))
-		return 0; /* driver is not loaded yet */
-	if (dev->status != SNDRV_SEQ_DEVICE_FREE)
-		return 0; /* already initialized */
-	if (ops->argsize != dev->argsize) {
-		pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n",
-			   dev->name, ops->id, ops->argsize, dev->argsize);
-		return -EINVAL;
-	}
-	if (ops->ops.init_device(dev) >= 0) {
-		dev->status = SNDRV_SEQ_DEVICE_REGISTERED;
-		ops->num_init_devices++;
-	} else {
-		pr_err("ALSA: seq: init_device failed: %s: %s\n",
-			   dev->name, dev->id);
-	}
-
-	return 0;
-}
-
-/*
- * release the device - call free_device operator
- */
-static int free_device(struct snd_seq_device *dev, struct ops_list *ops)
-{
-	int result;
-
-	if (! (ops->driver & DRIVER_LOADED))
-		return 0; /* driver is not loaded yet */
-	if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED)
-		return 0; /* not registered */
-	if (ops->argsize != dev->argsize) {
-		pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n",
-			   dev->name, ops->id, ops->argsize, dev->argsize);
-		return -EINVAL;
-	}
-	if ((result = ops->ops.free_device(dev)) >= 0 || result == -ENXIO) {
-		dev->status = SNDRV_SEQ_DEVICE_FREE;
-		dev->driver_data = NULL;
-		ops->num_init_devices--;
-	} else {
-		pr_err("ALSA: seq: free_device failed: %s: %s\n",
-			   dev->name, dev->id);
-	}
-
-	return 0;
-}
-
-/*
- * find the matching driver with given id
- */
-static struct ops_list * find_driver(char *id, int create_if_empty)
-{
-	struct ops_list *ops;
-
-	mutex_lock(&ops_mutex);
-	list_for_each_entry(ops, &opslist, list) {
-		if (strcmp(ops->id, id) == 0) {
-			ops->used++;
-			mutex_unlock(&ops_mutex);
-			return ops;
-		}
-	}
-	mutex_unlock(&ops_mutex);
-	if (create_if_empty)
-		return create_driver(id);
-	return NULL;
-}
-
-static void unlock_driver(struct ops_list *ops)
-{
-	mutex_lock(&ops_mutex);
-	ops->used--;
-	mutex_unlock(&ops_mutex);
-}
-
+EXPORT_SYMBOL(snd_seq_device_unregister_driver);
 
 /*
  * module part
  */
 
-static int __init alsa_seq_device_init(void)
+static int __init seq_dev_proc_init(void)
 {
 #ifdef CONFIG_PROC_FS
 	info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers",
@@ -594,17 +376,28 @@ static int __init alsa_seq_device_init(void)
 	return 0;
 }
 
+static int __init alsa_seq_device_init(void)
+{
+	int err;
+
+	err = bus_register(&snd_seq_bus_type);
+	if (err < 0)
+		return err;
+	err = seq_dev_proc_init();
+	if (err < 0)
+		bus_unregister(&snd_seq_bus_type);
+	return err;
+}
+
 static void __exit alsa_seq_device_exit(void)
 {
 #ifdef CONFIG_MODULES
 	cancel_work_sync(&autoload_work);
 #endif
-	remove_drivers();
 #ifdef CONFIG_PROC_FS
 	snd_info_free_entry(info_entry);
 #endif
-	if (num_ops)
-		pr_err("ALSA: seq: drivers not released (%d)\n", num_ops);
+	bus_unregister(&snd_seq_bus_type);
 }
 
 module_init(alsa_seq_device_init)
-- 
2.3.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/6] ALSA: seq: Clean up device and driver structs
  2015-02-16 16:55 [PATCH 0/6] Modernize sequecner device binding Takashi Iwai
                   ` (2 preceding siblings ...)
  2015-02-16 16:55 ` [PATCH 3/6] ALSA: seq: Rewrite sequencer device binding with standard bus Takashi Iwai
@ 2015-02-16 16:55 ` Takashi Iwai
  2015-02-16 16:55 ` [PATCH 5/6] ALSA: seq: Define driver object in each driver Takashi Iwai
  2015-02-16 16:55 ` [PATCH 6/6] ALSA: seq: Drop snd_seq_autoload_lock() and _unlock() Takashi Iwai
  5 siblings, 0 replies; 7+ messages in thread
From: Takashi Iwai @ 2015-02-16 16:55 UTC (permalink / raw)
  To: alsa-devel

Use const string pointer instead of copying the id string to each
object.  Also drop the status and list fields of snd_seq_device struct
that are no longer used.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/seq_device.h  | 18 ++++++------------
 sound/core/seq/seq_device.c | 31 ++++++++++---------------------
 2 files changed, 16 insertions(+), 33 deletions(-)

diff --git a/include/sound/seq_device.h b/include/sound/seq_device.h
index ea256b825146..b13cd2930d32 100644
--- a/include/sound/seq_device.h
+++ b/include/sound/seq_device.h
@@ -25,24 +25,16 @@
  * registered device information
  */
 
-#define ID_LEN	32
-
-/* status flag */
-#define SNDRV_SEQ_DEVICE_FREE		0
-#define SNDRV_SEQ_DEVICE_REGISTERED	1
-
 struct snd_seq_device {
 	/* device info */
 	struct snd_card *card;	/* sound card */
 	int device;		/* device number */
-	char id[ID_LEN];	/* driver id */
+	const char *id;		/* driver id */
 	char name[80];		/* device name */
 	int argsize;		/* size of the argument */
 	void *driver_data;	/* private data for driver */
-	int status;		/* flag - read only */
 	void *private_data;	/* private data for the caller */
 	void (*private_free)(struct snd_seq_device *device);
-	struct list_head list;	/* link to next device */
 	struct device dev;
 };
 
@@ -75,9 +67,11 @@ void snd_seq_device_load_drivers(void);
 #else
 #define snd_seq_device_load_drivers()
 #endif
-int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, struct snd_seq_device **result);
-int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, int argsize);
-int snd_seq_device_unregister_driver(char *id);
+int snd_seq_device_new(struct snd_card *card, int device, const char *id,
+		       int argsize, struct snd_seq_device **result);
+int snd_seq_device_register_driver(const char *id,
+				   struct snd_seq_dev_ops *entry, int argsize);
+int snd_seq_device_unregister_driver(const char *id);
 
 #define SNDRV_SEQ_DEVICE_ARGPTR(dev) (void *)((char *)(dev) + sizeof(struct snd_seq_device))
 
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index d3320ffe43c2..49daf6e3a387 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -54,7 +54,7 @@ MODULE_LICENSE("GPL");
 
 struct snd_seq_driver {
 	struct device_driver driver;
-	char id[ID_LEN];
+	const char *id;
 	int argsize;
 	struct snd_seq_dev_ops ops;
 };
@@ -215,8 +215,8 @@ static void snd_seq_dev_release(struct device *dev)
  * id = id of driver
  * result = return pointer (NULL allowed if unnecessary)
  */
-int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
-		       struct snd_seq_device **result)
+int snd_seq_device_new(struct snd_card *card, int device, const char *id,
+		       int argsize, struct snd_seq_device **result)
 {
 	struct snd_seq_device *dev;
 	int err;
@@ -239,9 +239,8 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
 	/* set up device info */
 	dev->card = card;
 	dev->device = device;
-	strlcpy(dev->id, id, sizeof(dev->id));
+	dev->id = id;
 	dev->argsize = argsize;
-	dev->status = SNDRV_SEQ_DEVICE_FREE;
 
 	device_initialize(&dev->dev);
 	dev->dev.parent = &card->card_dev;
@@ -270,26 +269,16 @@ static int snd_seq_drv_probe(struct device *dev)
 {
 	struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
 	struct snd_seq_device *sdev = to_seq_dev(dev);
-	int err;
 
-	err = sdrv->ops.init_device(sdev);
-	if (err < 0)
-		return err;
-	sdev->status = SNDRV_SEQ_DEVICE_REGISTERED;
-	return 0;
+	return sdrv->ops.init_device(sdev);
 }
 
 static int snd_seq_drv_remove(struct device *dev)
 {
 	struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
 	struct snd_seq_device *sdev = to_seq_dev(dev);
-	int err;
 
-	err = sdrv->ops.free_device(sdev);
-	if (err < 0)
-		return err;
-	sdev->status = SNDRV_SEQ_DEVICE_FREE;
-	return 0;
+	return sdrv->ops.free_device(sdev);
 }
 
 /*
@@ -297,8 +286,8 @@ static int snd_seq_drv_remove(struct device *dev)
  * id = driver id
  * entry = driver operators - duplicated to each instance
  */
-int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
-				   int argsize)
+int snd_seq_device_register_driver(const char *id,
+				   struct snd_seq_dev_ops *entry, int argsize)
 {
 	struct snd_seq_driver *sdrv;
 	int err;
@@ -315,7 +304,7 @@ int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
 	sdrv->driver.bus = &snd_seq_bus_type;
 	sdrv->driver.probe = snd_seq_drv_probe;
 	sdrv->driver.remove = snd_seq_drv_remove;
-	strlcpy(sdrv->id, id, sizeof(sdrv->id));
+	sdrv->id = id;
 	sdrv->argsize = argsize;
 	sdrv->ops = *entry;
 
@@ -343,7 +332,7 @@ static int find_drv(struct device_driver *drv, void *data)
 /*
  * unregister the specified driver
  */
-int snd_seq_device_unregister_driver(char *id)
+int snd_seq_device_unregister_driver(const char *id)
 {
 	struct snd_seq_driver *sdrv = (struct snd_seq_driver *)id;
 
-- 
2.3.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/6] ALSA: seq: Define driver object in each driver
  2015-02-16 16:55 [PATCH 0/6] Modernize sequecner device binding Takashi Iwai
                   ` (3 preceding siblings ...)
  2015-02-16 16:55 ` [PATCH 4/6] ALSA: seq: Clean up device and driver structs Takashi Iwai
@ 2015-02-16 16:55 ` Takashi Iwai
  2015-02-16 16:55 ` [PATCH 6/6] ALSA: seq: Drop snd_seq_autoload_lock() and _unlock() Takashi Iwai
  5 siblings, 0 replies; 7+ messages in thread
From: Takashi Iwai @ 2015-02-16 16:55 UTC (permalink / raw)
  To: alsa-devel

This patch moves the driver object initialization and allocation to
each driver's module init/exit code like other normal drivers.  The
snd_seq_driver struct is now published in seq_device.h, and each
driver is responsible to define it with proper driver attributes
(name, probe and remove) with snd_seq_driver specific attributes as id
and argsize fields.  The helper functions snd_seq_driver_register(),
snd_seq_driver_unregister() and module_snd_seq_driver() are used for
simplifying codes.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/seq_device.h         | 27 +++++++----
 sound/core/seq/oss/seq_oss.c       | 20 +++++---
 sound/core/seq/oss/seq_oss_synth.c |  6 ++-
 sound/core/seq/oss/seq_oss_synth.h |  4 +-
 sound/core/seq/seq_device.c        | 93 ++++----------------------------------
 sound/core/seq/seq_midi.c          | 28 ++++++++----
 sound/drivers/opl3/opl3_seq.c      | 34 ++++++--------
 sound/drivers/opl4/opl4_seq.c      | 33 ++++++--------
 sound/isa/sb/emu8000_synth.c       | 35 ++++++--------
 sound/pci/emu10k1/emu10k1_synth.c  | 35 ++++++--------
 10 files changed, 124 insertions(+), 191 deletions(-)

diff --git a/include/sound/seq_device.h b/include/sound/seq_device.h
index b13cd2930d32..ddc0d504cf39 100644
--- a/include/sound/seq_device.h
+++ b/include/sound/seq_device.h
@@ -41,8 +41,10 @@ struct snd_seq_device {
 #define to_seq_dev(_dev) \
 	container_of(_dev, struct snd_seq_device, dev)
 
+/* sequencer driver */
+
 /* driver operators
- * init_device:
+ * probe:
  *	Initialize the device with given parameters.
  *	Typically,
  *		1. call snd_hwdep_new
@@ -50,15 +52,19 @@ struct snd_seq_device {
  *		3. call snd_hwdep_register
  *		4. store the instance to dev->driver_data pointer.
  *		
- * free_device:
+ * remove:
  *	Release the private data.
  *	Typically, call snd_device_free(dev->card, dev->driver_data)
  */
-struct snd_seq_dev_ops {
-	int (*init_device)(struct snd_seq_device *dev);
-	int (*free_device)(struct snd_seq_device *dev);
+struct snd_seq_driver {
+	struct device_driver driver;
+	char *id;
+	int argsize;
 };
 
+#define to_seq_drv(_drv) \
+	container_of(_drv, struct snd_seq_driver, driver)
+
 /*
  * prototypes
  */
@@ -69,12 +75,17 @@ void snd_seq_device_load_drivers(void);
 #endif
 int snd_seq_device_new(struct snd_card *card, int device, const char *id,
 		       int argsize, struct snd_seq_device **result);
-int snd_seq_device_register_driver(const char *id,
-				   struct snd_seq_dev_ops *entry, int argsize);
-int snd_seq_device_unregister_driver(const char *id);
 
 #define SNDRV_SEQ_DEVICE_ARGPTR(dev) (void *)((char *)(dev) + sizeof(struct snd_seq_device))
 
+int __must_check __snd_seq_driver_register(struct snd_seq_driver *drv,
+					   struct module *mod);
+#define snd_seq_driver_register(drv) \
+	__snd_seq_driver_register(drv, THIS_MODULE)
+void snd_seq_driver_unregister(struct snd_seq_driver *drv);
+
+#define module_snd_seq_driver(drv) \
+	module_driver(drv, snd_seq_driver_register, snd_seq_driver_unregister)
 
 /*
  * id strings for generic devices
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index 16d42679e43f..ae1814aa767e 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -65,13 +65,19 @@ static unsigned int odev_poll(struct file *file, poll_table * wait);
  * module interface
  */
 
+static struct snd_seq_driver seq_oss_synth_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.probe = snd_seq_oss_synth_probe,
+		.remove = snd_seq_oss_synth_remove,
+	},
+	.id = SNDRV_SEQ_DEV_ID_OSS,
+	.argsize = sizeof(struct snd_seq_oss_reg),
+};
+
 static int __init alsa_seq_oss_init(void)
 {
 	int rc;
-	static struct snd_seq_dev_ops ops = {
-		snd_seq_oss_synth_register,
-		snd_seq_oss_synth_unregister,
-	};
 
 	snd_seq_autoload_lock();
 	if ((rc = register_device()) < 0)
@@ -86,8 +92,8 @@ static int __init alsa_seq_oss_init(void)
 		goto error;
 	}
 
-	if ((rc = snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OSS, &ops,
-						 sizeof(struct snd_seq_oss_reg))) < 0) {
+	rc = snd_seq_driver_register(&seq_oss_synth_driver);
+	if (rc < 0) {
 		snd_seq_oss_delete_client();
 		unregister_proc();
 		unregister_device();
@@ -104,7 +110,7 @@ static int __init alsa_seq_oss_init(void)
 
 static void __exit alsa_seq_oss_exit(void)
 {
-	snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OSS);
+	snd_seq_driver_unregister(&seq_oss_synth_driver);
 	snd_seq_oss_delete_client();
 	unregister_proc();
 	unregister_device();
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 701feb71b700..835edc80f918 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -98,8 +98,9 @@ snd_seq_oss_synth_init(void)
  * registration of the synth device
  */
 int
-snd_seq_oss_synth_register(struct snd_seq_device *dev)
+snd_seq_oss_synth_probe(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	int i;
 	struct seq_oss_synth *rec;
 	struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
@@ -149,8 +150,9 @@ snd_seq_oss_synth_register(struct snd_seq_device *dev)
 
 
 int
-snd_seq_oss_synth_unregister(struct snd_seq_device *dev)
+snd_seq_oss_synth_remove(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	int index;
 	struct seq_oss_synth *rec = dev->driver_data;
 	unsigned long flags;
diff --git a/sound/core/seq/oss/seq_oss_synth.h b/sound/core/seq/oss/seq_oss_synth.h
index dbdfcbb80eaa..74ac55f166b6 100644
--- a/sound/core/seq/oss/seq_oss_synth.h
+++ b/sound/core/seq/oss/seq_oss_synth.h
@@ -28,8 +28,8 @@
 #include <sound/seq_device.h>
 
 void snd_seq_oss_synth_init(void);
-int snd_seq_oss_synth_register(struct snd_seq_device *dev);
-int snd_seq_oss_synth_unregister(struct snd_seq_device *dev);
+int snd_seq_oss_synth_probe(struct device *dev);
+int snd_seq_oss_synth_remove(struct device *dev);
 void snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp);
 void snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp);
 void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp);
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 49daf6e3a387..48b20f009598 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -52,16 +52,6 @@ MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ALSA sequencer device management");
 MODULE_LICENSE("GPL");
 
-struct snd_seq_driver {
-	struct device_driver driver;
-	const char *id;
-	int argsize;
-	struct snd_seq_dev_ops ops;
-};
-
-#define to_seq_drv(_drv) \
-	container_of(_drv, struct snd_seq_driver, driver)
-
 /*
  * bus definition
  */
@@ -263,86 +253,23 @@ int snd_seq_device_new(struct snd_card *card, int device, const char *id,
 EXPORT_SYMBOL(snd_seq_device_new);
 
 /*
- * driver binding - just pass to each driver callback
+ * driver registration
  */
-static int snd_seq_drv_probe(struct device *dev)
+int __snd_seq_driver_register(struct snd_seq_driver *drv, struct module *mod)
 {
-	struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
-	struct snd_seq_device *sdev = to_seq_dev(dev);
-
-	return sdrv->ops.init_device(sdev);
-}
-
-static int snd_seq_drv_remove(struct device *dev)
-{
-	struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
-	struct snd_seq_device *sdev = to_seq_dev(dev);
-
-	return sdrv->ops.free_device(sdev);
-}
-
-/*
- * register device driver
- * id = driver id
- * entry = driver operators - duplicated to each instance
- */
-int snd_seq_device_register_driver(const char *id,
-				   struct snd_seq_dev_ops *entry, int argsize)
-{
-	struct snd_seq_driver *sdrv;
-	int err;
-
-	if (id == NULL || entry == NULL ||
-	    entry->init_device == NULL || entry->free_device == NULL)
+	if (WARN_ON(!drv->driver.name || !drv->id))
 		return -EINVAL;
-
-	sdrv = kzalloc(sizeof(*sdrv), GFP_KERNEL);
-	if (!sdrv)
-		return -ENOMEM;
-
-	sdrv->driver.name = id;
-	sdrv->driver.bus = &snd_seq_bus_type;
-	sdrv->driver.probe = snd_seq_drv_probe;
-	sdrv->driver.remove = snd_seq_drv_remove;
-	sdrv->id = id;
-	sdrv->argsize = argsize;
-	sdrv->ops = *entry;
-
-	err = driver_register(&sdrv->driver);
-	if (err < 0)
-		kfree(sdrv);
-	return err;
-}
-EXPORT_SYMBOL(snd_seq_device_register_driver);
-
-/* callback to find a specific driver; data is a pointer to the id string ptr.
- * when the id matches, store the driver pointer in return and break the loop.
- */
-static int find_drv(struct device_driver *drv, void *data)
-{
-	struct snd_seq_driver *sdrv = to_seq_drv(drv);
-	void **ptr = (void **)data;
-
-	if (strcmp(sdrv->id, *ptr))
-		return 0; /* id don't match, continue the loop */
-	*ptr = sdrv;
-	return 1; /* break the loop */
+	drv->driver.bus = &snd_seq_bus_type;
+	drv->driver.owner = mod;
+	return driver_register(&drv->driver);
 }
+EXPORT_SYMBOL_GPL(__snd_seq_driver_register);
 
-/*
- * unregister the specified driver
- */
-int snd_seq_device_unregister_driver(const char *id)
+void snd_seq_driver_unregister(struct snd_seq_driver *drv)
 {
-	struct snd_seq_driver *sdrv = (struct snd_seq_driver *)id;
-
-	if (!bus_for_each_drv(&snd_seq_bus_type, NULL, &sdrv, find_drv))
-		return -ENXIO;
-	driver_unregister(&sdrv->driver);
-	kfree(sdrv);
-	return 0;
+	driver_unregister(&drv->driver);
 }
-EXPORT_SYMBOL(snd_seq_device_unregister_driver);
+EXPORT_SYMBOL_GPL(snd_seq_driver_unregister);
 
 /*
  * module part
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 68fec776da26..79c73119cedc 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -273,8 +273,9 @@ static void snd_seq_midisynth_delete(struct seq_midisynth *msynth)
 
 /* register new midi synth port */
 static int
-snd_seq_midisynth_register_port(struct snd_seq_device *dev)
+snd_seq_midisynth_probe(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	struct seq_midisynth_client *client;
 	struct seq_midisynth *msynth, *ms;
 	struct snd_seq_port_info *port;
@@ -427,8 +428,9 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)
 
 /* release midi synth port */
 static int
-snd_seq_midisynth_unregister_port(struct snd_seq_device *dev)
+snd_seq_midisynth_remove(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	struct seq_midisynth_client *client;
 	struct seq_midisynth *msynth;
 	struct snd_card *card = dev->card;
@@ -457,23 +459,29 @@ snd_seq_midisynth_unregister_port(struct snd_seq_device *dev)
 	return 0;
 }
 
+static struct snd_seq_driver seq_midisynth_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.probe = snd_seq_midisynth_probe,
+		.remove = snd_seq_midisynth_remove,
+	},
+	.id = SNDRV_SEQ_DEV_ID_MIDISYNTH,
+	.argsize = 0,
+};
 
 static int __init alsa_seq_midi_init(void)
 {
-	static struct snd_seq_dev_ops ops = {
-		snd_seq_midisynth_register_port,
-		snd_seq_midisynth_unregister_port,
-	};
-	memset(&synths, 0, sizeof(synths));
+	int err;
+
 	snd_seq_autoload_lock();
-	snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH, &ops, 0);
+	err = snd_seq_driver_register(&seq_midisynth_driver);
 	snd_seq_autoload_unlock();
-	return 0;
+	return err;
 }
 
 static void __exit alsa_seq_midi_exit(void)
 {
-	snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH);
+	snd_seq_driver_unregister(&seq_midisynth_driver);
 }
 
 module_init(alsa_seq_midi_init)
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
index a9f618e06a22..fdae5d7f421f 100644
--- a/sound/drivers/opl3/opl3_seq.c
+++ b/sound/drivers/opl3/opl3_seq.c
@@ -216,8 +216,9 @@ static int snd_opl3_synth_create_port(struct snd_opl3 * opl3)
 
 /* ------------------------------ */
 
-static int snd_opl3_seq_new_device(struct snd_seq_device *dev)
+static int snd_opl3_seq_probe(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	struct snd_opl3 *opl3;
 	int client, err;
 	char name[32];
@@ -257,8 +258,9 @@ static int snd_opl3_seq_new_device(struct snd_seq_device *dev)
 	return 0;
 }
 
-static int snd_opl3_seq_delete_device(struct snd_seq_device *dev)
+static int snd_opl3_seq_remove(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	struct snd_opl3 *opl3;
 
 	opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
@@ -275,22 +277,14 @@ static int snd_opl3_seq_delete_device(struct snd_seq_device *dev)
 	return 0;
 }
 
-static int __init alsa_opl3_seq_init(void)
-{
-	static struct snd_seq_dev_ops ops =
-	{
-		snd_opl3_seq_new_device,
-		snd_opl3_seq_delete_device
-	};
-
-	return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL3, &ops,
-					      sizeof(struct snd_opl3 *));
-}
-
-static void __exit alsa_opl3_seq_exit(void)
-{
-	snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OPL3);
-}
+static struct snd_seq_driver opl3_seq_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.probe = snd_opl3_seq_probe,
+		.remove = snd_opl3_seq_remove,
+	},
+	.id = SNDRV_SEQ_DEV_ID_OPL3,
+	.argsize = sizeof(struct snd_opl3 *),
+};
 
-module_init(alsa_opl3_seq_init)
-module_exit(alsa_opl3_seq_exit)
+module_snd_seq_driver(opl3_seq_driver);
diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c
index 99197699c55a..03d6202f4829 100644
--- a/sound/drivers/opl4/opl4_seq.c
+++ b/sound/drivers/opl4/opl4_seq.c
@@ -124,8 +124,9 @@ static void snd_opl4_seq_free_port(void *private_data)
 	snd_midi_channel_free_set(opl4->chset);
 }
 
-static int snd_opl4_seq_new_device(struct snd_seq_device *dev)
+static int snd_opl4_seq_probe(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	struct snd_opl4 *opl4;
 	int client;
 	struct snd_seq_port_callback pcallbacks;
@@ -180,8 +181,9 @@ static int snd_opl4_seq_new_device(struct snd_seq_device *dev)
 	return 0;
 }
 
-static int snd_opl4_seq_delete_device(struct snd_seq_device *dev)
+static int snd_opl4_seq_remove(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	struct snd_opl4 *opl4;
 
 	opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
@@ -195,21 +197,14 @@ static int snd_opl4_seq_delete_device(struct snd_seq_device *dev)
 	return 0;
 }
 
-static int __init alsa_opl4_synth_init(void)
-{
-	static struct snd_seq_dev_ops ops = {
-		snd_opl4_seq_new_device,
-		snd_opl4_seq_delete_device
-	};
-
-	return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL4, &ops,
-					      sizeof(struct snd_opl4 *));
-}
-
-static void __exit alsa_opl4_synth_exit(void)
-{
-	snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OPL4);
-}
+static struct snd_seq_driver opl4_seq_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.probe = snd_opl4_seq_probe,
+		.remove = snd_opl4_seq_remove,
+	},
+	.id = SNDRV_SEQ_DEV_ID_OPL4,
+	.argsize = sizeof(struct snd_opl4 *),
+};
 
-module_init(alsa_opl4_synth_init)
-module_exit(alsa_opl4_synth_exit)
+module_snd_seq_driver(opl4_seq_driver);
diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c
index 72332dfada9a..4aa719cad331 100644
--- a/sound/isa/sb/emu8000_synth.c
+++ b/sound/isa/sb/emu8000_synth.c
@@ -34,8 +34,9 @@ MODULE_LICENSE("GPL");
 /*
  * create a new hardware dependent device for Emu8000
  */
-static int snd_emu8000_new_device(struct snd_seq_device *dev)
+static int snd_emu8000_probe(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	struct snd_emu8000 *hw;
 	struct snd_emux *emu;
 
@@ -93,8 +94,9 @@ static int snd_emu8000_new_device(struct snd_seq_device *dev)
 /*
  * free all resources
  */
-static int snd_emu8000_delete_device(struct snd_seq_device *dev)
+static int snd_emu8000_remove(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	struct snd_emu8000 *hw;
 
 	if (dev->driver_data == NULL)
@@ -114,21 +116,14 @@ static int snd_emu8000_delete_device(struct snd_seq_device *dev)
  *  INIT part
  */
 
-static int __init alsa_emu8000_init(void)
-{
-	
-	static struct snd_seq_dev_ops ops = {
-		snd_emu8000_new_device,
-		snd_emu8000_delete_device,
-	};
-	return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU8000, &ops,
-					      sizeof(struct snd_emu8000*));
-}
-
-static void __exit alsa_emu8000_exit(void)
-{
-	snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_EMU8000);
-}
-
-module_init(alsa_emu8000_init)
-module_exit(alsa_emu8000_exit)
+static struct snd_seq_driver emu8000_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.probe = snd_emu8000_probe,
+		.remove = snd_emu8000_remove,
+	},
+	.id = SNDRV_SEQ_DEV_ID_EMU8000,
+	.argsize = sizeof(struct snd_emu8000 *),
+};
+
+module_snd_seq_driver(emu8000_driver);
diff --git a/sound/pci/emu10k1/emu10k1_synth.c b/sound/pci/emu10k1/emu10k1_synth.c
index 4c41c903a840..5457d5613f6b 100644
--- a/sound/pci/emu10k1/emu10k1_synth.c
+++ b/sound/pci/emu10k1/emu10k1_synth.c
@@ -29,8 +29,9 @@ MODULE_LICENSE("GPL");
 /*
  * create a new hardware dependent device for Emu10k1
  */
-static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev)
+static int snd_emu10k1_synth_probe(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	struct snd_emux *emux;
 	struct snd_emu10k1 *hw;
 	struct snd_emu10k1_synth_arg *arg;
@@ -79,8 +80,9 @@ static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev)
 	return 0;
 }
 
-static int snd_emu10k1_synth_delete_device(struct snd_seq_device *dev)
+static int snd_emu10k1_synth_remove(struct device *_dev)
 {
+	struct snd_seq_device *dev = to_seq_dev(_dev);
 	struct snd_emux *emux;
 	struct snd_emu10k1 *hw;
 	unsigned long flags;
@@ -104,21 +106,14 @@ static int snd_emu10k1_synth_delete_device(struct snd_seq_device *dev)
  *  INIT part
  */
 
-static int __init alsa_emu10k1_synth_init(void)
-{
-	
-	static struct snd_seq_dev_ops ops = {
-		snd_emu10k1_synth_new_device,
-		snd_emu10k1_synth_delete_device,
-	};
-	return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, &ops,
-					      sizeof(struct snd_emu10k1_synth_arg));
-}
-
-static void __exit alsa_emu10k1_synth_exit(void)
-{
-	snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH);
-}
-
-module_init(alsa_emu10k1_synth_init)
-module_exit(alsa_emu10k1_synth_exit)
+static struct snd_seq_driver emu10k1_synth_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.probe = snd_emu10k1_synth_probe,
+		.remove = snd_emu10k1_synth_remove,
+	},
+	.id = SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH,
+	.argsize = sizeof(struct snd_emu10k1_synth_arg),
+};
+
+module_snd_seq_driver(emu10k1_synth_driver);
-- 
2.3.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 6/6] ALSA: seq: Drop snd_seq_autoload_lock() and _unlock()
  2015-02-16 16:55 [PATCH 0/6] Modernize sequecner device binding Takashi Iwai
                   ` (4 preceding siblings ...)
  2015-02-16 16:55 ` [PATCH 5/6] ALSA: seq: Define driver object in each driver Takashi Iwai
@ 2015-02-16 16:55 ` Takashi Iwai
  5 siblings, 0 replies; 7+ messages in thread
From: Takashi Iwai @ 2015-02-16 16:55 UTC (permalink / raw)
  To: alsa-devel

The autoload lock became already superfluous due to the recent rework
of autoload code.  Let's drop them now.  This allows us to simplify a
few codes nicely.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/seq_kernel.h   |  6 +-----
 sound/core/seq/oss/seq_oss.c |  2 --
 sound/core/seq/seq_device.c  | 19 +++++++------------
 sound/core/seq/seq_dummy.c   |  6 +-----
 sound/core/seq/seq_midi.c    | 18 +-----------------
 5 files changed, 10 insertions(+), 41 deletions(-)

diff --git a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h
index 18a2ac58b88f..feb58d455560 100644
--- a/include/sound/seq_kernel.h
+++ b/include/sound/seq_kernel.h
@@ -99,13 +99,9 @@ int snd_seq_event_port_attach(int client, struct snd_seq_port_callback *pcbp,
 int snd_seq_event_port_detach(int client, int port);
 
 #ifdef CONFIG_MODULES
-void snd_seq_autoload_lock(void);
-void snd_seq_autoload_unlock(void);
 void snd_seq_autoload_init(void);
-#define snd_seq_autoload_exit()	snd_seq_autoload_lock()
+void snd_seq_autoload_exit(void);
 #else
-#define snd_seq_autoload_lock()
-#define snd_seq_autoload_unlock()
 #define snd_seq_autoload_init()
 #define snd_seq_autoload_exit()
 #endif
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index ae1814aa767e..72873a46afeb 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -79,7 +79,6 @@ static int __init alsa_seq_oss_init(void)
 {
 	int rc;
 
-	snd_seq_autoload_lock();
 	if ((rc = register_device()) < 0)
 		goto error;
 	if ((rc = register_proc()) < 0) {
@@ -104,7 +103,6 @@ static int __init alsa_seq_oss_init(void)
 	snd_seq_oss_synth_init();
 
  error:
-	snd_seq_autoload_unlock();
 	return rc;
 }
 
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 48b20f009598..355b34269bd1 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -98,19 +98,8 @@ static void snd_seq_device_info(struct snd_info_entry *entry,
  */
 
 #ifdef CONFIG_MODULES
-/* avoid auto-loading during module_init() */
+/* flag to block auto-loading */
 static atomic_t snd_seq_in_init = ATOMIC_INIT(1); /* blocked as default */
-void snd_seq_autoload_lock(void)
-{
-	atomic_inc(&snd_seq_in_init);
-}
-EXPORT_SYMBOL(snd_seq_autoload_lock);
-
-void snd_seq_autoload_unlock(void)
-{
-	atomic_dec(&snd_seq_in_init);
-}
-EXPORT_SYMBOL(snd_seq_autoload_unlock);
 
 static int request_seq_drv(struct device *dev, void *data)
 {
@@ -147,6 +136,12 @@ void snd_seq_autoload_init(void)
 }
 EXPORT_SYMBOL(snd_seq_autoload_init);
 
+void snd_seq_autoload_exit(void)
+{
+	atomic_inc(&snd_seq_in_init);
+}
+EXPORT_SYMBOL(snd_seq_autoload_exit);
+
 void snd_seq_device_load_drivers(void)
 {
 	queue_autoload_drivers();
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index 5d905d90d504..d3a2ec4f0561 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -214,11 +214,7 @@ delete_client(void)
 
 static int __init alsa_seq_dummy_init(void)
 {
-	int err;
-	snd_seq_autoload_lock();
-	err = register_client();
-	snd_seq_autoload_unlock();
-	return err;
+	return register_client();
 }
 
 static void __exit alsa_seq_dummy_exit(void)
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 79c73119cedc..5dd0ee258359 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -469,20 +469,4 @@ static struct snd_seq_driver seq_midisynth_driver = {
 	.argsize = 0,
 };
 
-static int __init alsa_seq_midi_init(void)
-{
-	int err;
-
-	snd_seq_autoload_lock();
-	err = snd_seq_driver_register(&seq_midisynth_driver);
-	snd_seq_autoload_unlock();
-	return err;
-}
-
-static void __exit alsa_seq_midi_exit(void)
-{
-	snd_seq_driver_unregister(&seq_midisynth_driver);
-}
-
-module_init(alsa_seq_midi_init)
-module_exit(alsa_seq_midi_exit)
+module_snd_seq_driver(seq_midisynth_driver);
-- 
2.3.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-02-16 16:55 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-16 16:55 [PATCH 0/6] Modernize sequecner device binding Takashi Iwai
2015-02-16 16:55 ` [PATCH 1/6] ALSA: seq: Move EXPORT_SYMBOL() after each function Takashi Iwai
2015-02-16 16:55 ` [PATCH 2/6] ALSA: seq: Don't compile snd_seq_device_load_drivers() for built-in Takashi Iwai
2015-02-16 16:55 ` [PATCH 3/6] ALSA: seq: Rewrite sequencer device binding with standard bus Takashi Iwai
2015-02-16 16:55 ` [PATCH 4/6] ALSA: seq: Clean up device and driver structs Takashi Iwai
2015-02-16 16:55 ` [PATCH 5/6] ALSA: seq: Define driver object in each driver Takashi Iwai
2015-02-16 16:55 ` [PATCH 6/6] ALSA: seq: Drop snd_seq_autoload_lock() and _unlock() Takashi Iwai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.