Resent-Date: Wed, 21 Oct 1998 10:42:52 +0200 (MET DST)
To: linux-m68k@lists.linux-m68k.org
Subject: Less memory wastage in dmasound driver
X-Yow: I joined scientology at a garage sale!!
From: Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
Date: 21 Oct 1998 10:43:14 +0200
Resent-From: linux-m68k@phil.uni-sb.de

I have changed the dmasound driver to allocate its buffers only if it is
actually in use.  Otherwise the memory is just wasted most of the time.

Andreas.

----------------------------------------------------------------------
--- linux/drivers/sound/dmasound.c.~1~	Wed Aug 26 18:46:54 1998
+++ linux/drivers/sound/dmasound.c	Tue Oct 20 15:13:45 1998
@@ -685,9 +685,9 @@
 
 
 #ifdef CONFIG_ATARI
-static void *AtaAlloc(unsigned int size, int flags) __init;
-static void AtaFree(void *, unsigned int size) __init;
-static int AtaIrqInit(void) __init;
+static void *AtaAlloc(unsigned int size, int flags);
+static void AtaFree(void *, unsigned int size);
+static int AtaIrqInit(void);
 #ifdef MODULE
 static void AtaIrqCleanUp(void);
 #endif /* MODULE */
@@ -708,9 +708,9 @@
 #endif /* CONFIG_ATARI */
 
 #ifdef CONFIG_AMIGA
-static void *AmiAlloc(unsigned int size, int flags) __init;
-static void AmiFree(void *, unsigned int) __init;
-static int AmiIrqInit(void) __init;
+static void *AmiAlloc(unsigned int size, int flags);
+static void AmiFree(void *, unsigned int);
+static int AmiIrqInit(void);
 #ifdef MODULE
 static void AmiIrqCleanUp(void);
 #endif /* MODULE */
@@ -725,9 +725,9 @@
 #endif /* CONFIG_AMIGA */
 
 #ifdef CONFIG_PMAC
-static void *PMacAlloc(unsigned int size, int flags) __init;
-static void PMacFree(void *ptr, unsigned int size) __init;
-static int PMacIrqInit(void) __init;
+static void *PMacAlloc(unsigned int size, int flags);
+static void PMacFree(void *ptr, unsigned int size);
+static int PMacIrqInit(void);
 #ifdef MODULE
 static void PMacIrqCleanup(void);
 #endif /* MODULE */
@@ -2223,7 +2223,7 @@
 	atari_stram_free( obj );
 }
 
-static int AtaIrqInit(void)
+static __init int AtaIrqInit(void)
 {
 	/* Set up timer A. Timer A
 	   will receive a signal upon end of playing from the sound
@@ -2720,7 +2720,7 @@
 	amiga_chip_free (obj);
 }
 
-static int AmiIrqInit(void)
+static __init int AmiIrqInit(void)
 {
 	/* turn off DMA for audio channels */
 	custom.dmacon = AMI_AUDIO_OFF;
@@ -2988,7 +2988,7 @@
 	kfree(ptr);
 }
 
-static int PMacIrqInit(void)
+static __init int PMacIrqInit(void)
 {
 	if (request_irq(awacs_irq, pmac_awacs_intr, 0, "AWACS", 0)
 	    || request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "AWACS out", 0))
@@ -3813,7 +3813,7 @@
 };
 
 
-__initfunc(static void mixer_init(void))
+static __init void mixer_init(void)
 {
 #ifndef MODULE
 	int mixer_unit;
@@ -3861,6 +3861,42 @@
  */
 
 
+static int sq_allocate_buffers(void)
+{
+	int i;
+
+	if (sound_buffers)
+		return 0;
+	sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
+	if (!sound_buffers)
+		return -ENOMEM;
+	for (i = 0; i < numBufs; i++) {
+		sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
+		if (!sound_buffers[i]) {
+			while (i--)
+				sound.mach.dma_free (sound_buffers[i], bufSize << 10);
+			kfree (sound_buffers);
+			sound_buffers = 0;
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+
+static void sq_release_buffers(void)
+{
+	int i;
+
+	if (sound_buffers) {
+		for (i = 0; i < numBufs; i++)
+			sound.mach.dma_free (sound_buffers[i], bufSize << 10);
+		kfree (sound_buffers);
+		sound_buffers = 0;
+	}
+}
+
+
 static void sq_setup(int numBufs, int bufSize, char **buffers)
 {
 #ifdef CONFIG_PMAC
@@ -3876,7 +3912,6 @@
 	sq.front = sq.count = 0;
 	sq.rear = -1;
 	sq.write_queue = sq.open_queue = sq.sync_queue = 0;
-	sq.busy = 0;
 	sq.syncing = 0;
 
 	sq.playing = 0;
@@ -3996,9 +4031,12 @@
 		}
 		rc = 0;
 	}
+	sq.busy = 1;
+	rc = sq_allocate_buffers();
+	if (rc)
+		goto err_out_nobusy;
 	sq_setup(numBufs, bufSize << 10, sound_buffers);
 	sq.open_mode = file->f_flags;
-	sq.busy = 1;
 #ifdef CONFIG_ATARI
 	sq.ignore_int = 1;
 #endif /* CONFIG_ATARI */
@@ -4012,6 +4050,9 @@
 		sound_set_format(AFMT_MU_LAW);
 	}
 	return 0;
+err_out_nobusy:
+	sq.busy = 0;
+	WAKE_UP(sq.open_queue);
 err_out:
 	MOD_DEC_USE_COUNT;
 	return rc;
@@ -4064,8 +4105,10 @@
 	sound.soft = sound.dsp;
 	sound.hard = sound.dsp;
 	sound_silence();
-	if (rc == 0)
+	if (rc == 0) {
+		sq_release_buffers();
 		MOD_DEC_USE_COUNT;
+	}
 	return rc;
 }
 
@@ -4175,7 +4218,7 @@
 };
 
 
-__initfunc(static void sq_init(void))
+static __init void sq_init(void)
 {
 #ifndef MODULE
 	int sq_unit;
@@ -4370,7 +4413,7 @@
 };
 
 
-__initfunc(static void state_init(void))
+static __init void state_init(void)
 {
 #ifndef MODULE
 	int state_unit;
@@ -4393,10 +4436,9 @@
 /*** Config & Setup **********************************************************/
 
 
-__initfunc(void dmasound_init(void))
+void __init dmasound_init(void)
 {
 	int has_sound = 0;
-	int i;
 #ifdef CONFIG_PMAC
 	struct device_node *np;
 #endif
@@ -4499,25 +4541,7 @@
 		return;
 
 	/* Set up sound queue, /dev/audio and /dev/dsp. */
-	sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
-	if (!sound_buffers) {
-	out_of_memory:
-		printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
-		return;
-	}
-	for (i = 0; i < numBufs; i++) {
-		sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
-		if (!sound_buffers[i]) {
-			while (i--)
-				sound.mach.dma_free (sound_buffers[i], bufSize << 10);
-			kfree (sound_buffers);
-			sound_buffers = 0;
-			goto out_of_memory;
-		}
-	}
 
-	sq_setup(numBufs, bufSize << 10, sound_buffers);
-
 	/* Set default settings. */
 	sq_init();
 
@@ -4544,7 +4568,7 @@
 
 #define MAXARGS		8	/* Should be sufficient for now */
 
-__initfunc(void dmasound_setup(char *str, int *ints))
+void __init dmasound_setup(char *str, int *ints)
 {
 	/* check the bootstrap parameter for "dmasound=" */
 
@@ -4584,18 +4608,12 @@
 
 void cleanup_module(void)
 {
-	int i;
-
 	if (irq_installed) {
 		sound_silence();
 		sound.mach.irqcleanup();
 	}
 
-	if (sound_buffers) {
-		for (i = 0; i < numBufs; i++)
-			sound.mach.dma_free(sound_buffers[i], bufSize << 10);
-		kfree(sound_buffers);
-	}
+	sq_release_buffers();
 
 	if (mixer_unit >= 0)
 		unregister_sound_mixer(mixer_unit);

