Skip to contentSkip to conversation

Sound problems with snd_hda on x86_64

PATCH Denis Vlasenko 2 participants 7 messages Jul 28, 2006 Sound

lore
Share & tools
lore
#0 lore raw

Hello,

I just built my very first 64-bit kernel for Athlon64 and it boots and works. Thank you Andi for all your work on x86_64.

The only trouble so far that KDE's artsd and mplayer have trouble playing sound.

Strace of artsd on 32 bits:

1762  open("/dev/snd/pcmC0D0p", O_RDWR|O_NONBLOCK) = 9
1762  close(8)                          = 0
1762  ioctl(9, AGPIOC_ACQUIRE or APM_IOC_STANDBY <unfinished ...>
1762  <... ioctl resumed> , 0x77c58280) = 0
1762  fcntl64(9, F_GETFL)               = 0x802 (flags O_RDWR|O_NONBLOCK)
1762  ioctl(9, AGPIOC_INFO, 0x77c5827c) = 0
1762  ioctl(9, AGPIOC_RELEASE or APM_IOC_SUSPEND, 0x77c58278) = 0
1762  mmap2(NULL, 4096, PROT_READ, MAP_SHARED, 9, 0x80000) = 0x6f85c000
1762  mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, 9, 0x81000) = 0x6f85b000

On 64 bits:

2203  open("/dev/snd/pcmC0D0p", O_RDWR|O_NONBLOCK) = 9
2203  close(8)                          = 0
2203  ioctl(9, AGPIOC_ACQUIRE or APM_IOC_STANDBY <unfinished ...>
2203  <... ioctl resumed> , 0xffa9eda0) = 0
2203  fcntl64(9, F_GETFL)               = 0x802 (flags O_RDWR|O_NONBLOCK)
2203  ioctl(9, AGPIOC_INFO, 0xffa9ed9c) = 0
2203  ioctl(9, AGPIOC_RELEASE or APM_IOC_SUSPEND, 0xffa9ed98) = 0
2203  mmap2(NULL, 4096, PROT_READ, MAP_SHARED, 9, 0x80000) = -1 ENXIO (No such device or address)
2203  write(2, "ALSA lib ../../../src/pcm/pcm_hw"..., 64) = 64
2203  write(2, "status mmap failed", 18) = 18
2203  write(2, ": No such device or address", 27) = 27
2203  write(2, "\n", 1)                 = 1

-ENXIO seems to be the thing which gives trouble.
I think it comes from here:

sound/core/pcm_native.c +4 -4
@@ -34,7 +34,7 @@
 #include <sound/timer.h>
 #include <sound/minors.h>
 #include <asm/io.h>
-
+#define ret_ENXIO printk("return -ENXIO in %s:%s line %d\n", __FILE__, __FUNCTION__, __LINE__)
 /*
  *  Compatibility
  */
@@ -3220,17 +3220,17 @@ static int snd_pcm_mmap(struct file *fil
 	
 	pcm_file = file->private_data;
 	substream = pcm_file->substream;
-	snd_assert(substream != NULL, return -ENXIO);
+	snd_assert(substream != NULL, ret_ENXIO; return -ENXIO);
 
 	offset = area->vm_pgoff << PAGE_SHIFT;
 	switch (offset) {
 	case SNDRV_PCM_MMAP_OFFSET_STATUS:
 		if (substream->no_mmap_ctrl)
-			return -ENXIO;
+			{ret_ENXIO; return -ENXIO;} // vda: returns here
 		return snd_pcm_mmap_status(substream, file, area);
 	case SNDRV_PCM_MMAP_OFFSET_CONTROL:
 		if (substream->no_mmap_ctrl)
-			return -ENXIO;
+			{ret_ENXIO; return -ENXIO;}
 		return snd_pcm_mmap_control(substream, file, area);
 	default:
 		return snd_pcm_mmap_data(substream, file, area);

Which is, in turn, is caused by this code:

sound/core/pcm_compat.c +2 -0
@@ -478,6 +478,8 @@ static long snd_pcm_ioctl_compat(struct 
 	 * mmap of PCM status/control records because of the size
 	 * incompatibility.
 	 */
+printk("substream->no_mmap_ctrl = 1 in %s:%s line %d\n", __FILE__, __FUNCTION__, __LINE__);
+dump_stack();
 	substream->no_mmap_ctrl = 1;
 
 	switch (cmd) {

It's puzzling. Even a 486 processor, can do 64-bit operations (using cmpxchg8) on memory-mapped areas, why does code disallows mmap for 64-bit CPUs but allows for 32-bit ones?

I suspect that not all sound devices are mmap-able, and I think artsd is not THAT buggy to try mmap on those and die, so why does it not detect that snd_hda is not mmap-able on x86_64 kernel?
Is it artsd problem or snd_hda problem?

I did not investigate mplayer problem this deep. Visually, mplayer plays movies faster than real time, unless given an option "-ao null".

The chip is integrated Realtek ALC883 on MSI K9N Neo mobo
(http://www.pixmania.co.uk/uk/uk/270290/art/msi/k9n-neo-f-socket-am2-amd.html).

# lsmod
Module                  Size  Used by
snd_pcm_oss            25824  0
snd_mixer_oss          18368  1 snd_pcm_oss
snd_hda_intel          19484  0
snd_hda_codec         164608  1 snd_hda_intel
snd_pcm                88588  3 snd_pcm_oss,snd_hda_intel,snd_hda_codec
snd_timer              26184  1 snd_pcm
snd                    63336  6 snd_pcm_oss,snd_mixer_oss,snd_hda_intel,snd_hda_codec,snd_pcm,snd_timer
soundcore              11616  1 snd
snd_page_alloc         10640  2 snd_hda_intel,snd_pcm
...

printks from instrumentation shown above:

22:37:45.8 hda_codec: Unknown model for ALC882, trying auto-probe from BIOS... 22:44:35.0 substream->no_mmap_ctrl = 1 in sound/core/pcm_compat.c:snd_pcm_ioctl_compat line 481 22:44:35.0
22:44:35.0 Call Trace: <ffffffff880ba51b>{:snd_pcm:snd_pcm_ioctl_compat+91}

22:44:35.0        <ffffffff8809bc84>{:snd:snd_card_file_remove+199} <ffffffff8026391c>{kobject_put+25}
22:44:35.0        <ffffffff801884da>{mntput_no_expire+27} <ffffffff8016d750>{__fput+447}
22:44:35.0        <ffffffff801986ca>{compat_sys_ioctl+176} <ffffffff8011b12e>{ia32_sysret+0}

22:44:35.0 substream->no_mmap_ctrl = 1 in sound/core/pcm_compat.c:snd_pcm_ioctl_compat line 481 22:44:35.0
22:44:35.0 Call Trace: <ffffffff880ba51b>{:snd_pcm:snd_pcm_ioctl_compat+91}
22:44:35.0 <ffffffff8809bc84>{:snd:snd_card_file_remove+199} <ffffffff8017ed34>{sys_fcntl+759}
22:44:35.0 <ffffffff801986ca>{compat_sys_ioctl+176} <ffffffff8011b12e>{ia32_sysret+0}
22:44:35.0 substream->no_mmap_ctrl = 1 in sound/core/pcm_compat.c:snd_pcm_ioctl_compat line 481 22:44:35.0
22:44:35.0 Call Trace: <ffffffff880ba51b>{:snd_pcm:snd_pcm_ioctl_compat+91}
22:44:35.0 <ffffffff8809bc84>{:snd:snd_card_file_remove+199} <ffffffff8017ed34>{sys_fcntl+759}
22:44:35.0 <ffffffff801986ca>{compat_sys_ioctl+176} <ffffffff8011b12e>{ia32_sysret+0}
22:44:35.0 return -ENXIO in sound/core/pcm_native.c:snd_pcm_mmap line 3229

Takashi, do you want more info and/or digging into mplayer problem?
--
vda

#1 lore raw

At Fri, 28 Jul 2006 12:16:25 +0200,

Quoted 87 lines · Denis Vlasenko

Hello,

I just built my very first 64-bit kernel for Athlon64 and it boots and works. Thank you Andi for all your work on x86_64.

The only trouble so far that KDE's artsd and mplayer have trouble playing sound.

Strace of artsd on 32 bits:

1762  open("/dev/snd/pcmC0D0p", O_RDWR|O_NONBLOCK) = 9
1762  close(8)                          = 0
1762  ioctl(9, AGPIOC_ACQUIRE or APM_IOC_STANDBY <unfinished ...>
1762  <... ioctl resumed> , 0x77c58280) = 0
1762  fcntl64(9, F_GETFL)               = 0x802 (flags O_RDWR|O_NONBLOCK)
1762  ioctl(9, AGPIOC_INFO, 0x77c5827c) = 0
1762  ioctl(9, AGPIOC_RELEASE or APM_IOC_SUSPEND, 0x77c58278) = 0
1762  mmap2(NULL, 4096, PROT_READ, MAP_SHARED, 9, 0x80000) = 0x6f85c000
1762  mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, 9, 0x81000) = 0x6f85b000

On 64 bits:

2203  open("/dev/snd/pcmC0D0p", O_RDWR|O_NONBLOCK) = 9
2203  close(8)                          = 0
2203  ioctl(9, AGPIOC_ACQUIRE or APM_IOC_STANDBY <unfinished ...>
2203  <... ioctl resumed> , 0xffa9eda0) = 0
2203  fcntl64(9, F_GETFL)               = 0x802 (flags O_RDWR|O_NONBLOCK)
2203  ioctl(9, AGPIOC_INFO, 0xffa9ed9c) = 0
2203  ioctl(9, AGPIOC_RELEASE or APM_IOC_SUSPEND, 0xffa9ed98) = 0
2203  mmap2(NULL, 4096, PROT_READ, MAP_SHARED, 9, 0x80000) = -1 ENXIO (No such device or address)
2203  write(2, "ALSA lib ../../../src/pcm/pcm_hw"..., 64) = 64
2203  write(2, "status mmap failed", 18) = 18
2203  write(2, ": No such device or address", 27) = 27
2203  write(2, "\n", 1)                 = 1

-ENXIO seems to be the thing which gives trouble.
I think it comes from here:

sound/core/pcm_native.c +4 -4
@@ -34,7 +34,7 @@
 #include <sound/timer.h>
 #include <sound/minors.h>
 #include <asm/io.h>
-
+#define ret_ENXIO printk("return -ENXIO in %s:%s line %d\n", __FILE__, __FUNCTION__, __LINE__)
 /*
  *  Compatibility
  */
@@ -3220,17 +3220,17 @@ static int snd_pcm_mmap(struct file *fil
 
 	pcm_file = file->private_data;
 	substream = pcm_file->substream;
-	snd_assert(substream != NULL, return -ENXIO);
+	snd_assert(substream != NULL, ret_ENXIO; return -ENXIO);
 
 	offset = area->vm_pgoff << PAGE_SHIFT;
 	switch (offset) {
 	case SNDRV_PCM_MMAP_OFFSET_STATUS:
 		if (substream->no_mmap_ctrl)
-			return -ENXIO;
+			{ret_ENXIO; return -ENXIO;} // vda: returns here
 		return snd_pcm_mmap_status(substream, file, area);
 	case SNDRV_PCM_MMAP_OFFSET_CONTROL:
 		if (substream->no_mmap_ctrl)
-			return -ENXIO;
+			{ret_ENXIO; return -ENXIO;}
 		return snd_pcm_mmap_control(substream, file, area);
 	default:
 		return snd_pcm_mmap_data(substream, file, area);

Which is, in turn, is caused by this code:

sound/core/pcm_compat.c +2 -0
@@ -478,6 +478,8 @@ static long snd_pcm_ioctl_compat(struct 
 	 * mmap of PCM status/control records because of the size
 	 * incompatibility.
 	 */
+printk("substream->no_mmap_ctrl = 1 in %s:%s line %d\n", __FILE__, __FUNCTION__, __LINE__);
+dump_stack();
 	substream->no_mmap_ctrl = 1;
 
 	switch (cmd) {
Quoted 3 lines

It's puzzling. Even a 486 processor, can do 64-bit operations (using cmpxchg8) on memory-mapped areas, why does code disallows mmap for 64-bit CPUs but allows for 32-bit ones?

On the contrary, the driver disallows mmap for 32bit task on 64bit architecture. This is because the size of the mapped record is different between 32bit and 64bit architectures, so it cannot be shared.

BTW, with the recent version of alsa-lib, you no longer need artsd unless you want a network transparent. Disable it on kde control center.

Takashi

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

#2 lore raw
Quoted 14 lines · Takashi Iwai
Quoted 14 lines

Which is, in turn, is caused by this code:

sound/core/pcm_compat.c +2 -0
@@ -478,6 +478,8 @@ static long snd_pcm_ioctl_compat(struct 
 	 * mmap of PCM status/control records because of the size
 	 * incompatibility.
 	 */
+printk("substream->no_mmap_ctrl = 1 in %s:%s line %d\n", __FILE__, __FUNCTION__, __LINE__);
+dump_stack();
 	substream->no_mmap_ctrl = 1;
 
 	switch (cmd) {
Quoted 8 lines
Quoted 3 lines

It's puzzling. Even a 486 processor, can do 64-bit operations (using cmpxchg8) on memory-mapped areas, why does code disallows mmap for 64-bit CPUs but allows for 32-bit ones?

On the contrary, the driver disallows mmap for 32bit task on 64bit architecture. This is because the size of the mapped record is different between 32bit and 64bit architectures, so it cannot be shared.

Why artsd attempts mmap at all then? Why it thinks that /dev/snd/pcmC0D0p is mmap-able when it is not?

Quoted 3 lines

BTW, with the recent version of alsa-lib, you no longer need artsd unless you want a network transparent. Disable it on kde control center.

This is good.
--
vda

#3 lore raw

At Fri, 28 Jul 2006 12:47:11 +0200,

Quoted 25 lines · Denis Vlasenko
Quoted 14 lines · Takashi Iwai
Quoted 14 lines

Which is, in turn, is caused by this code:

sound/core/pcm_compat.c +2 -0
@@ -478,6 +478,8 @@ static long snd_pcm_ioctl_compat(struct 
 	 * mmap of PCM status/control records because of the size
 	 * incompatibility.
 	 */
+printk("substream->no_mmap_ctrl = 1 in %s:%s line %d\n", __FILE__, __FUNCTION__, __LINE__);
+dump_stack();
 	substream->no_mmap_ctrl = 1;
 
 	switch (cmd) {
Quoted 8 lines
Quoted 3 lines

It's puzzling. Even a 486 processor, can do 64-bit operations (using cmpxchg8) on memory-mapped areas, why does code disallows mmap for 64-bit CPUs but allows for 32-bit ones?

On the contrary, the driver disallows mmap for 32bit task on 64bit architecture. This is because the size of the mapped record is different between 32bit and 64bit architectures, so it cannot be shared.

Quoted 1 line

Why artsd attempts mmap at all then?

The app must try mmap. From the application side, you can't know whether you're 32bit-emulation mode or it's really on 32bit architecture. And, mmap is usually done automatically via alsa-lib plugin for optimization or soft-mixing purpose.

Quoted 2 lines

Why it thinks that
/dev/snd/pcmC0D0p is mmap-able when it is not?

Dunno. pcm_compat.c is only for 32bit context on 64bit architecture. The 64bit program will never go there.

Takashi

#4 lore raw
Quoted 6 lines · Takashi Iwai
Quoted 1 line

Why artsd attempts mmap at all then?

The app must try mmap. From the application side, you can't know whether you're 32bit-emulation mode or it's really on 32bit architecture. And, mmap is usually done automatically via alsa-lib plugin for optimization or soft-mixing purpose.

Well, alsa seems to have info about mmap-ability here:

static struct snd_pcm_hardware azx_pcm_hw = {
        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                 SNDRV_PCM_INFO_MMAP_VALID |
                                 SNDRV_PCM_INFO_PAUSE /*|*/
                                 /*SNDRV_PCM_INFO_RESUME*/),

...
};

but it is not split into "can mmap data", "can mmap control/status". When this one triggers:

snd_pcm_ioctl_compat()
...
/*
* When PCM is used on 32bit mode, we need to disable
* mmap of PCM status/control records because of the size
* incompatibility.
*/
substream->no_mmap_ctrl = 1;

It does not clear any such flags. If there will be separate bits for data and "status/control", should they be cleared here too?

What will happen if fd is opened in 64-bit process and then process will exec a 32-bit one, _after_ doing ioctl but _before_ mmap?! substream->no_mmap_ctrl will remain cleared. Looks disastrous.

And still _now_ there is only one bit. Does it mean "mmap works on data and status/control" or "mmap works on data and _maybe_ on status/control"?

Another matter. IIRC this mmap is not to the hardware (hardware memory-mapped structures won't change layout when one replaces 32bit kernel by 64bit one) but to some software alsa structure. Can it be made more clever in this case, like using 32bit structure for 32bit tasks? Or allowing 32bit tasks to detect that structure is 64bit and they should use it? Second one sounds saner.

Looks like real mess to me.
--
vda

#5 lore raw

[CC list reduced since it's pretty ALSA specific now]

At Fri, 28 Jul 2006 15:14:13 +0200,

Quoted 17 lines · Denis Vlasenko
Quoted 6 lines · Takashi Iwai
Quoted 1 line

Why artsd attempts mmap at all then?

The app must try mmap. From the application side, you can't know whether you're 32bit-emulation mode or it's really on 32bit architecture. And, mmap is usually done automatically via alsa-lib plugin for optimization or soft-mixing purpose.

Well, alsa seems to have info about mmap-ability here:

static struct snd_pcm_hardware azx_pcm_hw = {
        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                 SNDRV_PCM_INFO_MMAP_VALID |
                                 SNDRV_PCM_INFO_PAUSE /*|*/
                                 /*SNDRV_PCM_INFO_RESUME*/),
Quoted 4 lines

...
};

but it is not split into "can mmap data", "can mmap control/status".

It's only for mmap data and has nothing to do with control/status mmap.

Quoted 11 lines

When this one triggers:

snd_pcm_ioctl_compat()
...
/*
* When PCM is used on 32bit mode, we need to disable
* mmap of PCM status/control records because of the size
* incompatibility.
*/
substream->no_mmap_ctrl = 1;

Quoted 7 lines

It does not clear any such flags. If there will be separate bits for data and "status/control", should they be cleared here too?

What will happen if fd is opened in 64-bit process and then process will exec a 32-bit one, _after_ doing ioctl but _before_ mmap?! substream->no_mmap_ctrl will remain cleared. Looks disastrous.

mmap is called always after ioctl as long as you use alsa-lib.

Quoted 3 lines

And still _now_ there is only one bit. Does it mean "mmap works on data and status/control" or "mmap works on data and _maybe_ on status/control"?

The PCM bit is only for mmap data. The status/control mmap is irrelevant, and can be used even the PCM data is non-mmappable.

Quoted 6 lines

Another matter. IIRC this mmap is not to the hardware (hardware memory-mapped structures won't change layout when one replaces 32bit kernel by 64bit one) but to some software alsa structure. Can it be made more clever in this case, like using 32bit structure for 32bit tasks? Or allowing 32bit tasks to detect that structure is 64bit and they should use it?

Would be nice, but how to detect it?

Quoted 1 line

Second one sounds saner.

Well, the simplest solution is to fix that 64bit incompatiblity in the struct definition. Right now, it's still unchanged just to keep the compatibility with older versions, but it's possible to introduce a new struct together with new mmap offset, for example.

Takashi

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

#6 lore raw
In reply to Takashi Iwai
Quoted 6 lines · Takashi Iwai
Quoted 1 line

Why artsd attempts mmap at all then?

The app must try mmap. From the application side, you can't know whether you're 32bit-emulation mode or it's really on 32bit architecture. And, mmap is usually done automatically via alsa-lib plugin for optimization or soft-mixing purpose.

Well, alsa seems to have info about mmap-ability here:

static struct snd_pcm_hardware azx_pcm_hw = {
        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                 SNDRV_PCM_INFO_MMAP_VALID |
                                 SNDRV_PCM_INFO_PAUSE /*|*/
                                 /*SNDRV_PCM_INFO_RESUME*/),

...
};

but it is not split into "can mmap data", "can mmap control/status". When this one triggers:

snd_pcm_ioctl_compat()
...
/*
* When PCM is used on 32bit mode, we need to disable
* mmap of PCM status/control records because of the size
* incompatibility.
*/
substream->no_mmap_ctrl = 1;

It does not clear any such flags. If there will be separate bits for data and "status/control", should they be cleared here too?

What will happen if fd is opened in 64-bit process and then process will exec a 32-bit one, _after_ doing ioctl but _before_ mmap?! substream->no_mmap_ctrl will remain cleared. Looks disastrous.

And still _now_ there is only one bit. Does it mean "mmap works on data and status/control" or "mmap works on data and _maybe_ on status/control"?

Another matter. IIRC this mmap is not to the hardware (hardware memory-mapped structures won't change layout when one replaces 32bit kernel by 64bit one) but to some software alsa structure. Can it be made more clever in this case, like using 32bit structure for 32bit tasks? Or allowing 32bit tasks to detect that structure is 64bit and they should use it? Second one sounds saner.

Looks like real mess to me.
--
vda

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV