All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: Driver mmap kernel memory
@ 2007-02-08  8:27 Micha Nelissen
  2007-02-08 11:45 ` Takashi Iwai
  0 siblings, 1 reply; 6+ messages in thread
From: Micha Nelissen @ 2007-02-08  8:27 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Alsa Development List

[-- Attachment #1: Type: text/plain, Size: 1111 bytes --]

Takashi Iwai wrote:
> At Wed, 7 Feb 2007 09:31:50 +0100,
> Micha Nelissen wrote:
>> 
>> The CPU architecture is armeb.
> 
> OK then you'd need dma_mmap_coherent() for mmapping the data.

Hmm? I'm not mmapping anything into user space, I suppose ALSA does this
?

In the driver, I access the buffer using the runtime->dma_area field.
 
>> I have more information now. The problem disappears if I do the
>> endian swap in the kernel driver. That means that I specify
>> SNDDRV_PCM_FMTBIT_S16_BE | SNDDRV_PCM_FMTBIT_S16_LE, instead of only
>> SNDDRV_PCM_FMTBIT_S16_BE, and I decide using the runtime->format
>> whether to swap or not.
> 
> Could you elaborate?  It sounds like a coincidence to me...

What do you want to know ? I've attached some code that shows the piece
in the kernel driver doing the checking of the buffer values
(alsa-buf-check.c). Also attached is an alsa test program that I used
(testtune.c).

Fields in my_device: p_start (= dma_area), p_cur (= current playback
pointer), p_end (= end of playback buffer); all point into dma_area.

Hope this helps,

Micha

[-- Attachment #2: alsa-buf-check.c --]
[-- Type: application/octet-stream, Size: 693 bytes --]

#if 1
				if (sample != my_device->exp_value) {
				    if (my_device->num_errors < 25) {
					int i;
					printk("error! expect=%d, got=%d, playpos=%d, wraps=%d, found @", 
					    my_device->exp_value, sample, 
					    (my_device->p_cur-my_device->playback_substream->runtime->dma_area)/sizeof(sample), 
					    my_device->num_wraps);
					for (i=0; i<32*1024; i++)
					    if (((s16*)my_device->playback_substream->runtime->dma_area)[i] == my_device->exp_value)
						printk(" %d", i);
					printk("\n");
				    } else if (my_device->num_errors == 25)
					printk("max number of sample errors reached\n");
				    my_device->num_errors++;
				}
				my_device->exp_value++;
#endif				


[-- Attachment #3: testtune.c --]
[-- Type: application/octet-stream, Size: 6997 bytes --]

#include <alsa/asoundlib.h>
#include <alsa/pcm.h>
#include <math.h>
#include <sys/time.h>

#define SWAP16(x) (((((unsigned short)x) & 0xff00) >> 8) | ((x & 0xff) << 8))

char* pcmdev = "default";

int main(int argc, char** argv)
{
        snd_pcm_hw_params_t *hwparams=NULL;
        snd_pcm_sw_params_t *swparams=NULL;
	snd_pcm_status_t* status;
	snd_pcm_t* pcm_handle;
        int dir;
        uint exact_uvalue;
        unsigned long exact_ulvalue;
	unsigned short* buf;
	struct timeval stv, ctv;
        int channels, sent, currtime, disptime, curravg, maxavg;
	int rate, format, stereo, rw, delay;
        int periods=2;
        int periodsize=500;
	int i, err, offset, numframes;

	rate = 8000;
	stereo = 0;
	rw = 1;

        if (snd_pcm_open(&pcm_handle, pcmdev, SND_PCM_STREAM_PLAYBACK,0) < 0) {
                printf("alsa_card_open_r: Error opening PCM device %s\n", pcmdev );
                return -1;
        }

        /* Allocate the snd_pcm_hw_params_t structure on the stack. */
        snd_pcm_hw_params_alloca(&hwparams);

        /* Init hwparams with full configuration space */
        if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
                printf("alsa_set_params: Cannot configure this PCM device.\n");
                return -1;
        }

        if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
                printf("alsa_set_params: Error setting access.\n");
                return -1;
        }
        /* Set sample format */
        format=SND_PCM_FORMAT_S16_LE;
        if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, format) < 0) {
                printf("alsa_set_params: Error setting format.\n");
                return -1;
        }
        /* Set number of channels */
        if (stereo) channels=2;
        else channels=1;
        if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels) < 0) {
                printf("alsa_set_params: Error setting channels.\n");
                return -1;
        }
        /* Set sample rate. If the exact rate is not supported */
        /* by the hardware, use nearest possible rate.         */
        exact_uvalue=rate;
        dir=0;
        if ((err=snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_uvalue, &dir))<0){
                printf("alsa_set_params: Error setting rate to %i:%s",rate,snd_strerror(err));
                return -1;
        }
        if (dir != 0) {
                printf("alsa_set_params: The rate %d Hz is not supported by your hardware.\n "
                "==> Using %d Hz instead.\n", rate, exact_uvalue);
        }
        /* choose greater period size when rate is high */
        periodsize=periodsize*(rate/8000);

        /* Set buffer size (in frames). The resulting latency is given by */
        /* latency = periodsize * periods / (rate * bytes_per_frame)     */
        /* set period size */
        exact_ulvalue=periodsize;
        dir=0;
        if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &exact_ulvalue, &dir) < 0) {
                printf("alsa_set_params: Error setting period size.\n");
                return -1;
        }
        if (dir != 0) {
                printf("alsa_set_params: The period size %d is not supported by your hardware.\n "
                "==> Using %d instead.\n", periodsize, (int)exact_ulvalue);
        }
        periodsize=exact_ulvalue;
        /* Set number of periods. Periods used to be called fragments. */
        exact_uvalue=periods;
        dir=0;
        if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &exact_uvalue, &dir) < 0) {
                printf("alsa_set_params: Error setting periods.\n");
                return -1;
        }
        if (dir != 0) {
                printf("alsa_set_params: The number of periods %d is not supported by your hardware.\n "
                "==> Using %d instead.\n", periods, exact_uvalue);
        }
        /* Apply HW parameter settings to */
        /* PCM device and prepare device  */
        if ((err=snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
                printf("alsa_set_params: Error setting HW params:%s",snd_strerror(err));
                return -1;
        }
        /*prepare sw params */
        if (rw){
                snd_pcm_sw_params_alloca(&swparams);
                snd_pcm_sw_params_current(pcm_handle, swparams);
                if ((err=snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams,periods*periodsize ))<0){
                        printf("alsa_set_params: Error setting start threshold:%s",snd_strerror(err));
                        return -1;
                }
                if ((err=snd_pcm_sw_params(pcm_handle, swparams))<0){
                        printf("alsa_set_params: Error setting SW params:%s",snd_strerror(err));
                        return -1;
                }
        }

	numframes = 64*1024;
	buf = malloc(numframes*sizeof(buf[0]));
	for (i = 0; i < numframes; i++){
		buf[i] = i;
		buf[i] = SWAP16(buf[i]);
	}

	gettimeofday(&stv, NULL);
	sent = 0;
	disptime = 0;
	maxavg = 0;
	offset = 0;
	snd_pcm_status_alloca(&status);
	do {
		err = snd_pcm_writei(pcm_handle, buf+offset, numframes-offset);
		//usleep(1000000);
		gettimeofday(&ctv, NULL);
		printf("T: %ld.%08ld bytes written=%3d ", 
		    ctv.tv_sec - stv.tv_sec - (ctv.tv_usec < stv.tv_usec ? 1 : 0), 
		    ctv.tv_usec - stv.tv_usec + (ctv.tv_usec < stv.tv_usec ? 1000000 : 0), err);
		if (err > 0) {
			sent += err;
			currtime = (ctv.tv_sec - stv.tv_sec);// * 1000 + (ctv.tv_usec - stv.tv_usec) / 1000;
			//if (ctv.tv_usec < stv.tv_usec)
			//	currtime += 1000;
			if (currtime > 0) {
				curravg = sent/currtime;
				if (curravg > maxavg)
					maxavg = curravg;
			}
			if (currtime > disptime) {
				//fprintf(stderr, "Playing rate: %5d samples/sec     \r", maxavg);
				disptime++;
				maxavg = 0;
			} 
		}
		if (err == -EAGAIN) {
			printf("overrun! waiting until buffer empty ");
			if (snd_pcm_wait(pcm_handle, 2000) == 0) {
			    printf("timed out! hw broken?\n");
			    break;
			}
		} else if (err == -EPIPE) {
			printf("underrun! ");
			snd_pcm_prepare(pcm_handle);
		} else if (err < 0) {
			printf("error %d: %s ", err, snd_strerror(err));
		} else if (err >= 0 && err < numframes) {
			offset += err;
		}
		if (snd_pcm_status(pcm_handle, status) < 0)
			printf("error getting status! ");
		delay = snd_pcm_status_get_delay(status);
		printf("delay=%4d ", delay);
		if (delay > 0 && delay < 640) {
			// speed up
			sent -= 320;
			printf("artificial speedup! ");
		}
		if (offset == numframes)
			offset = 0;
		ctv.tv_sec = stv.tv_sec + sent / rate - ctv.tv_sec;
		ctv.tv_usec = stv.tv_usec + (sent % rate) * 1000 / rate * 1000 - ctv.tv_usec;
		if (ctv.tv_usec < 0)
			ctv.tv_usec = 0;
		else if (ctv.tv_usec > 1000000) {
			ctv.tv_sec++;
			ctv.tv_usec -= 1000000;
		}
		printf("sleeping %ld.%06ld seconds\n", ctv.tv_sec, ctv.tv_usec);
		//select(0, NULL, NULL, NULL, &ctv);
	} while (1);

	return 0;
}

[-- Attachment #4: Type: text/plain, Size: 374 bytes --]

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

[-- Attachment #5: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/alsa-devel

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

* Re: Driver mmap kernel memory
  2007-02-08  8:27 Driver mmap kernel memory Micha Nelissen
@ 2007-02-08 11:45 ` Takashi Iwai
  0 siblings, 0 replies; 6+ messages in thread
From: Takashi Iwai @ 2007-02-08 11:45 UTC (permalink / raw)
  To: Micha Nelissen; +Cc: Alsa Development List

At Thu, 8 Feb 2007 09:27:51 +0100,
Micha Nelissen wrote:
> 
> Takashi Iwai wrote:
> > At Wed, 7 Feb 2007 09:31:50 +0100,
> > Micha Nelissen wrote:
> >> 
> >> The CPU architecture is armeb.
> > 
> > OK then you'd need dma_mmap_coherent() for mmapping the data.
> 
> Hmm? I'm not mmapping anything into user space, I suppose ALSA does this
> ?
> In the driver, I access the buffer using the runtime->dma_area field.

On ARM, you cannot mmap and access concurrently with the normal
allocated pages because of coherency.  Instead, you have to allocate
pages via dma_alloc_coherent() and mmap them via dma_mmap_coherent() 
(invoked from mmap PCM ops).  Take a look at alsa-kernel/arm/devdma.*
for example.


Takashi

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

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

* Re: Driver mmap kernel memory
  2007-02-07  8:31 Micha Nelissen
@ 2007-02-07 17:32 ` Takashi Iwai
  0 siblings, 0 replies; 6+ messages in thread
From: Takashi Iwai @ 2007-02-07 17:32 UTC (permalink / raw)
  To: Micha Nelissen; +Cc: Alsa Development List

At Wed, 7 Feb 2007 09:31:50 +0100,
Micha Nelissen wrote:
> 
> Takashi Iwai wrote:
> >> Has anyone seen this behaviour before, and how to fix it ? Or, any
> >> hints how to reproduce the alsa mmap behaviour in a smaller software
> >> stack ? 
> > 
> > Which architecture is it?  It might be a memory coherency problem.
> > Does the normal snd_pcm_writei() work as expected?
> 
> The CPU architecture is armeb.

OK then you'd need dma_mmap_coherent() for mmapping the data.

> I have more information now. The problem disappears if I do the endian
> swap in the kernel driver. That means that I specify
> SNDDRV_PCM_FMTBIT_S16_BE | SNDDRV_PCM_FMTBIT_S16_LE, instead of only
> SNDDRV_PCM_FMTBIT_S16_BE, and I decide using the runtime->format whether
> to swap or not.

Could you elaborate?  It sounds like a coincidence to me...


Takashi

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

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

* Re: Driver mmap kernel memory
@ 2007-02-07  8:31 Micha Nelissen
  2007-02-07 17:32 ` Takashi Iwai
  0 siblings, 1 reply; 6+ messages in thread
From: Micha Nelissen @ 2007-02-07  8:31 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Alsa Development List

Takashi Iwai wrote:
>> Has anyone seen this behaviour before, and how to fix it ? Or, any
>> hints how to reproduce the alsa mmap behaviour in a smaller software
>> stack ? 
> 
> Which architecture is it?  It might be a memory coherency problem.
> Does the normal snd_pcm_writei() work as expected?

The CPU architecture is armeb.

I have more information now. The problem disappears if I do the endian
swap in the kernel driver. That means that I specify
SNDDRV_PCM_FMTBIT_S16_BE | SNDDRV_PCM_FMTBIT_S16_LE, instead of only
SNDDRV_PCM_FMTBIT_S16_BE, and I decide using the runtime->format whether
to swap or not.

Hope this helps,

Micha

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

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

* Re: Driver mmap kernel memory
  2007-02-05  9:51 Micha Nelissen
@ 2007-02-06 11:55 ` Takashi Iwai
  0 siblings, 0 replies; 6+ messages in thread
From: Takashi Iwai @ 2007-02-06 11:55 UTC (permalink / raw)
  To: Micha Nelissen; +Cc: Alsa Development List

At Mon, 5 Feb 2007 10:51:16 +0100,
Micha Nelissen wrote:
> 
> Hi,
> 
> I have a 16 bit alsa driver that allocates kernel memory, uses
> SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), and
> specifies MMAP | MMAP_VALID et.al. The idea is that user space writes
> into this mmapped memory, and from the kernel I send the data to the
> sound device. 
> 
> For testing, I've modified this driver to check the values in the buffer
> to be increasing 1, 2, 3, etc.. and written a test program that opens
> alsa and writes these values in a buffer using snd_pcm_writei.
> 
> I observe that some samples are from the previous iteration in the
> buffer, but the surrounding samples are ok. For example with 2000 frames
> buffer size, period size 500, then in the third iteration I read 2000,
> 4001, 4002, ... instead of 4000, 4001, 4002, ...
> 
> Memory test ran ok, so that's not the problem, and also linux is running
> stable.
> 
> The rate is 8 khz, and I'm not getting alsa underruns.
> 
> Has anyone seen this behaviour before, and how to fix it ? Or, any hints
> how to reproduce the alsa mmap behaviour in a smaller software stack ?

Which architecture is it?  It might be a memory coherency problem.
Does the normal snd_pcm_writei() work as expected?


Takashi

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

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

* Driver mmap kernel memory
@ 2007-02-05  9:51 Micha Nelissen
  2007-02-06 11:55 ` Takashi Iwai
  0 siblings, 1 reply; 6+ messages in thread
From: Micha Nelissen @ 2007-02-05  9:51 UTC (permalink / raw)
  To: Alsa Development List

Hi,

I have a 16 bit alsa driver that allocates kernel memory, uses
SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), and
specifies MMAP | MMAP_VALID et.al. The idea is that user space writes
into this mmapped memory, and from the kernel I send the data to the
sound device. 

For testing, I've modified this driver to check the values in the buffer
to be increasing 1, 2, 3, etc.. and written a test program that opens
alsa and writes these values in a buffer using snd_pcm_writei.

I observe that some samples are from the previous iteration in the
buffer, but the surrounding samples are ok. For example with 2000 frames
buffer size, period size 500, then in the third iteration I read 2000,
4001, 4002, ... instead of 4000, 4001, 4002, ...

Memory test ran ok, so that's not the problem, and also linux is running
stable.

The rate is 8 khz, and I'm not getting alsa underruns.

Has anyone seen this behaviour before, and how to fix it ? Or, any hints
how to reproduce the alsa mmap behaviour in a smaller software stack ?

Thanks in advance,

Micha

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

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

end of thread, other threads:[~2007-02-08 11:45 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-08  8:27 Driver mmap kernel memory Micha Nelissen
2007-02-08 11:45 ` Takashi Iwai
  -- strict thread matches above, loose matches on Subject: below --
2007-02-07  8:31 Micha Nelissen
2007-02-07 17:32 ` Takashi Iwai
2007-02-05  9:51 Micha Nelissen
2007-02-06 11:55 ` 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.