[ALSA] dynamic minors (6/6): increase maximum number of sound cards

Modules: ALSA Core,Memalloc module,ALSA sequencer

With dynamic minor numbers, we can increase the number of sound cards.

This requires that the sequencer client numbers of some kernel drivers
are allocated dynamically, too.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
diff --git a/sound/core/init.c b/sound/core/init.c
index 728bb2c..58e17d3 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -338,7 +338,7 @@
 
 static void choose_default_id(struct snd_card *card)
 {
-	int i, len, idx_flag = 0, loops = 8;
+	int i, len, idx_flag = 0, loops = SNDRV_CARDS;
 	char *id, *spos;
 	
 	id = spos = card->shortname;	
@@ -380,9 +380,12 @@
 
 	      __change:
 		len = strlen(id);
-		if (idx_flag)
-			id[len-1]++;
-		else if ((size_t)len <= sizeof(card->id) - 3) {
+		if (idx_flag) {
+			if (id[len-1] != '9')
+				id[len-1]++;
+			else
+				id[len-1] = 'A';
+		} else if ((size_t)len <= sizeof(card->id) - 3) {
 			strcat(id, "_1");
 			idx_flag++;
 		} else {
@@ -461,12 +464,12 @@
 		read_lock(&snd_card_rwlock);
 		if ((card = snd_cards[idx]) != NULL) {
 			count++;
-			snd_iprintf(buffer, "%i [%-15s]: %s - %s\n",
+			snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n",
 					idx,
 					card->id,
 					card->driver,
 					card->shortname);
-			snd_iprintf(buffer, "                     %s\n",
+			snd_iprintf(buffer, "                      %s\n",
 					card->longname);
 		}
 		read_unlock(&snd_card_rwlock);
@@ -508,7 +511,8 @@
 	for (idx = 0; idx < SNDRV_CARDS; idx++) {
 		read_lock(&snd_card_rwlock);
 		if ((card = snd_cards[idx]) != NULL)
-			snd_iprintf(buffer, "%i %s\n", idx, card->module->name);
+			snd_iprintf(buffer, "%2i %s\n",
+				    idx, card->module->name);
 		read_unlock(&snd_card_rwlock);
 	}
 }
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index e4b8959..19b3dcb 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -43,10 +43,6 @@
 MODULE_LICENSE("GPL");
 
 
-#ifndef SNDRV_CARDS
-#define SNDRV_CARDS	8
-#endif
-
 /*
  */
 
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 95bd5ae..2a9c6b3 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -47,6 +47,10 @@
  * 
  */
 
+/* range for dynamically allocated client numbers of kernel drivers */
+#define SNDRV_SEQ_DYNAMIC_CLIENT_BEGIN	16
+#define SNDRV_SEQ_DYNAMIC_CLIENT_END	48
+
 #define SNDRV_SEQ_LFLG_INPUT	0x0001
 #define SNDRV_SEQ_LFLG_OUTPUT	0x0002
 #define SNDRV_SEQ_LFLG_OPEN	(SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT)
@@ -203,7 +207,8 @@
 }
 
 
-static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
+static struct snd_seq_client *seq_create_client1(int client_index, int poolsize,
+						 int kernel_client)
 {
 	unsigned long flags;
 	int c;
@@ -227,7 +232,15 @@
 	/* find free slot in the client table */
 	spin_lock_irqsave(&clients_lock, flags);
 	if (client_index < 0) {
-		for (c = 128; c < SNDRV_SEQ_MAX_CLIENTS; c++) {
+		int cmin, cmax;
+		if (kernel_client) {
+			cmin = SNDRV_SEQ_DYNAMIC_CLIENT_BEGIN;
+			cmax = SNDRV_SEQ_DYNAMIC_CLIENT_END;
+		} else {
+			cmin = 128;
+			cmax = SNDRV_SEQ_MAX_CLIENTS;
+		}
+		for (c = cmin; c < cmax; c++) {
 			if (clienttab[c] || clienttablock[c])
 				continue;
 			clienttab[client->number = c] = client;
@@ -306,7 +319,7 @@
 
 	if (down_interruptible(&register_mutex))
 		return -ERESTARTSYS;
-	client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS);
+	client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS, 0);
 	if (client == NULL) {
 		up(&register_mutex);
 		return -ENOMEM;	/* failure code */
@@ -2212,13 +2225,19 @@
 		return -EINVAL;
 	if (card == NULL && client_index > 63)
 		return -EINVAL;
-	if (card)
-		client_index += 64 + (card->number << 2);
 
 	if (down_interruptible(&register_mutex))
 		return -ERESTARTSYS;
+
+	if (card) {
+		if (card->number < 16)
+			client_index += 64 + (card->number << 2);
+		else
+			client_index = -1;
+	}
+
 	/* empty write queue as default */
-	client = seq_create_client1(client_index, 0);
+	client = seq_create_client1(client_index, 0, 1);
 	if (client == NULL) {
 		up(&register_mutex);
 		return -EBUSY;	/* failure code */
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 5e22283..5febd05 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -358,15 +358,15 @@
 			continue;
 		if (mptr->card >= 0) {
 			if (mptr->device >= 0)
-				snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n",
+				snd_iprintf(buffer, "%3i: [%2i-%2i]: %s\n",
 					    minor, mptr->card, mptr->device,
 					    snd_device_type_name(mptr->type));
 			else
-				snd_iprintf(buffer, "%3i: [%i]   : %s\n",
+				snd_iprintf(buffer, "%3i: [%2i]   : %s\n",
 					    minor, mptr->card,
 					    snd_device_type_name(mptr->type));
 		} else
-			snd_iprintf(buffer, "%3i:       : %s\n", minor,
+			snd_iprintf(buffer, "%3i:        : %s\n", minor,
 				    snd_device_type_name(mptr->type));
 	}
 	up(&sound_mutex);
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index b9e89ca..3ae1c0d 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -105,6 +105,8 @@
 	int register1 = -1, register2 = -1;
 	struct device *carddev = NULL;
 
+	if (card && card->number >= 8)
+		return 0; /* ignore silently */
 	if (minor < 0)
 		return minor;
 	preg = kmalloc(sizeof(struct snd_minor), GFP_KERNEL);
@@ -162,6 +164,8 @@
 	int track2 = -1;
 	struct snd_minor *mptr;
 
+	if (card && card->number >= 8)
+		return 0;
 	if (minor < 0)
 		return minor;
 	down(&sound_oss_mutex);