Re: problem with XHCI_SPURIOUS_WAKEUP quirk

2019-10-21 Thread Takashi Iwai
On Mon, 21 Oct 2019 20:14:19 +0200,
Ross Zwisler wrote:
> 
> Hi,
> 
> I'm hitting an issue on a Broadwell based Chromebox that appears to be
> related to the XHCI_SPURIOUS_WAKEUP quirk.
> 
> Here are the reproduction steps:
> 
> 1) Start with a fully booted system on a recent kernel.  I've been
> testing with v5.4-rc4.
> 
> 2) Gracefully shut down the system, either with 'halt -p' or by
> pushing the power button.  This causes the XHCI_SPURIOUS_WAKEUP quirk
> to be applied on shutdown via xhci_shutdown().
> 
> 3) Quickly (within a few seconds) restart the system using the power button.
> 
> 4) After the system restarts, we end up in a state where USB 2.0
> devices work fine, but all USB 3.X devices don't work at all.  The
> kernel never sees them being inserted, we never call usb_new_device()
> or any other USB related kernel code.  This state persists for the
> duration of the boot on all ports for the internal USB 3.0 hub, and is
> independent of which devices were plugged into the hub during boot.
> 
> Attaching a USB analyzer between the USB hub and the USB 3.0 device, I
> see that the hub sees the device insertion, but disables SuperSpeed.
> >From then on all the USB analyzer sees is garbage, and the connection
> never successfully drops down to USB 2.0.
> 
> Disabling the above mentioned quirk prevents this from happening, and
> it also doesn't happen if the system is warm rebooted or if the system
> is left off for a longer period of time (~10 seconds or more) before
> powering back on.
> 
> So, a few questions:
> 
> 1) I'm running on a Chromebox using Coreboot.  Does anyone have a
> BIOS-based BDW system to see if they can reproduce it there?

I'll poke a colleague who has a Lenovo laptop with BDW.

> 2) What is the appropriate way to deal with this issue?  From looking
> at the history of the quirk, it looks like it was put in for good
> reasons and that it still needs to be there for other systems.
> Assuming other vendors' systems don't reproduce the above issue,
> should I just exclude Google made systems from the quirk?  Something
> else?

I suspected the symptom rather being XHCI_SPURIOUS_REBOOT, judging
from the description, but it's buggy BIOS thingy, so everything may
happen...

I'd take an approach limiting the change to specific platforms
(Google) via DMI match or such, as the device in question is really
old and has a high potential regression risk.  But just my $0.02.


thanks,

Takashi


Re: [alsa-devel] [PATCH] ALSA: usb-audio: Fix gpf in snd_usb_pipe_sanity_check

2019-07-30 Thread Takashi Iwai
On Tue, 30 Jul 2019 13:28:56 +0200,
Hillf Danton wrote:
> 
> 
> On Tue, 30 Jul 2019 18:08:02 +0800 Takashi Iwai wrote:
> >
> > You don't have to copy the whole these texts at all.
> > In general, it'd suffice to point out the dashboard URL, and if the
> > stack trace is mandatory, drop the useless hex numbers and just show
> > the significant part of the stack trace.
> >
> I am used to give readers as much info as appropriate, and learning that
> an URL is enough in cases like this one. I will send you the pruned
> version next time.

That's fine, I already edited the commit message in my side.

> > > It was introduced in commit 801ebf1043ae for checking pipe and endpoint
> > > types. It is fixed by adding a check of the ep pointer in question.
> > >
> > > Reported-by: syzbot 
> > > 
> > > Fixes: commit 801ebf1043ae ("ALSA: usb-audio: Sanity checks for each pipe 
> > > and EP types")
> >
> > Drop "commit" word.
> >
> Yes, Sir.
> 
> > > Cc: Andrey Konovalov 
> > > Signed-off-by: Hillf Danton 
> > > ---
> There is a typo, s/dhanton/hdanton/, as you pointed out in another mail.

Good, also corrected.

> > > This is to make syzbot happy for now and in long run we can make
> > > snd_usb_pipe_sanity_check() available outside sound/usb by making
> > > usb_urb_ep_type_check() a wrapper of the former. We will revisit
> > > sound/usb once when things in the usb/core get in place.
> >
> > Actually I expected to apply the "long-term" fix now.
> 
> There is change in usb/core included in that fix as you see, and
> according to the rule, one fix a patch, it is better and simpler
> IMO to fix the sound part first.

Yeah, that's a right approach, too.

What I expected was a patch series, containing two changes: one to
add/modify the USB core helper and another to apply it for usb-audio.
But it's fine to move that direction after addressing the usb-audio
problem quickly, of course.

> > The same kind
> > of fix was already submitted from me (),
> > but I didn't merge it because working on the usb core helper would be
> > a saner solution.
> >
> Feel free to merge that, Sir.

Heh, you did it right, so let's merge yours now.

Thanks!


Takashi


Re: [alsa-devel] [PATCH] ALSA: usb-audio: Fix gpf in snd_usb_pipe_sanity_check

2019-07-30 Thread Takashi Iwai
On Tue, 30 Jul 2019 12:07:56 +0200,
Takashi Iwai wrote:
> 
> On Tue, 30 Jul 2019 11:24:36 +0200,
> Hillf Danton wrote:
> > Signed-off-by: Hillf Danton 

BTW, is this address a typo?


Takashi


Re: [alsa-devel] [PATCH] ALSA: usb-audio: Fix gpf in snd_usb_pipe_sanity_check

2019-07-30 Thread Takashi Iwai
On Tue, 30 Jul 2019 11:24:36 +0200,
Hillf Danton wrote:
> 
> 
> syzbot found the following crash on:
> 
> HEAD commit:7f7867ff usb-fuzzer: main usb gadget fuzzer driver
> git tree:   https://github.com/google/kasan.git usb-fuzzer
> console output: https://syzkaller.appspot.com/x/log.txt?x=12befdc860
> kernel config:  https://syzkaller.appspot.com/x/.config?x=792eb47789f57810
> dashboard link: https://syzkaller.appspot.com/bug?extid=d59c4387bfb6eced94e2
> compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
> syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=16efc49fa0
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=1324585460
> 
> usb 1-1: New USB device found, idVendor=07fd, idProduct=0004, bcdDevice=d5.ac
> usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
> usb 1-1: config 0 descriptor??
> usb 1-1: string descriptor 0 read error: -71
> usb 1-1: Waiting for MOTU Microbook II to boot up...
> kasan: CONFIG_KASAN_INLINE enabled
> kasan: GPF could be caused by NULL-ptr deref or user memory access
> general protection fault:  [#1] SMP KASAN
> CPU: 1 PID: 21 Comm: kworker/1:1 Not tainted 5.3.0-rc2+ #23
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS 
> Google 01/01/2011
> Workqueue: usb_hub_wq hub_event
> RIP: 0010:snd_usb_pipe_sanity_check+0x80/0x130 sound/usb/helper.c:75
> Code: 48 c1 ea 03 80 3c 02 00 0f 85 b3 00 00 00 48 8b 6d 00 c1 eb 1e 48 b8  
> 00 00 00 00 00 fc ff df 48 8d 7d 03 48 89 fa 48 c1 ea 03 <0f> b6 04 02 48  
> 89 fa 83 e2 07 38 d0 7f 04 84 c0 75 7b 48 b8 00 00
> RSP: 0018:8881da2f7010 EFLAGS: 00010246
> RAX: dc00 RBX: 0001 RCX: 8484d252
> RDX:  RSI: 8484d26c RDI: 0003
> RBP:  R08: 8881da22e000 R09: ed103b665d58
> R10: ed103b665d57 R11: 8881db32eabf R12: 
> R13: 8881d400ba80 R14: 11103b45ee06 R15: 8881c79244a0
> FS:  () GS:8881db30() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 7f31b2a87000 CR3: 0001d3fd4000 CR4: 001406e0
> Call Trace:
>   snd_usb_motu_microbookii_communicate.constprop.0+0xa0/0x2fb  
> sound/usb/quirks.c:1007
>   snd_usb_motu_microbookii_boot_quirk sound/usb/quirks.c:1051 [inline]
>   snd_usb_apply_boot_quirk.cold+0x163/0x370 sound/usb/quirks.c:1280
>   usb_audio_probe+0x2ec/0x2010 sound/usb/card.c:576
>   usb_probe_interface+0x305/0x7a0 drivers/usb/core/driver.c:361
>   really_probe+0x281/0x650 drivers/base/dd.c:548
>   driver_probe_device+0x101/0x1b0 drivers/base/dd.c:709
>   __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:816
>   bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454
>   __device_attach+0x217/0x360 drivers/base/dd.c:882
>   bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514
>   device_add+0xae6/0x16f0 drivers/base/core.c:2114
>   usb_set_configuration+0xdf6/0x1670 drivers/usb/core/message.c:2023
>   generic_probe+0x9d/0xd5 drivers/usb/core/generic.c:210
>   usb_probe_device+0x99/0x100 drivers/usb/core/driver.c:266
>   really_probe+0x281/0x650 drivers/base/dd.c:548
>   driver_probe_device+0x101/0x1b0 drivers/base/dd.c:709
>   __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:816
>   bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454
>   __device_attach+0x217/0x360 drivers/base/dd.c:882
>   bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514
>   device_add+0xae6/0x16f0 drivers/base/core.c:2114
>   usb_new_device.cold+0x6a4/0xe79 drivers/usb/core/hub.c:2536
>   hub_port_connect drivers/usb/core/hub.c:5098 [inline]
>   hub_port_connect_change drivers/usb/core/hub.c:5213 [inline]
>   port_event drivers/usb/core/hub.c:5359 [inline]
>   hub_event+0x1b5c/0x3640 drivers/usb/core/hub.c:5441
>   process_one_work+0x92b/0x1530 kernel/workqueue.c:2269
>   worker_thread+0x96/0xe20 kernel/workqueue.c:2415
>   kthread+0x318/0x420 kernel/kthread.c:255
>   ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352
> Modules linked in:
> [ end trace 41e8577a8c48635e ]

You don't have to copy the whole these texts at all.
In general, it'd suffice to point out the dashboard URL, and if the
stack trace is mandatory, drop the useless hex numbers and just show
the significant part of the stack trace.

> It was introduced in commit 801ebf1043ae for checking pipe and endpoint
> types. It is fixed by adding a check of the ep pointer in question.
> 
> Reported-by: syzbot 
> Fixes: commit 801ebf1043ae ("ALSA: usb-audio: Sanity checks for each pipe and 
> EP types")

Drop "commit" word.

> Cc: Andrey Konovalov 
> Signed-off-by: Hillf Danton 
> ---
> This is to make syzbot happy for now and in long run we can make
> snd_usb_pipe_sanity_check() available outside sound/usb by making
> usb_urb_ep_type_check() a wrapper of the former. We will revisit
> sound/usb once when things in the usb/core get in place.

Actually I expected to apply the "long-term" fix now.  The same kind
of fix was

Re: general protection fault in snd_usb_pipe_sanity_check

2019-07-30 Thread Takashi Iwai
On Mon, 29 Jul 2019 18:38:06 +0200,
syzbot wrote:
> 
> Hello,
> 
> syzbot found the following crash on:
> 
> HEAD commit:7f7867ff usb-fuzzer: main usb gadget fuzzer driver
> git tree:   https://github.com/google/kasan.git usb-fuzzer
> console output: https://syzkaller.appspot.com/x/log.txt?x=12befdc860
> kernel config:  https://syzkaller.appspot.com/x/.config?x=792eb47789f57810
> dashboard link: https://syzkaller.appspot.com/bug?extid=d59c4387bfb6eced94e2
> compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
> syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=16efc49fa0
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=1324585460
> 
> IMPORTANT: if you fix the bug, please add the following tag to the commit:
> Reported-by: syzbot+d59c4387bfb6eced9...@syzkaller.appspotmail.com
> 
> usb 1-1: New USB device found, idVendor=07fd, idProduct=0004,
> bcdDevice=d5.ac
> usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
> usb 1-1: config 0 descriptor??
> usb 1-1: string descriptor 0 read error: -71
> usb 1-1: Waiting for MOTU Microbook II to boot up...
> kasan: CONFIG_KASAN_INLINE enabled
> kasan: GPF could be caused by NULL-ptr deref or user memory access
> general protection fault:  [#1] SMP KASAN
> CPU: 1 PID: 21 Comm: kworker/1:1 Not tainted 5.3.0-rc2+ #23
> Hardware name: Google Google Compute Engine/Google Compute Engine,
> BIOS  Google 01/01/2011
> Workqueue: usb_hub_wq hub_event
> RIP: 0010:snd_usb_pipe_sanity_check+0x80/0x130 sound/usb/helper.c:75
> Code: 48 c1 ea 03 80 3c 02 00 0f 85 b3 00 00 00 48 8b 6d 00 c1 eb 1e
> 48 b8  00 00 00 00 00 fc ff df 48 8d 7d 03 48 89 fa 48 c1 ea 03 <0f>
> b6 04 02 48  89 fa 83 e2 07 38 d0 7f 04 84 c0 75 7b 48 b8 00 00
> RSP: 0018:8881da2f7010 EFLAGS: 00010246
> RAX: dc00 RBX: 0001 RCX: 8484d252
> RDX:  RSI: 8484d26c RDI: 0003
> RBP:  R08: 8881da22e000 R09: ed103b665d58
> R10: ed103b665d57 R11: 8881db32eabf R12: 
> R13: 8881d400ba80 R14: 11103b45ee06 R15: 8881c79244a0
> FS:  () GS:8881db30() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 7f31b2a87000 CR3: 0001d3fd4000 CR4: 001406e0
> Call Trace:
>  snd_usb_motu_microbookii_communicate.constprop.0+0xa0/0x2fb
> sound/usb/quirks.c:1007
>  snd_usb_motu_microbookii_boot_quirk sound/usb/quirks.c:1051 [inline]
>  snd_usb_apply_boot_quirk.cold+0x163/0x370 sound/usb/quirks.c:1280
>  usb_audio_probe+0x2ec/0x2010 sound/usb/card.c:576
>  usb_probe_interface+0x305/0x7a0 drivers/usb/core/driver.c:361
>  really_probe+0x281/0x650 drivers/base/dd.c:548
>  driver_probe_device+0x101/0x1b0 drivers/base/dd.c:709
(snip)

So finally we hit this known issue.  Hillf, please mark this one to
your fix patch once when ready.


Thanks!

Takashi


Re: WARNING in snd_usb_motu_microbookii_communicate/usb_submit_urb

2019-07-24 Thread Takashi Iwai
On Wed, 24 Jul 2019 15:33:21 +0200,
Andrey Konovalov wrote:
> 
> On Wed, Jul 24, 2019 at 3:15 PM Takashi Iwai  wrote:
> >
> > On Tue, 23 Jul 2019 19:03:29 +0200,
> > Andrey Konovalov wrote:
> > >
> > > (Takashi, with your helper check syzkaller now generates a new bug
> > > report (not reported by syzbot yet due to breakage during kernel boot
> > > on 5.3-rc1, so see below) and I guess this has to do with a missing ep
> > > != NULL check).
> > >
> > > kasan: CONFIG_KASAN_INLINE enabled
> > > kasan: GPF could be caused by NULL-ptr deref or user memory access
> > > general protection fault:  [#1] SMP KASAN
> > > CPU: 1 PID: 74 Comm: kworker/1:1 Not tainted 5.3.0-rc1+ #40
> > > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 
> > > 04/01/2014
> > > Workqueue: usb_hub_wq hub_event
> > > RIP: 0010:snd_usb_pipe_sanity_check+0x80/0x130 sound/usb/helper.c:75
> > > Code: 48 c1 ea 03 80 3c 02 00 0f 85 b3 00 00 00 48 8b 6d 00 c1 eb 1e
> > > 48 b8 00 00 00 00 00 fc ff df 48 8d 7d 03 48 89 fa 48 c1 ea 03 <0f> b6
> > > 04 02 48 89 fa 83 e2 07 38 d0 7f 04 84 c0 75 7b 48 b8 00 00
> > > RSP: 0018:88806c33f0a8 EFLAGS: 00010246
> > > RAX: dc00 RBX: 0001 RCX: 833819c2
> > > RDX:  RSI: 833819dc RDI: 0003
> > > RBP:  R08: 88806c33 R09: fbfff0d1a792
> > > R10: fbfff0d1a791 R11: 868d3c8f R12: 
> > > R13: dc00 R14: 88806975cc80 R15: 88806975c4a0
> > > FS:  () GS:88806d10() 
> > > knlGS:
> > > CS:  0010 DS:  ES:  CR0: 80050033
> > > CR2: 7fcc3a48c000 CR3: 6861c003 CR4: 00160ee0
> > > Call Trace:
> > >  snd_usb_accessmusic_boot_quirk sound/usb/quirks.c:835 [inline]
> > >  snd_usb_apply_boot_quirk+0xa19/0xc60 sound/usb/quirks.c:1267
> > >  usb_audio_probe+0x2ec/0x1f40 sound/usb/card.c:576
> > (snip)
> >
> > So it's a NULL pointer returned from usb_pipe_endpoint() with an
> > invalid pipe.  The fix patch is attached below.
> 
> Thanks for the fix! Do you think it makes sense to reuse the already
> existing usb_urb_ep_type_check() function instead of
> snd_usb_pipe_sanity_check() as Hillf suggested? They seem to be doing
> essentially the same thing.

Ah yes, that makes sense.  I don't mind either way.
If Hillf can submit a fix patch quickly, that's better.

I decided to have a small own helper for the ease of backporting,
possibly to stable trees later on.  Other than that, a common helper
is a better choice.


thanks,

Takashi


Re: WARNING in snd_usb_motu_microbookii_communicate/usb_submit_urb

2019-07-24 Thread Takashi Iwai
On Tue, 23 Jul 2019 19:03:29 +0200,
Andrey Konovalov wrote:
> 
> (Takashi, with your helper check syzkaller now generates a new bug
> report (not reported by syzbot yet due to breakage during kernel boot
> on 5.3-rc1, so see below) and I guess this has to do with a missing ep
> != NULL check).
> 
> kasan: CONFIG_KASAN_INLINE enabled
> kasan: GPF could be caused by NULL-ptr deref or user memory access
> general protection fault:  [#1] SMP KASAN
> CPU: 1 PID: 74 Comm: kworker/1:1 Not tainted 5.3.0-rc1+ #40
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 
> 04/01/2014
> Workqueue: usb_hub_wq hub_event
> RIP: 0010:snd_usb_pipe_sanity_check+0x80/0x130 sound/usb/helper.c:75
> Code: 48 c1 ea 03 80 3c 02 00 0f 85 b3 00 00 00 48 8b 6d 00 c1 eb 1e
> 48 b8 00 00 00 00 00 fc ff df 48 8d 7d 03 48 89 fa 48 c1 ea 03 <0f> b6
> 04 02 48 89 fa 83 e2 07 38 d0 7f 04 84 c0 75 7b 48 b8 00 00
> RSP: 0018:88806c33f0a8 EFLAGS: 00010246
> RAX: dc00 RBX: 0001 RCX: 833819c2
> RDX:  RSI: 833819dc RDI: 0003
> RBP:  R08: 88806c33 R09: fbfff0d1a792
> R10: fbfff0d1a791 R11: 868d3c8f R12: 
> R13: dc00 R14: 88806975cc80 R15: 88806975c4a0
> FS:  () GS:88806d10() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 7fcc3a48c000 CR3: 6861c003 CR4: 00160ee0
> Call Trace:
>  snd_usb_accessmusic_boot_quirk sound/usb/quirks.c:835 [inline]
>  snd_usb_apply_boot_quirk+0xa19/0xc60 sound/usb/quirks.c:1267
>  usb_audio_probe+0x2ec/0x1f40 sound/usb/card.c:576
(snip)

So it's a NULL pointer returned from usb_pipe_endpoint() with an
invalid pipe.  The fix patch is attached below.


thanks,

Takashi

-- 8< --
From: Takashi Iwai 
Subject: [PATCH] ALSA: usb-audio: Fix NULL dereference at pipe sanity check

The newly introduced helper for a sanity check of a pipe causes an
Oops due to the NULL pointer returned from usb_pipe_endpoint() with an
invalid pipe.  Let's fix it.

Fixes: 801ebf1043ae ("ALSA: usb-audio: Sanity checks for each pipe and EP 
types")
Reported-by: Andrey Konovalov 
Signed-off-by: Takashi Iwai 
---
 sound/usb/helper.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index 71d5f540334a..919d69e0aba3 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -72,6 +72,8 @@ int snd_usb_pipe_sanity_check(struct usb_device *dev, 
unsigned int pipe)
struct usb_host_endpoint *ep;
 
ep = usb_pipe_endpoint(dev, pipe);
+   if (!ep)
+   return -EINVAL;
if (usb_pipetype(pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
return -EINVAL;
return 0;
-- 
2.16.4



[PATCH] ALSA: usb-audio: Fix parse of UAC2 Extension Units

2019-07-04 Thread Takashi Iwai
Extension Unit (XU) is used to have a compatible layout with
Processing Unit (PU) on UAC1, and the usb-audio driver code assumed it
for parsing the descriptors.  Meanwhile, on UAC2, XU became slightly
incompatible with PU; namely, XU has a one-byte bmControls bitmap
while PU has two bytes bmControls bitmap.  This incompatibility
results in the read of a wrong address for the last iExtension field,
which ended up with an incorrect string for the mixer element name, as
recently reported for Focusrite Scarlett 18i20 device.

This patch corrects the present misalignment by introducing a couple
of new macros and calling them depending on the descriptor type.

Reported-by: Stefan Sauer 
Cc: 
Signed-off-by: Takashi Iwai 
---
 include/uapi/linux/usb/audio.h | 37 +
 sound/usb/mixer.c  | 16 ++--
 2 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h
index ddc5396800aa..76b7c3f6cd0d 100644
--- a/include/uapi/linux/usb/audio.h
+++ b/include/uapi/linux/usb/audio.h
@@ -450,6 +450,43 @@ static inline __u8 *uac_processing_unit_specific(struct 
uac_processing_unit_desc
}
 }
 
+/*
+ * Extension Unit (XU) has almost compatible layout with Processing Unit, but
+ * on UAC2, it has a different bmControls size (bControlSize); it's 1 byte for
+ * XU while 2 bytes for PU.  The last iExtension field is a one-byte index as
+ * well as iProcessing field of PU.
+ */
+static inline __u8 uac_extension_unit_bControlSize(struct 
uac_processing_unit_descriptor *desc,
+  int protocol)
+{
+   switch (protocol) {
+   case UAC_VERSION_1:
+   return desc->baSourceID[desc->bNrInPins + 4];
+   case UAC_VERSION_2:
+   return 1; /* in UAC2, this value is constant */
+   case UAC_VERSION_3:
+   return 4; /* in UAC3, this value is constant */
+   default:
+   return 1;
+   }
+}
+
+static inline __u8 uac_extension_unit_iExtension(struct 
uac_processing_unit_descriptor *desc,
+int protocol)
+{
+   __u8 control_size = uac_extension_unit_bControlSize(desc, protocol);
+
+   switch (protocol) {
+   case UAC_VERSION_1:
+   case UAC_VERSION_2:
+   default:
+   return *(uac_processing_unit_bmControls(desc, protocol)
++ control_size);
+   case UAC_VERSION_3:
+   return 0; /* UAC3 does not have this field */
+   }
+}
+
 /* 4.5.2 Class-Specific AS Interface Descriptor */
 struct uac1_as_header_descriptor {
__u8  bLength;  /* in bytes: 7 */
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index e003b5e7b01a..ac121b10c51c 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -2318,7 +2318,7 @@ static struct procunit_info extunits[] = {
  */
 static int build_audio_procunit(struct mixer_build *state, int unitid,
void *raw_desc, struct procunit_info *list,
-   char *name)
+   bool extension_unit)
 {
struct uac_processing_unit_descriptor *desc = raw_desc;
int num_ins;
@@ -2335,6 +2335,8 @@ static int build_audio_procunit(struct mixer_build 
*state, int unitid,
static struct procunit_info default_info = {
0, NULL, default_value_info
};
+   const char *name = extension_unit ?
+   "Extension Unit" : "Processing Unit";
 
if (desc->bLength < 13) {
usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", 
name, unitid);
@@ -2448,7 +2450,10 @@ static int build_audio_procunit(struct mixer_build 
*state, int unitid,
} else if (info->name) {
strlcpy(kctl->id.name, info->name, 
sizeof(kctl->id.name));
} else {
-   nameid = uac_processing_unit_iProcessing(desc, 
state->mixer->protocol);
+   if (extension_unit)
+   nameid = uac_extension_unit_iExtension(desc, 
state->mixer->protocol);
+   else
+   nameid = uac_processing_unit_iProcessing(desc, 
state->mixer->protocol);
len = 0;
if (nameid)
len = snd_usb_copy_string_desc(state->chip,
@@ -2481,10 +2486,10 @@ static int parse_audio_processing_unit(struct 
mixer_build *state, int unitid,
case UAC_VERSION_2:
default:
return build_audio_procunit(state, unitid, raw_desc,
-   procunits, "Processing Unit");
+   procunits, false);
case UAC_VERSION_3:
return build_audio_procu

Re: [alsa-devel] don't pass a NULL struct device to DMA API functions

2019-02-01 Thread Takashi Iwai
On Fri, 01 Feb 2019 17:09:57 +0100,
Christoph Hellwig wrote:
> 
> On Fri, Feb 01, 2019 at 02:16:08PM +0100, Takashi Iwai wrote:
> > Actually there are a bunch of ISA sound drivers that still call
> > allocators with NULL device.
> > 
> > The patch below should address it, although it's only compile-tested.
> 
> Oh, I missed these "indirect" calls.  This looks good to me:
> 
> Reviewed-by: Christoph Hellwig 

OK, merged this one to for-next branch now as well.


thanks,

Takashi



Re: [alsa-devel] [PATCH 17/18] ALSA: hal2: pass struct device to DMA API functions

2019-02-01 Thread Takashi Iwai
On Fri, 01 Feb 2019 17:09:06 +0100,
Christoph Hellwig wrote:
> 
> On Fri, Feb 01, 2019 at 02:12:45PM +0100, Takashi Iwai wrote:
> > Shall I take this one through sound git tree or all through yours?
> 
> Feel free to merge the sound bits through your tree!

Alright, merged both patches 17 and 18 now.


thanks,

Takashi


Re: [alsa-devel] don't pass a NULL struct device to DMA API functions

2019-02-01 Thread Takashi Iwai
On Fri, 01 Feb 2019 09:47:43 +0100,
Christoph Hellwig wrote:
> 
> We still have a few drivers which pass a NULL struct device pointer
> to DMA API functions, which generally is a bad idea as the API
> implementations rely on the device not only for ops selection, but
> also the dma mask and various other attributes.
> 
> This series contains all easy conversions to pass a struct device,
> besides that there also is some arch code that needs separate handling,
> a driver that should not use the DMA API at all, and one that is
> a complete basket case to be deal with separately.

Actually there are a bunch of ISA sound drivers that still call
allocators with NULL device.

The patch below should address it, although it's only compile-tested.


thanks,

Takashi

-- 8< --
From: Takashi Iwai 
Subject: [PATCH] ALSA: isa: Avoid passing NULL to memory allocators

We used to pass NULL to memory allocators for ISA devices due to
historical reasons.  But we prefer rather a proper device object to be
assigned, so let's fix it by replacing snd_dma_isa_data() call with
card->dev reference, and kill snd_dma_isa_data() definition.

Signed-off-by: Takashi Iwai 
---
 Documentation/sound/kernel-api/writing-an-alsa-driver.rst | 10 +-
 include/sound/memalloc.h  |  1 -
 sound/isa/ad1816a/ad1816a_lib.c   |  2 +-
 sound/isa/cmi8330.c   |  2 +-
 sound/isa/es1688/es1688_lib.c |  2 +-
 sound/isa/es18xx.c|  2 +-
 sound/isa/gus/gus_pcm.c   |  4 ++--
 sound/isa/sb/sb16_main.c  |  2 +-
 sound/isa/sb/sb8_main.c   |  2 +-
 sound/isa/sscape.c|  7 ---
 sound/isa/wss/wss_lib.c   |  2 +-
 11 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst 
b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
index 7c2f2032d30a..6b154dbb02cc 100644
--- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
+++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
@@ -3520,14 +3520,14 @@ allocator will try to get an area as large as possible 
within the
 given size.
 
 The second argument (type) and the third argument (device pointer) are
-dependent on the bus. In the case of the ISA bus, pass
-:c:func:`snd_dma_isa_data()` as the third argument with
+dependent on the bus. For normal devices, pass the device pointer
+(typically identical as ``card->dev``) to the third argument with
 ``SNDRV_DMA_TYPE_DEV`` type. For the continuous buffer unrelated to the
 bus can be pre-allocated with ``SNDRV_DMA_TYPE_CONTINUOUS`` type and the
 ``snd_dma_continuous_data(GFP_KERNEL)`` device pointer, where
-``GFP_KERNEL`` is the kernel allocation flag to use. For the PCI
-scatter-gather buffers, use ``SNDRV_DMA_TYPE_DEV_SG`` with
-``snd_dma_pci_data(pci)`` (see the `Non-Contiguous Buffers`_
+``GFP_KERNEL`` is the kernel allocation flag to use. For the
+scatter-gather buffers, use ``SNDRV_DMA_TYPE_DEV_SG`` with the device
+pointer (see the `Non-Contiguous Buffers`_
 section).
 
 Once the buffer is pre-allocated, you can use the allocator in the
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index af3fa577fa06..1ac0dd82a916 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -37,7 +37,6 @@ struct snd_dma_device {
 };
 
 #define snd_dma_pci_data(pci)  (&(pci)->dev)
-#define snd_dma_isa_data() NULL
 #define snd_dma_continuous_data(x) ((struct device *)(__force unsigned 
long)(x))
 
 
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index 61e8c7e524db..94b381a78e9e 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -693,7 +693,7 @@ int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device)
snd_ad1816a_init(chip);
 
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
+ chip->card->dev,
  64*1024, chip->dma1 > 3 || 
chip->dma2 > 3 ? 128*1024 : 64*1024);
 
chip->pcm = pcm;
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 7e5aa06414c4..1868b73aa49c 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -470,7 +470,7 @@ static int snd_cmi8330_pcm(struct snd_card *card, struct 
snd_cmi8330 *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 
&chip->streams[SNDRV_PCM_STREAM_CAPTURE].ops);
 
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
+   

Re: [alsa-devel] [PATCH 17/18] ALSA: hal2: pass struct device to DMA API functions

2019-02-01 Thread Takashi Iwai
On Fri, 01 Feb 2019 09:48:00 +0100,
Christoph Hellwig wrote:
> 
> The DMA API generally relies on a struct device to work properly, and
> only barely works without one for legacy reasons.  Pass the easily
> available struct device from the platform_device to remedy this.
> 
> Signed-off-by: Christoph Hellwig 

Looks good to me:
  Reviewed-by: Takashi Iwai 

Shall I take this one through sound git tree or all through yours?


thanks,

Takashi


Re: [alsa-devel] [PATCH 18/18] ALSA: pass struct device to DMA API functions

2019-02-01 Thread Takashi Iwai
On Fri, 01 Feb 2019 09:48:01 +0100,
Christoph Hellwig wrote:
> 
> The DMA API generally relies on a struct device to work properly, and
> only barely works without one for legacy reasons.  Pass the easily
> available struct device from the platform_device to remedy this.
> 
> Also use GFP_KERNEL instead of GFP_USER as the gfp_t for the memory
> allocation, as we should treat this allocation as a normal kernel one.
> 
> Signed-off-by: Christoph Hellwig 

Reviewed-by: Takashi Iwai 


thanks,

Takashi


Re: ALSA:usb audio Higher sample rates on usb audio no longer working.

2019-01-03 Thread Takashi Iwai
On Fri, 04 Jan 2019 00:16:42 +0100,
Con Kolivas wrote:
> 
> Hi Iwai-san.
> 
> Added some relevant CCs.
> 
> On Fri, 4 Jan 2019 at 00:23, Takashi Iwai  wrote:
> >
> > On Thu, 03 Jan 2019 12:43:54 +0100,
> > Con Kolivas wrote:
> > >
> > > Upon switching from 4.19.0 to 4.20.0, pulseaudio started complaining
> > > that sinks that previously worked are no longer supported.
> > >
> > > On 4.19.0 trying 24 bit 88200, 176400, and 192000 I get the following
> > > output from pulse.
> > > resampler.c: Forcing resampler 'copy', because of fixed, identical
> > > sample rates.sink-input.c: Created input 15 "Playback Stream" on
> > > alsa_output.usb-DSPeaker_Anti-Mode_X4-00.iec958-stereo with sample
> > > spec float32le 2ch 176400Hz and channel map front-left,front-right
> > >
> > > Switching to 4.20 gives me:
> > > alsa-sink.c: Sink does not support sample rate of 176400 Hz
> > > and
> > > alsa-sink.c: Sink does not support sample rate of 88200 Hz
> > > and
> > > alsa-sink.c: Sink does not support sample rate of 192000 Hz
> > >
> > > Sample rates of 44100, 48000, and 96000 work fine, but 88200, 176400,
> > > and 192000 no longer work
> > >
> > > Switching back to 4.19 immediately fixes the issue.
> > >
> > >
> > > I tried looking through the alsa changelogs but there were too many to
> > > give an obvious culprit, and haven't had time to do a git bisect. If
> > > there's an obvious choice patch to back out I'd be grateful for the
> > > heads up.
> >
> > Hm, through a quick glance, there hasn't been any relevant changes in
> > USB-audio part (sound/usb/*).  Also, the changes in sound/core/* are
> > irrelevant with your problem.
> >
> > So I have no idea what went wrong.  The bisection, or at least,
> > narrowing down the commits would be helpful.
> 
> I've done a git bisect and found the offending commit:
> 
> commit f13912d3f014a7f2fa5c35d25ee8c3f96bda6272 (refs/bisect/bad)
> Author: Saranya Gopal 
> Date:   Wed Sep 12 08:46:26 2018 +0530
> 
> usbcore: Select UAC3 configuration for audio if present
> 
> USB audio class 3.0 specification introduced many significant
> changes like
>  - new power domains, support for LPM/L1
>  - new cluster descriptor
>  - new high capability and class-specific string descriptors
>  - BADD profiles
>  - ... and many other things (check spec from link below:
> http://www.usb.org/developers/docs/devclass_docs/USB_Audio_v3.0.zip)
> 
> Now that UAC3 is supported in linux, choose UAC3
> configuration for audio if the device supports it.
> Selecting this configuration will enable the system to
> save power by leveraging the new power domains and LPM L1
> capability and also support new codec types and data formats
> for consumer audio applications.
> 
> Signed-off-by: Saranya Gopal 
> Reviewed-by: Felipe Balbi 
> Signed-off-by: Greg Kroah-Hartman 
> 
> Reverting this patch fixes the problem for me.

[ Adding linux-usb ML to Cc, as it's a core USB issue ]

So the device seems incorrectly advertising as if it were supporting
UAC3 -- assuming the device is still not UAC3-capable.

IOW, it's a buggy firmware.  We need some blacklisting, or revert the
commit for now, unless any real UAC3 device comes up to the market.


thanks,

Takashi


Re: [alsa-devel] [PATCH 6/9] ALSA: usb: caiaq: use usb_fill_int_urb()

2018-06-22 Thread Takashi Iwai
On Thu, 21 Jun 2018 23:16:39 +0200,
Sebastian Andrzej Siewior wrote:
> 
> On 2018-06-21 22:19:32 [+0200], Daniel Mack wrote:
> > On Tuesday, June 19, 2018 11:55 PM, Sebastian Andrzej Siewior wrote:
> > > Using usb_fill_int_urb() helps to find code which initializes an
> > > URB. A grep for members of the struct (like ->complete) reveal lots
> > > of other things, too.
> > 
> > Acked-by: Daniel Mack 
> 
> nope, please don't.
> Takashi, please ignore the usb_fill_.* patches. I will be doing another
> spin with usb_fill_iso_urb() instead.

This sounds like a better approach, indeed.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 8/9] ALSA: usx2y: usbusx2yaudio: use usb_fill_int_urb()

2018-06-20 Thread Takashi Iwai
On Wed, 20 Jun 2018 17:47:01 +0200,
Sebastian Andrzej Siewior wrote:
> 
> On 2018-06-20 17:38:44 [+0200], To Takashi Iwai wrote:
> > okay, as you wish:
> 
> I'm sorry, I compiled one patch and send the other. Here is the fixed
> one.

Well, you seem to have forgotten to update the changelog...

Don't need to rush, it's a change for 4.19.


thanks,

Takashi

> 
> > > thanks,
> > > 
> > > Takashi
> > 
> --- >8
> Subject: [PATCH 8/9 v4] ALSA: usx2y: usbusx2yaudio: use usb_fill_int_urb()
> 
> Using usb_fill_int_urb() helps to find code which initializes an
> URB. A grep for members of the struct (like ->complete) reveal lots
> of other things, too.
> 
> The "&& !(*purb)->transfer_buffer" check has been removed because the
> URB has been freshly allocated a few lines above so ->transfer_buffer
> has to be NULL here.
> The `dev' and `transfer_size' assignments have been moved from
> usX2Y_urbs_start() to usX2Y_urbs_allocate() because they don't change
> overtime.
> The multiplication via check_mul_overflow() has been extracted from
> kmalloc_array() to avoid two multiplication (one with overflow check and
> one without for the length argument). This requires to change the type
> `maxpacksize' to int so there is only one type involved in the
> multiplication.
> 
> Cc: Jaroslav Kysela 
> Cc: Takashi Iwai 
> Signed-off-by: Sebastian Andrzej Siewior 
> ---
>  sound/usb/usx2y/usbusx2yaudio.c | 23 +++
>  1 file changed, 11 insertions(+), 12 deletions(-)
> 
> diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
> index 2b833054e3b0..de3a21444db3 100644
> --- a/sound/usb/usx2y/usbusx2yaudio.c
> +++ b/sound/usb/usx2y/usbusx2yaudio.c
> @@ -425,6 +425,9 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream 
> *subs)
>   /* allocate and initialize data urbs */
>   for (i = 0; i < NRURBS; i++) {
>   struct urb **purb = subs->urb + i;
> + void *buf = NULL;
> + int len = 0;
> +
>   if (*purb) {
>   usb_kill_urb(*purb);
>   continue;
> @@ -434,22 +437,20 @@ static int usX2Y_urbs_allocate(struct 
> snd_usX2Y_substream *subs)
>   usX2Y_urbs_release(subs);
>   return -ENOMEM;
>   }
> - if (!is_playback && !(*purb)->transfer_buffer) {
> +
> + if (!is_playback) {
>   /* allocate a capture buffer per urb */
> - (*purb)->transfer_buffer =
> - kmalloc_array(subs->maxpacksize,
> -   nr_of_packs(), GFP_KERNEL);
> - if (NULL == (*purb)->transfer_buffer) {
> + buf = kmalloc_array(subs->maxpacksize, nr_of_packs(),
> + GFP_KERNEL);
> + if (!buf) {
>   usX2Y_urbs_release(subs);
>   return -ENOMEM;
>   }
> + len = subs->maxpacksize * nr_of_packs();
>   }
> - (*purb)->dev = dev;
> - (*purb)->pipe = pipe;
> + usb_fill_int_urb(*purb, dev, pipe, buf, len,
> +  i_usX2Y_subs_startup, subs, 1);
>   (*purb)->number_of_packets = nr_of_packs();
> - (*purb)->context = subs;
> - (*purb)->interval = 1;
> - (*purb)->complete = i_usX2Y_subs_startup;
>   }
>   return 0;
>  }
> @@ -485,12 +486,10 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream 
> *subs)
>   unsigned long pack;
>   if (0 == i)
>   atomic_set(&subs->state, state_STARTING3);
> - urb->dev = usX2Y->dev;
>   for (pack = 0; pack < nr_of_packs(); pack++) {
>   urb->iso_frame_desc[pack].offset = 
> subs->maxpacksize * pack;
>   urb->iso_frame_desc[pack].length = 
> subs->maxpacksize;
>   }
> - urb->transfer_buffer_length = subs->maxpacksize * 
> nr_of_packs(); 
>   if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
>   snd_printk (KERN_ERR "cannot submit datapipe 
> for urb %d, err = %d\n", i, err);
>   err = -EPIPE;
> -- 
> 2.17.1
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 8/9] ALSA: usx2y: usbusx2yaudio: use usb_fill_int_urb()

2018-06-20 Thread Takashi Iwai
On Wed, 20 Jun 2018 16:39:22 +0200,
Sebastian Andrzej Siewior wrote:
> 
> On 2018-06-20 14:51:12 [+0200], Takashi Iwai wrote:
> > On Tue, 19 Jun 2018 23:55:20 +0200,
> > Sebastian Andrzej Siewior wrote:
> > > - (*purb)->transfer_buffer =
> > > - kmalloc_array(subs->maxpacksize,
> > > -   nr_of_packs(), GFP_KERNEL);
> > > - if (NULL == (*purb)->transfer_buffer) {
> > > + len = subs->maxpacksize * nr_of_packs();
> > > + buf = kmalloc(len, GFP_KERNEL);
> > 
> > I'd keep kmalloc_array() as is, and just put subs->maxpacksize *
> > nr_of_packs() in usb_fill_int_urb().  Otherwise it's a step backward.
> 
> but then we end up with two multiplications.

Yes, but it's no hot path, and the code won't bigger.
And I bet you won't notice any performance lost by that :)

> What about pulling the
> overflow-mul macro out of malloc_array() and doing this instead:

Well, it's neither smaller nor more readable...


thanks,

Takashi

> 
> --- >8
> 
> Subject: [PATCH 8/9 v2] ALSA: usx2y: usbusx2yaudio: use usb_fill_int_urb()
> 
> Using usb_fill_int_urb() helps to find code which initializes an
> URB. A grep for members of the struct (like ->complete) reveal lots
> of other things, too.
> 
> The "&& !(*purb)->transfer_buffer" check has been removed because the
> URB has been freshly allocated a few lines above so ->transfer_buffer
> has to be NULL here.
> The `dev' and `transfer_size' assignments have been moved from
> usX2Y_urbs_start() to usX2Y_urbs_allocate() because they don't change
> overtime.
> The multiplication via check_mul_overflow() has been extracted from
> kmalloc_array() to avoid two multiplication (one with overflow check and
> one without for the length argument). This requires to change the type
> `maxpacksize' to int so there is only one type involved in the
> multiplication.
> 
> Cc: Jaroslav Kysela 
> Cc: Takashi Iwai 
> Signed-off-by: Sebastian Andrzej Siewior 
> ---
>  sound/usb/usx2y/usbusx2y.h  |  2 +-
>  sound/usb/usx2y/usbusx2yaudio.c | 38 -
>  2 files changed, 20 insertions(+), 20 deletions(-)
> 
> diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h
> index e0f77172ce8f..2bec412589b4 100644
> --- a/sound/usb/usx2y/usbusx2y.h
> +++ b/sound/usb/usx2y/usbusx2y.h
> @@ -56,7 +56,7 @@ struct snd_usX2Y_substream {
>   struct snd_pcm_substream *pcm_substream;
>  
>   int endpoint;   
> - unsigned intmaxpacksize;/* max packet size in 
> bytes */
> + int maxpacksize;/* max packet size in 
> bytes */
>  
>   atomic_tstate;
>  #define state_STOPPED0
> diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
> index 2b833054e3b0..e5580cb59858 100644
> --- a/sound/usb/usx2y/usbusx2yaudio.c
> +++ b/sound/usb/usx2y/usbusx2yaudio.c
> @@ -425,33 +425,35 @@ static int usX2Y_urbs_allocate(struct 
> snd_usX2Y_substream *subs)
>   /* allocate and initialize data urbs */
>   for (i = 0; i < NRURBS; i++) {
>   struct urb **purb = subs->urb + i;
> + void *buf = NULL;
> + int len = 0;
> +
>   if (*purb) {
>   usb_kill_urb(*purb);
>   continue;
>   }
>   *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL);
> - if (NULL == *purb) {
> - usX2Y_urbs_release(subs);
> - return -ENOMEM;
> - }
> - if (!is_playback && !(*purb)->transfer_buffer) {
> + if (NULL == *purb)
> + goto err_free;
> +
> + if (!is_playback) {
>   /* allocate a capture buffer per urb */
> - (*purb)->transfer_buffer =
> - kmalloc_array(subs->maxpacksize,
> -   nr_of_packs(), GFP_KERNEL);
> - if (NULL == (*purb)->transfer_buffer) {
> - usX2Y_urbs_release(subs);
> - return -ENOMEM;
> - }
> + if (check_mul_overflow(subs->maxpacksize,
> +nr_of_packs(),
> +&len))
> + goto err_free;
> +   

Re: [PATCH 4/9 v2] ALSA: usb-audio: use usb_fill_int_urb()

2018-06-20 Thread Takashi Iwai
On Wed, 20 Jun 2018 15:56:53 +0200,
Takashi Iwai wrote:
> 
> On Wed, 20 Jun 2018 15:52:49 +0200,
> Sebastian Andrzej Siewior wrote:
> > 
> > On 2018-06-20 15:21:49 [+0200], Takashi Iwai wrote:
> > > > usb_fill_int_urb() ensures that syncinterval is within the allowed range
> > > > on HS/SS. The interval value seems to come from
> > > > snd_usb_parse_datainterval() which is bInterval - 1 and only in the rage
> > > > 1 … 4. So in order to keep the magic working I pass datainterval + 1.
> > > 
> > > This needs more explanation.  By this conversion, the interval
> > > computation becomes really tricky.
> > > 
> > > There are two interval calculations.  The first one is
> > > fp->datainterval and it's from snd_usb_parse_datainterval() as you
> > > mentioned.  And a tricky part is that fp->datainterval is 0 on
> > > FULL_SPEED.  Casually, fp->datainterval+1 will be translated to the
> > > correct value since (0 + 1) == (1 << 0).
> > > 
> > > OTOH, for the sync EP, it's taken from ep->syncinterval, which is set
> > > in snd_usb_add_endpoint().  Luckily, again, ep->syncinterval + 1 works
> > > for FULL_SPEED as well, as (1 + 1) == (1 << 1).
> > 
> > Do you want me to add your additional explanation to the description?
> 
> Yes.  It's a very implicit assumption, and needs clarification.
> In addition, the comment 1...4 is only for fp->datainterval, not about
> ep->syncinterval.
> 
> Alternatively, give some comments in the places where putting
> fp->datainterval and ep->syncinterval.

Oh, and for other patches, something about interval could be
mentioned in the change log.  You pass 1 to the macro as if it were
identical as the original code (urb->interval = 1), but this isn't
evaluated equally.

Effectively it'll result in the same, but better to be clarified.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/9 v2] ALSA: usb-audio: use usb_fill_int_urb()

2018-06-20 Thread Takashi Iwai
On Wed, 20 Jun 2018 15:52:49 +0200,
Sebastian Andrzej Siewior wrote:
> 
> On 2018-06-20 15:21:49 [+0200], Takashi Iwai wrote:
> > > usb_fill_int_urb() ensures that syncinterval is within the allowed range
> > > on HS/SS. The interval value seems to come from
> > > snd_usb_parse_datainterval() which is bInterval - 1 and only in the rage
> > > 1 … 4. So in order to keep the magic working I pass datainterval + 1.
> > 
> > This needs more explanation.  By this conversion, the interval
> > computation becomes really tricky.
> > 
> > There are two interval calculations.  The first one is
> > fp->datainterval and it's from snd_usb_parse_datainterval() as you
> > mentioned.  And a tricky part is that fp->datainterval is 0 on
> > FULL_SPEED.  Casually, fp->datainterval+1 will be translated to the
> > correct value since (0 + 1) == (1 << 0).
> > 
> > OTOH, for the sync EP, it's taken from ep->syncinterval, which is set
> > in snd_usb_add_endpoint().  Luckily, again, ep->syncinterval + 1 works
> > for FULL_SPEED as well, as (1 + 1) == (1 << 1).
> 
> Do you want me to add your additional explanation to the description?

Yes.  It's a very implicit assumption, and needs clarification.
In addition, the comment 1...4 is only for fp->datainterval, not about
ep->syncinterval.

Alternatively, give some comments in the places where putting
fp->datainterval and ep->syncinterval.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/9 v2] ALSA: usb-audio: use usb_fill_int_urb()

2018-06-20 Thread Takashi Iwai
On Wed, 20 Jun 2018 11:38:27 +0200,
Sebastian Andrzej Siewior wrote:
> 
> Using usb_fill_int_urb() helps to find code which initializes an
> URB. A grep for members of the struct (like ->complete) reveal lots
> of other things, too.
> 
> data_ep_set_params() additionally sets urb->transfer_buffer_length which
> was not the case earlier.
> usb_fill_int_urb() ensures that syncinterval is within the allowed range
> on HS/SS. The interval value seems to come from
> snd_usb_parse_datainterval() which is bInterval - 1 and only in the rage
> 1 … 4. So in order to keep the magic working I pass datainterval + 1.

This needs more explanation.  By this conversion, the interval
computation becomes really tricky.

There are two interval calculations.  The first one is
fp->datainterval and it's from snd_usb_parse_datainterval() as you
mentioned.  And a tricky part is that fp->datainterval is 0 on
FULL_SPEED.  Casually, fp->datainterval+1 will be translated to the
correct value since (0 + 1) == (1 << 0).

OTOH, for the sync EP, it's taken from ep->syncinterval, which is set
in snd_usb_add_endpoint().  Luckily, again, ep->syncinterval + 1 works
for FULL_SPEED as well, as (1 + 1) == (1 << 1).


thanks,

Takashi

> Cc: Jaroslav Kysela 
> Cc: Takashi Iwai 
> Signed-off-by: Sebastian Andrzej Siewior 
> ---
> v1…v2: description changes (spelling + usb_fill_int_urb() ensures
>"syncinterval" not data_ep_set_params())
> 
>  sound/usb/endpoint.c | 24 ++--
>  1 file changed, 10 insertions(+), 14 deletions(-)
> 
> diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
> index c90607ebe155..bbc02db5b417 100644
> --- a/sound/usb/endpoint.c
> +++ b/sound/usb/endpoint.c
> @@ -772,6 +772,8 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
>   /* allocate and initialize data urbs */
>   for (i = 0; i < ep->nurbs; i++) {
>   struct snd_urb_ctx *u = &ep->urb[i];
> + void *buf;
> +
>   u->index = i;
>   u->ep = ep;
>   u->packets = urb_packs;
> @@ -783,16 +785,13 @@ static int data_ep_set_params(struct snd_usb_endpoint 
> *ep,
>   if (!u->urb)
>   goto out_of_memory;
>  
> - u->urb->transfer_buffer =
> - usb_alloc_coherent(ep->chip->dev, u->buffer_size,
> -GFP_KERNEL, &u->urb->transfer_dma);
> - if (!u->urb->transfer_buffer)
> + buf = usb_alloc_coherent(ep->chip->dev, u->buffer_size,
> +  GFP_KERNEL, &u->urb->transfer_dma);
> + if (!buf)
>   goto out_of_memory;
> - u->urb->pipe = ep->pipe;
> + usb_fill_int_urb(u->urb, NULL, ep->pipe, buf, u->buffer_size,
> +  snd_complete_urb, u, ep->datainterval + 1);
>   u->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
> - u->urb->interval = 1 << ep->datainterval;
> - u->urb->context = u;
> - u->urb->complete = snd_complete_urb;
>   INIT_LIST_HEAD(&u->ready_list);
>   }
>  
> @@ -823,15 +822,12 @@ static int sync_ep_set_params(struct snd_usb_endpoint 
> *ep)
>   u->urb = usb_alloc_urb(1, GFP_KERNEL);
>   if (!u->urb)
>   goto out_of_memory;
> - u->urb->transfer_buffer = ep->syncbuf + i * 4;
> + usb_fill_int_urb(u->urb, NULL, ep->pipe, ep->syncbuf + i * 4, 4,
> +  snd_complete_urb, u, ep->syncinterval + 1);
> +
>   u->urb->transfer_dma = ep->sync_dma + i * 4;
> - u->urb->transfer_buffer_length = 4;
> - u->urb->pipe = ep->pipe;
>   u->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
>   u->urb->number_of_packets = 1;
> - u->urb->interval = 1 << ep->syncinterval;
> - u->urb->context = u;
> - u->urb->complete = snd_complete_urb;
>   }
>  
>   ep->nurbs = SYNC_URBS;
> -- 
> 2.17.1
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: ALSA: use irqsave() in URB completion + usb_fill_int_urb

2018-06-20 Thread Takashi Iwai
On Tue, 19 Jun 2018 23:55:12 +0200,
Sebastian Andrzej Siewior wrote:
> 
> This series is mostly about using _irqsave() primitives in the
> completion callback in order to get rid of local_irq_save() in
> __usb_hcd_giveback_urb(). While at it, I also tried to move drivers to
> use usb_fill_int_urb() otherwise it is hard find users of a certain API.

At the next time, please split to two different patchsets in such a
case.  The conversions to usb_fill_int_urb() and the change to
_irqsave() are completely different things; the former is merely a
code cleanup that doesn't give any functional change, while the latter
is the followup for the USB core change.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 8/9] ALSA: usx2y: usbusx2yaudio: use usb_fill_int_urb()

2018-06-20 Thread Takashi Iwai
On Tue, 19 Jun 2018 23:55:20 +0200,
Sebastian Andrzej Siewior wrote:
> 
> Using usb_fill_int_urb() helps to find code which initializes an
> URB. A grep for members of the struct (like ->complete) reveal lots
> of other things, too.
> 
> The "&& !(*purb)->transfer_buffer" check has been removed because the
> URB has been freshly allocated a few lines above so ->transfer_buffer
> has to be NULL here.
> The `dev' and `transfer_size' assignments have been moved from
> usX2Y_urbs_start() to usX2Y_urbs_allocate() because they don't change
> overtime.
> 
> Cc: Jaroslav Kysela 
> Cc: Takashi Iwai 
> Signed-off-by: Sebastian Andrzej Siewior 
> ---
>  sound/usb/usx2y/usbusx2yaudio.c | 21 +
>  1 file changed, 9 insertions(+), 12 deletions(-)
> 
> diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
> index 2b833054e3b0..9a49bdb07508 100644
> --- a/sound/usb/usx2y/usbusx2yaudio.c
> +++ b/sound/usb/usx2y/usbusx2yaudio.c
> @@ -425,6 +425,9 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream 
> *subs)
>   /* allocate and initialize data urbs */
>   for (i = 0; i < NRURBS; i++) {
>   struct urb **purb = subs->urb + i;
> + void *buf = NULL;
> + unsigned int len = 0;
> +
>   if (*purb) {
>   usb_kill_urb(*purb);
>   continue;
> @@ -434,22 +437,18 @@ static int usX2Y_urbs_allocate(struct 
> snd_usX2Y_substream *subs)
>   usX2Y_urbs_release(subs);
>   return -ENOMEM;
>   }
> - if (!is_playback && !(*purb)->transfer_buffer) {
> + if (!is_playback) {
>   /* allocate a capture buffer per urb */
> - (*purb)->transfer_buffer =
> - kmalloc_array(subs->maxpacksize,
> -   nr_of_packs(), GFP_KERNEL);
> - if (NULL == (*purb)->transfer_buffer) {
> + len = subs->maxpacksize * nr_of_packs();
> + buf = kmalloc(len, GFP_KERNEL);

I'd keep kmalloc_array() as is, and just put subs->maxpacksize *
nr_of_packs() in usb_fill_int_urb().  Otherwise it's a step backward.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] usb: audio-v2: Correct the comment for struct uac_clock_selector_descriptor

2018-04-06 Thread Takashi Iwai
The comment in UAC2 clock selector descriptor definition mentions the
bAssocTerminal after baCSourceID[], but it doesn't exist in the actual
definition.  Let's correct it.

Fixes: 5dd360ebd832 ("include/linux/usb/audio-v2.h: add more UAC2 details")
Signed-off-by: Takashi Iwai 
---
 include/linux/usb/audio-v2.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h
index aaafecf073ff..49699255cfd3 100644
--- a/include/linux/usb/audio-v2.h
+++ b/include/linux/usb/audio-v2.h
@@ -94,7 +94,7 @@ struct uac_clock_selector_descriptor {
__u8 bClockID;
__u8 bNrInPins;
__u8 baCSourceID[];
-   /* bmControls, bAssocTerminal and iClockSource omitted */
+   /* bmControls and iClockSource omitted */
 } __attribute__((packed));
 
 /* 4.7.2.3 Clock Multiplier Descriptor */
-- 
2.16.3

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Mixer regression with usb soundcard

2017-12-18 Thread Takashi Iwai
On Tue, 19 Dec 2017 02:04:51 +0100,
Mauro Santos wrote:
> 
> On 18-12-2017 22:48, Takashi Iwai wrote:
> > On Mon, 18 Dec 2017 22:56:07 +0100,
> > Mauro Santos wrote:
> >>
> >> On 18-12-2017 19:30, Takashi Iwai wrote:
> >>> On Mon, 18 Dec 2017 20:10:44 +0100,
> >>> Mauro Santos wrote:
> >>>>
> >>>> On 18-12-2017 17:50, Jaejoong Kim wrote:
> >>>>> Mauro,
> >>>>>
> >>>>> Could you please try debug patch(I also attach the patch file)?
> >>>>
> >>>> With the attached patch I get the following when plugging in the usb dac
> >>>> directly to a usb3 port:
> >>>> [   54.391539] usb 1-2: new full-speed USB device number 7 using xhci_hcd
> >>>> [   54.514996] usb 1-2: device descriptor read/64, error -71
> >>>> [   54.849808] input: HiFimeDIY Audio HiFimeDIY DAC as
> >>>> /devices/pci:00/:00:14.0/usb1/1-2/1-2:1.0/0003:1852:7022.0003/input/input20
> >>>> [   54.850168] hid-generic 0003:1852:7022.0003: input,hidraw2: USB HID
> >>>> v1.00 Device [HiFimeDIY Audio HiFimeDIY DAC] on usb-:00:14.0-2/input0
> >>>> [   54.950421] usb 1-2: [DEBUG] nameid:0, len:0
> >>>> [   54.950426] usb 1-2: [DEBUG] len:3, get_term_name:PCM
> >>>> [   54.950429] usb 1-2: [11] SU [PCM] items = 2
> >>>> [   54.950985] usbcore: registered new interface driver snd-usb-audio
> >>>
> >>> Hmm, the driver get the supposedly correct name string here, so I see
> >>> no flaw, so far.
> >>>
> >>> Could you put the similar debug prints after reverting the commit and
> >>> compare?  Or, at minimum, you can enable simply the kernel debug
> >>> prints like below:
> >>>
> >>>   % echo "file sound/usb/mixer.c +p" > 
> >>> /sys/kernel/debug/dynamic_debug_control
> >>>
> >>> and re-plug the device.
> >>>
> >>> Also, could you attach the output of "amixer contents" on both working
> >>> and non-working kernels?
> >>>
> >>
> >> I have compiled a new kernel where I have reverted the commit and I've
> >> added the debug output based on your last debug patch. I attach the
> >> patch that reverts the changes and adds the debug output just in case
> >> anyone wants to do a sanity check on it (don't mind the indentation I
> >> think I botched that).
> >>
> >> With the debug patches I get no extra output when echoing to the
> >> dynamic_debug/control file, I guess that's expected.
> >>
> >> I attach the dmesg and amixer outputs for the case without revert plus
> >> debug (bad) and revert plus debug (good).
> >>
> >> One change does jump out:
> >>
> >> bad:  usb 1-2: [11] SU [PCM] items = 2
> >> good: usb 1-2: [11] SU [PCM Capture Source] items = 2
> > 
> > Thanks, that explains what went wrong.  The commit dropped the brace
> > at the if-line, and it ended up with the lack of suffix unless
> > get_term_name() fails.
> > 
> > The fix patch is below.  Could you check whether it cures the issue?
> 
> This patch does seem to work fine for me, I can see all the mixer
> controls for the usb soundcard/dac.
> 
> For good measure I have also tested with a couple of usb headsets and I
> didn't see anything amiss (they don't have any "Capture Source" controls
> though).
> 
> Thank you for looking into this and fixing it.

Good to hear, I queued the fix to for-linus branch.
I'm going to send a pull request for rc5.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Mixer regression with usb soundcard

2017-12-18 Thread Takashi Iwai
On Mon, 18 Dec 2017 22:56:07 +0100,
Mauro Santos wrote:
> 
> On 18-12-2017 19:30, Takashi Iwai wrote:
> > On Mon, 18 Dec 2017 20:10:44 +0100,
> > Mauro Santos wrote:
> >>
> >> On 18-12-2017 17:50, Jaejoong Kim wrote:
> >>> Mauro,
> >>>
> >>> Could you please try debug patch(I also attach the patch file)?
> >>
> >> With the attached patch I get the following when plugging in the usb dac
> >> directly to a usb3 port:
> >> [   54.391539] usb 1-2: new full-speed USB device number 7 using xhci_hcd
> >> [   54.514996] usb 1-2: device descriptor read/64, error -71
> >> [   54.849808] input: HiFimeDIY Audio HiFimeDIY DAC as
> >> /devices/pci:00/:00:14.0/usb1/1-2/1-2:1.0/0003:1852:7022.0003/input/input20
> >> [   54.850168] hid-generic 0003:1852:7022.0003: input,hidraw2: USB HID
> >> v1.00 Device [HiFimeDIY Audio HiFimeDIY DAC] on usb-:00:14.0-2/input0
> >> [   54.950421] usb 1-2: [DEBUG] nameid:0, len:0
> >> [   54.950426] usb 1-2: [DEBUG] len:3, get_term_name:PCM
> >> [   54.950429] usb 1-2: [11] SU [PCM] items = 2
> >> [   54.950985] usbcore: registered new interface driver snd-usb-audio
> > 
> > Hmm, the driver get the supposedly correct name string here, so I see
> > no flaw, so far.
> > 
> > Could you put the similar debug prints after reverting the commit and
> > compare?  Or, at minimum, you can enable simply the kernel debug
> > prints like below:
> > 
> >   % echo "file sound/usb/mixer.c +p" > 
> > /sys/kernel/debug/dynamic_debug_control
> > 
> > and re-plug the device.
> > 
> > Also, could you attach the output of "amixer contents" on both working
> > and non-working kernels?
> > 
> 
> I have compiled a new kernel where I have reverted the commit and I've
> added the debug output based on your last debug patch. I attach the
> patch that reverts the changes and adds the debug output just in case
> anyone wants to do a sanity check on it (don't mind the indentation I
> think I botched that).
> 
> With the debug patches I get no extra output when echoing to the
> dynamic_debug/control file, I guess that's expected.
> 
> I attach the dmesg and amixer outputs for the case without revert plus
> debug (bad) and revert plus debug (good).
> 
> One change does jump out:
> 
> bad:  usb 1-2: [11] SU [PCM] items = 2
> good: usb 1-2: [11] SU [PCM Capture Source] items = 2

Thanks, that explains what went wrong.  The commit dropped the brace
at the if-line, and it ended up with the lack of suffix unless
get_term_name() fails.

The fix patch is below.  Could you check whether it cures the issue?

Also, Jaejoong, could you check whether it doesn't your device,
either?  I believe it should keep working, but just to be sure.


Takashi

-- 8< --
From: Takashi Iwai 
Subject: [PATCH] ALSA: usb-audio: Fix the missing ctl name suffix at parsing
 SU

The commit 89b89d121ffc ("ALSA: usb-audio: Add check return value for
usb_string()") added the check of the return value from
snd_usb_copy_string_desc(), which is correct per se, but it introduced
a regression.  In the original code, either the "Clock Source",
"Playback Source" or "Capture Source" suffix is added after the
terminal string, while the commit changed it to add the suffix only
when get_term_name() is failing.  It ended up with an incorrect ctl
name like "PCM" instead of "PCM Capture Source".

Also, even the original code has a similar bug: when the ctl name is
generated from snd_usb_copy_string_desc() for the given iSelector, it
also doesn't put the suffix.

This patch addresses these issues: the suffix is added always when no
static mapping is found.  Also the patch tries to put more comments
and cleans up the if/else block for better readability in order to
avoid the same pitfall again.

Fixes: 89b89d121ffc ("ALSA: usb-audio: Add check return value for usb_string()")
Reported-by: Mauro Santos 
Cc: 
Signed-off-by: Takashi Iwai 
---
 sound/usb/mixer.c | 27 ---
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index afc208e1c756..60ebc99ae323 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -2173,20 +2173,25 @@ static int parse_audio_selector_unit(struct mixer_build 
*state, int unitid,
kctl->private_value = (unsigned long)namelist;
kctl->private_free = usb_mixer_selector_elem_free;
 
-   nameid = uac_selector_unit_iSelector(desc);
+   /* check the static mapping table at first */
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
-   if (len)
-

Re: Mixer regression with usb soundcard

2017-12-18 Thread Takashi Iwai
On Mon, 18 Dec 2017 20:10:44 +0100,
Mauro Santos wrote:
> 
> On 18-12-2017 17:50, Jaejoong Kim wrote:
> > Mauro,
> > 
> > Could you please try debug patch(I also attach the patch file)?
> 
> With the attached patch I get the following when plugging in the usb dac
> directly to a usb3 port:
> [   54.391539] usb 1-2: new full-speed USB device number 7 using xhci_hcd
> [   54.514996] usb 1-2: device descriptor read/64, error -71
> [   54.849808] input: HiFimeDIY Audio HiFimeDIY DAC as
> /devices/pci:00/:00:14.0/usb1/1-2/1-2:1.0/0003:1852:7022.0003/input/input20
> [   54.850168] hid-generic 0003:1852:7022.0003: input,hidraw2: USB HID
> v1.00 Device [HiFimeDIY Audio HiFimeDIY DAC] on usb-:00:14.0-2/input0
> [   54.950421] usb 1-2: [DEBUG] nameid:0, len:0
> [   54.950426] usb 1-2: [DEBUG] len:3, get_term_name:PCM
> [   54.950429] usb 1-2: [11] SU [PCM] items = 2
> [   54.950985] usbcore: registered new interface driver snd-usb-audio

Hmm, the driver get the supposedly correct name string here, so I see
no flaw, so far.

Could you put the similar debug prints after reverting the commit and
compare?  Or, at minimum, you can enable simply the kernel debug
prints like below:

  % echo "file sound/usb/mixer.c +p" > /sys/kernel/debug/dynamic_debug_control

and re-plug the device.

Also, could you attach the output of "amixer contents" on both working
and non-working kernels?


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Mixer regression with usb soundcard

2017-12-18 Thread Takashi Iwai
On Mon, 18 Dec 2017 18:05:18 +0100,
Mauro Santos wrote:
> 
> On 18-12-2017 15:45, Takashi Iwai wrote:
> > On Mon, 18 Dec 2017 16:30:13 +0100,
> > Mauro Santos wrote:
> >>
> >> On 18-12-2017 13:53, Takashi Iwai wrote:
> >>> On Mon, 18 Dec 2017 14:44:44 +0100,
> >>> Greg KH wrote:
> >>>>
> >>>> On Sun, Dec 17, 2017 at 06:56:05PM +, Mauro Santos wrote:
> >>>>> I believe this is the right place to report this problem, but if it
> >>>>> isn't please point me in the right direction.
> >>>>
> >>>> Adding the developer of that patch, and the sound maintainer and
> >>>> developers to the thread.
> >>>>
> >>>>> I have noticed that after the update from kernel 4.14.5 to 4.14.6
> >>>>> alsamixer does not show the usual volume controls for my usb soundcard.
> >>>>>
> >>>>> Reverting 3884d12e17ab770aa0f5d4bc65bfbfd006f417fa ALSA: usb-audio: Add
> >>>>> check return value for usb_string() (from linux-stable) makes the
> >>>>> controls come back again with kernel 4.14.6.
> >>> (snip)
> >>>>
> >>>> This is odd, Takashi, I thought we fixed up the problem that if the
> >>>> string was invalid, the code would continue to go on, it's not a "real"
> >>>> error.  Did that not get marked for the stable trees?
> >>>
> >>> Yes, it was marked as stable, and it's odd that the revert of the
> >>> given commit changes the behavior in that way.
> >>>
> >>> Mauro, could you double-check whether reverting the commit really does
> >>> fix it as expected?  If yes, could you put some debug print at the
> >>> part the patch touches, and check which unit id gives len=0 from
> >>> snd_usb_copy_string_desc()?
> >>
> >> I'm sure reverting that patch makes things work as expected. I noticed
> >> the problem after an update and that is the only thing I revert on top
> >> of the kernel provided by the distro (Arch Linux).
> > 
> > Did you revert only one patch, not both patches?
> > Just to be sure.
> 
> I have reverted only one patch.
> 
> >> Alsamixer works fine for the built in soundcard in my laptop, but the
> >> mixer for the usb soundcard was not working so it's specific to usb and
> >> only 2 patches touch the mixer.c file between 4.14.5 and 4.14.6. I've
> >> tried reversing both, one at a time, and only reverting this one
> >> restored the expected behavior.
> >>
> >> Regarding adding the debug print I'm going to need guidance. Without
> >> reverting anything, would adding at line 2178 of sound/usb/mixer.c the
> >> following be enough?
> >>
> >> printk("usbmixdbg: nameid=%d len=%d 
> >> id.name=%s\n",nameid,len,kctl->id.name);
> >>
> >> It would then look like this (minus the line wrapping):
> >> len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
> >> printk("usbmixdbg: nameid=%d len=%d 
> >> id.name=%s\n",nameid,len,kctl->id.name);
> >> if (len)
> > 
> > Well, at that point, there should be no difference.
> > The difference is after that, so what I'd like to see is something
> > like:
> > 
> > --- a/sound/usb/mixer.c
> > +++ b/sound/usb/mixer.c
> > @@ -2175,14 +2175,18 @@ static int parse_audio_selector_unit(struct 
> > mixer_build *state, int unitid,
> >  
> > nameid = uac_selector_unit_iSelector(desc);
> > len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
> > +   pr_info("XXX id=%d, check_mapped_name=%d\n", id, len);
> > if (len)
> > ;
> > -   else if (nameid)
> > +   else if (nameid) {
> > len = snd_usb_copy_string_desc(state, nameid, kctl->id.name,
> >  sizeof(kctl->id.name));
> > -   else
> > +   pr_info("XXX id=%d, copy_string=%d\n", len);
> > +   } else {
> > len = get_term_name(state, &state->oterm,
> > kctl->id.name, sizeof(kctl->id.name), 0);
> > +   pr_info("XXX id=%d, get_term_name=%d\n", len);
> > +   }
> >  
> > if (!len) {
> > strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
> > 
> > 
> > If you see copy_string=0, it means that your hardware reports a bogus
> > entry, and the driver does it correctly.  If ignoring that error
> > really restores the old behavior back, it essentially means that it
> > worked casually in the past...
> 
> I have applied your patch on top of 4.14.7 without reverting anything
> and I was planning to reply only after I had some result but building
> failed (without any errors strangely).
> 
> I took a second look at your patch and I have a (maybe silly/naive)
> question, don't the second and third pr_info calls need an extra
> argument? There are two %d in the string but only one variable (len).

Yeah, sure, of course you need them :)
I haven't tested the patch, but just to give you an idea.
Sorry if you wasted your time due to that.


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Mixer regression with usb soundcard

2017-12-18 Thread Takashi Iwai
On Mon, 18 Dec 2017 17:59:38 +0100,
Jaejoong Kim wrote:
> 
> AudioControl Interface Descriptor:
> bLength 8
> bDescriptorType36
> bDescriptorSubtype  5 (SELECTOR_UNIT)
> bUnitID11
> bNrInPins   2
> baSource( 0)   14
> baSource( 1)5
> iSelector   0
> ^
> 
> >From the lsusb.txt, iSelector is '0' which means
> uac_selector_unit_iSelector() return zero I think.

Yes, and in that case, nameid=0, thus it should go to
get_term_name(), and there must be no difference.
If any difference came from the given commit, it must be nameid!=0,
and yet snd_usb_copy_string_desc(namei) returns an error.

In anyway, another potential fix would be the patch like below.
It covers the case where an error is returned from
snb_usb_copy_string_desc() and doesn't fall back to the default name
resolution.


thanks,

Takashi

--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -656,10 +656,14 @@ static int get_term_name(struct mixer_build *state, 
struct usb_audio_term *iterm
 unsigned char *name, int maxlen, int term_only)
 {
struct iterm_name_combo *names;
+   int len;
 
-   if (iterm->name)
-   return snd_usb_copy_string_desc(state, iterm->name,
+   if (iterm->name) {
+   len = snd_usb_copy_string_desc(state, iterm->name,
name, maxlen);
+   if (len)
+   return len;
+   }
 
/* virtual type - not a real terminal */
if (iterm->type >> 16) {
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Mixer regression with usb soundcard

2017-12-18 Thread Takashi Iwai
On Mon, 18 Dec 2017 16:30:13 +0100,
Mauro Santos wrote:
> 
> On 18-12-2017 13:53, Takashi Iwai wrote:
> > On Mon, 18 Dec 2017 14:44:44 +0100,
> > Greg KH wrote:
> >>
> >> On Sun, Dec 17, 2017 at 06:56:05PM +, Mauro Santos wrote:
> >>> I believe this is the right place to report this problem, but if it
> >>> isn't please point me in the right direction.
> >>
> >> Adding the developer of that patch, and the sound maintainer and
> >> developers to the thread.
> >>
> >>> I have noticed that after the update from kernel 4.14.5 to 4.14.6
> >>> alsamixer does not show the usual volume controls for my usb soundcard.
> >>>
> >>> Reverting 3884d12e17ab770aa0f5d4bc65bfbfd006f417fa ALSA: usb-audio: Add
> >>> check return value for usb_string() (from linux-stable) makes the
> >>> controls come back again with kernel 4.14.6.
> > (snip)
> >>
> >> This is odd, Takashi, I thought we fixed up the problem that if the
> >> string was invalid, the code would continue to go on, it's not a "real"
> >> error.  Did that not get marked for the stable trees?
> > 
> > Yes, it was marked as stable, and it's odd that the revert of the
> > given commit changes the behavior in that way.
> > 
> > Mauro, could you double-check whether reverting the commit really does
> > fix it as expected?  If yes, could you put some debug print at the
> > part the patch touches, and check which unit id gives len=0 from
> > snd_usb_copy_string_desc()?
> 
> I'm sure reverting that patch makes things work as expected. I noticed
> the problem after an update and that is the only thing I revert on top
> of the kernel provided by the distro (Arch Linux).

Did you revert only one patch, not both patches?
Just to be sure.

> Alsamixer works fine for the built in soundcard in my laptop, but the
> mixer for the usb soundcard was not working so it's specific to usb and
> only 2 patches touch the mixer.c file between 4.14.5 and 4.14.6. I've
> tried reversing both, one at a time, and only reverting this one
> restored the expected behavior.
> 
> Regarding adding the debug print I'm going to need guidance. Without
> reverting anything, would adding at line 2178 of sound/usb/mixer.c the
> following be enough?
> 
> printk("usbmixdbg: nameid=%d len=%d id.name=%s\n",nameid,len,kctl->id.name);
> 
> It would then look like this (minus the line wrapping):
> len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
> printk("usbmixdbg: nameid=%d len=%d id.name=%s\n",nameid,len,kctl->id.name);
> if (len)

Well, at that point, there should be no difference.
The difference is after that, so what I'd like to see is something
like:

--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -2175,14 +2175,18 @@ static int parse_audio_selector_unit(struct mixer_build 
*state, int unitid,
 
nameid = uac_selector_unit_iSelector(desc);
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
+   pr_info("XXX id=%d, check_mapped_name=%d\n", id, len);
if (len)
;
-   else if (nameid)
+   else if (nameid) {
len = snd_usb_copy_string_desc(state, nameid, kctl->id.name,
 sizeof(kctl->id.name));
-   else
+   pr_info("XXX id=%d, copy_string=%d\n", len);
+   } else {
len = get_term_name(state, &state->oterm,
kctl->id.name, sizeof(kctl->id.name), 0);
+   pr_info("XXX id=%d, get_term_name=%d\n", len);
+   }
 
if (!len) {
strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));


If you see copy_string=0, it means that your hardware reports a bogus
entry, and the driver does it correctly.  If ignoring that error
really restores the old behavior back, it essentially means that it
worked casually in the past...


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Mixer regression with usb soundcard

2017-12-18 Thread Takashi Iwai
On Mon, 18 Dec 2017 14:44:44 +0100,
Greg KH wrote:
> 
> On Sun, Dec 17, 2017 at 06:56:05PM +, Mauro Santos wrote:
> > I believe this is the right place to report this problem, but if it
> > isn't please point me in the right direction.
> 
> Adding the developer of that patch, and the sound maintainer and
> developers to the thread.
> 
> > I have noticed that after the update from kernel 4.14.5 to 4.14.6
> > alsamixer does not show the usual volume controls for my usb soundcard.
> > 
> > Reverting 3884d12e17ab770aa0f5d4bc65bfbfd006f417fa ALSA: usb-audio: Add
> > check return value for usb_string() (from linux-stable) makes the
> > controls come back again with kernel 4.14.6.
(snip)
> 
> This is odd, Takashi, I thought we fixed up the problem that if the
> string was invalid, the code would continue to go on, it's not a "real"
> error.  Did that not get marked for the stable trees?

Yes, it was marked as stable, and it's odd that the revert of the
given commit changes the behavior in that way.

Mauro, could you double-check whether reverting the commit really does
fix it as expected?  If yes, could you put some debug print at the
part the patch touches, and check which unit id gives len=0 from
snd_usb_copy_string_desc()?


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 3/9] ALSA: caiaq: Add a sanity check for invalid EPs

2017-10-11 Thread Takashi Iwai
On Wed, 11 Oct 2017 16:49:10 +0200,
Johan Hovold wrote:
> 
> On Wed, Oct 11, 2017 at 04:40:36PM +0200, Takashi Iwai wrote:
> > On Wed, 11 Oct 2017 16:20:31 +0200,
> > Johan Hovold wrote:
> 
> > > Unrelated to this patch, but this driver fails to kill the ep1_in_urb
> > > (which is submitted in this function) in case of later probe errors.
> > > This can lead to use-after-free or crashes in the completion callback.
> > 
> > Yes, a good catch.  Below is the fix patch.
> 
> > -- 8< --
> > From: Takashi Iwai 
> > Subject: [PATCH] ALSA: caiaq: Fix stray URB at probe error path
> > 
> > caiaq driver doesn't kill the URB properly at its error path during
> > the probe, which may lead to a use-after-free error later.  This patch
> > addresses it.
> > 
> > Reported-by: Johan Hovold 
> > Signed-off-by: Takashi Iwai 
> 
> Looks good to me:
> 
> Reviewed-by: Johan Hovold 

Thanks.  It's rather a material for for-linus with Cc to stable, so
marked it and queued.


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 4/9] ALSA: line6: Add a sanity check for invalid EPs

2017-10-11 Thread Takashi Iwai
On Wed, 11 Oct 2017 16:52:09 +0200,
Johan Hovold wrote:
> 
> On Wed, Oct 11, 2017 at 04:45:16PM +0200, Takashi Iwai wrote:
> > On Wed, 11 Oct 2017 16:28:37 +0200,
> > Johan Hovold wrote:
> > > 
> > > On Wed, Oct 11, 2017 at 12:36:41PM +0200, Takashi Iwai wrote:
> > > > As syzkaller spotted, currently line6 drivers submit a URB with the
> > > > fixed EP without checking whether it's actually available, which may
> > > > result in a kernel warning like:
> > > >   usb 1-1: BOGUS urb xfer, pipe 3 != type 1
> > > >   [ cut here ]
> > > >   WARNING: CPU: 0 PID: 24 at drivers/usb/core/urb.c:449
> > > >   usb_submit_urb+0xf8a/0x11d0
> > > >   Modules linked in:
> > > >   CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 
> > > > 4.14.0-rc2-42613-g1488251d1a98 #238
> > > >   Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 
> > > > 01/01/2011
> > > >   Workqueue: usb_hub_wq hub_event
> > > >   Call Trace:
> > > >line6_start_listen+0x55f/0x9e0 sound/usb/line6/driver.c:82
> > > >line6_init_cap_control sound/usb/line6/driver.c:690
> > > >line6_probe+0x7c9/0x1310 sound/usb/line6/driver.c:764
> > > >podhd_probe+0x64/0x70 sound/usb/line6/podhd.c:474
> > > >usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
> > > >
> > > > 
> > > > This patch adds a sanity check of validity of EPs at the device
> > > > initialization phase for avoiding the call with an invalid EP.
> > > > 
> > > > Reported-by: Andrey Konovalov 
> > > > Tested-by: Andrey Konovalov 
> > > > Signed-off-by: Takashi Iwai 
> > > > ---
> > > >  sound/usb/line6/driver.c | 7 +++
> > > >  1 file changed, 7 insertions(+)
> > > > 
> > > > diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
> > > > index 0ff5a7d2e19f..0da6f68761e3 100644
> > > > --- a/sound/usb/line6/driver.c
> > > > +++ b/sound/usb/line6/driver.c
> > > > @@ -78,6 +78,13 @@ static int line6_start_listen(struct usb_line6 
> > > > *line6)
> > > > line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
> > > > line6_data_received, line6);
> > > > }
> > > > +
> > > > +   /* sanity checks of EP before actually submitting */
> > > > +   if (usb_urb_ep_type_check(line6->urb_listen)) {
> > > > +   dev_err(line6->ifcdev, "invalid control EP\n");
> > > > +   return -EINVAL;
> > > > +   }
> > > 
> > > You're now doing this check twice (here and in usb_submit_urb) every
> > > time this URB is submitted rather just checking it once in probe.
> > > 
> > > Seems like a quick band-aid to me.
> > 
> > Yes, it is :)
> > 
> > We may split line6_start_listen() to two functions, one for
> > initializing URBs and another for submission, but it'll be more codes
> > and the check is fairly cheap.  So again it's a question whether
> > easier to read or to get minor optimization.
> 
> I'd say it's also a question about long-term maintainability. Those
> quick band-aids tend to keep piling up over time.

The codes we've touched are mostly for device-specific drivers or
quirk codes, and they are basically finished ones, so I guess it's a
kind of once-off fix.  Let's see.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 9/9] ALSA: line6: Add yet more sanity checks for invalid EPs

2017-10-11 Thread Takashi Iwai
On Wed, 11 Oct 2017 16:39:52 +0200,
Johan Hovold wrote:
> 
> On Wed, Oct 11, 2017 at 12:36:46PM +0200, Takashi Iwai wrote:
> > There are a few other places calling usb_submit_urb() with the URB
> > composed from the fixed endpoint without validation.  For avoiding the
> > spurious kernel warnings, add the sanity checks to appropriate
> > places.
> > 
> > Signed-off-by: Takashi Iwai 
> > ---
> >  sound/usb/line6/driver.c | 23 +++
> >  sound/usb/line6/midi.c   | 17 +++--
> >  2 files changed, 26 insertions(+), 14 deletions(-)
> > 
> > diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
> > index 0da6f68761e3..7c682b219584 100644
> > --- a/sound/usb/line6/driver.c
> > +++ b/sound/usb/line6/driver.c
> > @@ -175,17 +175,24 @@ static int line6_send_raw_message_async_part(struct 
> > message *msg,
> > }
> >  
> > msg->done += bytes;
> > -   retval = usb_submit_urb(urb, GFP_ATOMIC);
> >  
> > -   if (retval < 0) {
> > -   dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n",
> > -   __func__, retval);
> > -   usb_free_urb(urb);
> > -   kfree(msg);
> > -   return retval;
> > -   }
> > +   /* sanity checks of EP before actually submitting */
> > +   retval = usb_urb_ep_type_check(urb);
> > +   if (retval < 0)
> > +   goto error;
> 
> This also seems like something which should have been done once at urb
> allocation time, rather than on every submission (just like the URB
> initialisation should have been).

Yes, ideally this would be done in the init time.  But the code
allocates a URB temporarily and fills it depending on the board
configuration, so it's not too trivial to do that without a big code
refactoring.  So the current patch is merely hardening a bit.
For obtaining the ideal code flow, we'd need the whole code
restructuring in anyway for this driver; currently it's too messy.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 4/9] ALSA: line6: Add a sanity check for invalid EPs

2017-10-11 Thread Takashi Iwai
On Wed, 11 Oct 2017 16:28:37 +0200,
Johan Hovold wrote:
> 
> On Wed, Oct 11, 2017 at 12:36:41PM +0200, Takashi Iwai wrote:
> > As syzkaller spotted, currently line6 drivers submit a URB with the
> > fixed EP without checking whether it's actually available, which may
> > result in a kernel warning like:
> >   usb 1-1: BOGUS urb xfer, pipe 3 != type 1
> >   [ cut here ]
> >   WARNING: CPU: 0 PID: 24 at drivers/usb/core/urb.c:449
> >   usb_submit_urb+0xf8a/0x11d0
> >   Modules linked in:
> >   CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 
> > 4.14.0-rc2-42613-g1488251d1a98 #238
> >   Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 
> > 01/01/2011
> >   Workqueue: usb_hub_wq hub_event
> >   Call Trace:
> >line6_start_listen+0x55f/0x9e0 sound/usb/line6/driver.c:82
> >line6_init_cap_control sound/usb/line6/driver.c:690
> >line6_probe+0x7c9/0x1310 sound/usb/line6/driver.c:764
> >podhd_probe+0x64/0x70 sound/usb/line6/podhd.c:474
> >usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
> >
> > 
> > This patch adds a sanity check of validity of EPs at the device
> > initialization phase for avoiding the call with an invalid EP.
> > 
> > Reported-by: Andrey Konovalov 
> > Tested-by: Andrey Konovalov 
> > Signed-off-by: Takashi Iwai 
> > ---
> >  sound/usb/line6/driver.c | 7 +++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
> > index 0ff5a7d2e19f..0da6f68761e3 100644
> > --- a/sound/usb/line6/driver.c
> > +++ b/sound/usb/line6/driver.c
> > @@ -78,6 +78,13 @@ static int line6_start_listen(struct usb_line6 *line6)
> > line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
> > line6_data_received, line6);
> > }
> > +
> > +   /* sanity checks of EP before actually submitting */
> > +   if (usb_urb_ep_type_check(line6->urb_listen)) {
> > +   dev_err(line6->ifcdev, "invalid control EP\n");
> > +   return -EINVAL;
> > +   }
> 
> You're now doing this check twice (here and in usb_submit_urb) every
> time this URB is submitted rather just checking it once in probe.
> 
> Seems like a quick band-aid to me.

Yes, it is :)

We may split line6_start_listen() to two functions, one for
initializing URBs and another for submission, but it'll be more codes
and the check is fairly cheap.  So again it's a question whether
easier to read or to get minor optimization.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 6/9] ALSA: usx2y: Add sanity checks for invalid EPs

2017-10-11 Thread Takashi Iwai
On Wed, 11 Oct 2017 16:33:37 +0200,
Johan Hovold wrote:
> 
> On Wed, Oct 11, 2017 at 12:36:43PM +0200, Takashi Iwai wrote:
> > usx2y driver sets up URBs containing the fixed endpoints without
> > validation.  This may end up with an oops-like kernel warning when
> > submitted.
> > 
> > For avoiding it, this patch adds the calls of the new sanity-check
> > helper for URBs.
> > 
> > Signed-off-by: Takashi Iwai 
> > ---
> >  sound/usb/usx2y/usbusx2y.c  | 8 
> >  sound/usb/usx2y/usbusx2yaudio.c | 3 +++
> >  2 files changed, 11 insertions(+)
> > 
> > diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
> > index 4569c0efac0a..55a631ccfa25 100644
> > --- a/sound/usb/usx2y/usbusx2y.c
> > +++ b/sound/usb/usx2y/usbusx2y.c
> > @@ -244,6 +244,9 @@ static void i_usX2Y_In04Int(struct urb *urb)
> >   
> > usb_sndbulkpipe(usX2Y->dev, 0x04), &p4out->val.vol,
> >   p4out->type 
> > == eLT_Light ? sizeof(struct us428_lights) : 5,
> >   
> > i_usX2Y_Out04Int, usX2Y);
> > +   err = 
> > usb_urb_ep_type_check(usX2Y->AS04.urb[j]);
> > +   if (err < 0)
> > +   break;
> 
> It doesn't make much sense to add this check to the completion handler,
> where, if you ever get here, you already know that endpoint check at
> first submission succeeded.

OK, this one can be dropped while the latter one is kept.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 3/9] ALSA: caiaq: Add a sanity check for invalid EPs

2017-10-11 Thread Takashi Iwai
On Wed, 11 Oct 2017 16:20:31 +0200,
Johan Hovold wrote:
> 
> On Wed, Oct 11, 2017 at 12:36:40PM +0200, Takashi Iwai wrote:
> > As syzkaller spotted, currently caiaq driver submits a URB with the
> > fixed EP without checking whether it's actually available, which may
> > result in a kernel warning like:
> >   usb 1-1: BOGUS urb xfer, pipe 3 != type 1
> >   [ cut here ]
> >   WARNING: CPU: 1 PID: 1150 at drivers/usb/core/urb.c:449
> >   usb_submit_urb+0xf8a/0x11d0
> >   Modules linked in:
> >   CPU: 1 PID: 1150 Comm: kworker/1:1 Not tainted
> >   4.14.0-rc2-42660-g24b7bd59eec0 #277
> >   Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 
> > 01/01/2011
> >   Workqueue: usb_hub_wq hub_event
> >   Call Trace:
> >init_card sound/usb/caiaq/device.c:467
> >snd_probe+0x81c/0x1150 sound/usb/caiaq/device.c:525
> >usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
> >
> > 
> > This patch adds a sanity check of validity of EPs at the device
> > initialization phase for avoiding the call with an invalid EP.
> > 
> > Reported-by: Andrey Konovalov 
> > Tested-by: Andrey Konovalov 
> > Signed-off-by: Takashi Iwai 
> > ---
> >  sound/usb/caiaq/device.c | 7 +++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
> > index 0fb6b1b79261..a29674bf96e5 100644
> > --- a/sound/usb/caiaq/device.c
> > +++ b/sound/usb/caiaq/device.c
> > @@ -461,6 +461,13 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
> >   cdev->midi_out_buf, EP1_BUFSIZE,
> >   snd_usb_caiaq_midi_output_done, cdev);
> >  
> > +   /* sanity checks of EPs before actually submitting */
> > +   if (usb_urb_ep_type_check(&cdev->ep1_in_urb) ||
> > +   usb_urb_ep_type_check(&cdev->midi_out_urb)) {
> > +   dev_err(dev, "invalid EPs\n");
> > +   return -EINVAL;
> > +   }
> > +
> 
> Unrelated to this patch, but this driver fails to kill the ep1_in_urb
> (which is submitted in this function) in case of later probe errors.
> This can lead to use-after-free or crashes in the completion callback.

Yes, a good catch.  Below is the fix patch.


thanks,

Takashi

-- 8< --
From: Takashi Iwai 
Subject: [PATCH] ALSA: caiaq: Fix stray URB at probe error path

caiaq driver doesn't kill the URB properly at its error path during
the probe, which may lead to a use-after-free error later.  This patch
addresses it.

Reported-by: Johan Hovold 
Signed-off-by: Takashi Iwai 
---
 sound/usb/caiaq/device.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index a29674bf96e5..d55ca48de3ea 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -476,10 +476,12 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
 
err = snd_usb_caiaq_send_command(cdev, EP1_CMD_GET_DEVICE_INFO, NULL, 
0);
if (err)
-   return err;
+   goto err_kill_urb;
 
-   if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ))
-   return -ENODEV;
+   if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) 
{
+   err = -ENODEV;
+   goto err_kill_urb;
+   }
 
usb_string(usb_dev, usb_dev->descriptor.iManufacturer,
   cdev->vendor_name, CAIAQ_USB_STR_LEN);
@@ -514,6 +516,10 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
 
setup_card(cdev);
return 0;
+
+ err_kill_urb:
+   usb_kill_urb(&cdev->ep1_in_urb);
+   return err;
 }
 
 static int snd_probe(struct usb_interface *intf,
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/9] usb: core: Add a helper function to check the validity of EP type in URB

2017-10-11 Thread Takashi Iwai
On Wed, 11 Oct 2017 16:14:55 +0200,
Johan Hovold wrote:
> 
> On Wed, Oct 11, 2017 at 12:36:38PM +0200, Takashi Iwai wrote:
> > This patch adds a new helper function to perform a sanity check of the
> > given URB to see whether it contains a valid endpoint.  It's a light-
> > weight version of what usb_submit_urb() does, but without the kernel
> > warning followed by the stack trace, just returns an error code.
> > 
> > Especially for a driver that doesn't parse the descriptor but fills
> > the URB with the fixed endpoint (e.g. some quirks for non-compliant
> > devices), this kind of check is preferable at the probe phase before
> > actually submitting the urb.
> > 
> > Tested-by: Andrey Konovalov 
> > Signed-off-by: Takashi Iwai 
> > ---
> > v1->v2:
> > * Fix function name typos
> > * Call usb_urb_ep_type_check() in usb_submit_urb(), too
> > 
> >  drivers/usb/core/urb.c | 30 ++
> >  include/linux/usb.h|  2 ++
> >  2 files changed, 28 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
> > index 47903d510955..8b800e34407b 100644
> > --- a/drivers/usb/core/urb.c
> > +++ b/drivers/usb/core/urb.c
> > @@ -187,6 +187,31 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
> >  
> >  /*---*/
> >  
> > +static const int pipetypes[4] = {
> > +   PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
> > +};
> 
> No this one is no longer used outside of usb_urb_ep_type_check().

It is used in the error message, so I kept it here.


> > +
> > +/**
> > + * usb_urb_ep_type_check - sanity check of endpoint in the given urb
> > + * @urb: urb to be checked
> > + *
> > + * This performs a light-weight sanity check for the endpoint in the
> > + * given urb.  It returns 0 if the urb contains a valid endpoint, otherwise
> > + * a negative error code.
> > + */
> > +int usb_urb_ep_type_check(const struct urb *urb)
> > +{
> > +   const struct usb_host_endpoint *ep;
> > +
> > +   ep = usb_pipe_endpoint(urb->dev, urb->pipe);
> > +   if (!ep)
> > +   return -EINVAL;
> 
> And I know Greg asked you to call this function from usb_submit_urb()
> which have already done the above ep-lookup once. Maybe not that many
> extra cycles, but still seems unnecessary to me.

Yeah, we can do micro-optimization later if needed, e.g. splitting the
function.  It's a question of balance between code optimization and
readability...


thanks,

Takashi

> > +   if (usb_pipetype(urb->pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
> > +   return -EINVAL;
> > +   return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(usb_urb_ep_type_check);
> > +
> >  /**
> >   * usb_submit_urb - issue an asynchronous transfer request for an endpoint
> >   * @urb: pointer to the urb describing the request
> > @@ -326,9 +351,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
> >   */
> >  int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
> >  {
> > -   static int  pipetypes[4] = {
> > -   PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
> > -   };
> > int xfertype, max;
> > struct usb_device   *dev;
> > struct usb_host_endpoint*ep;
> > @@ -444,7 +466,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
> >  */
> >  
> > /* Check that the pipe's type matches the endpoint's type */
> > -   if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
> > +   if (usb_urb_ep_type_check(urb))
> > dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
> > usb_pipetype(urb->pipe), pipetypes[xfertype]);
> 
> Johan
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 0/9] sound: Add sanity checks for invalid EPs

2017-10-11 Thread Takashi Iwai
On Wed, 11 Oct 2017 15:03:29 +0200,
Greg KH wrote:
> 
> On Wed, Oct 11, 2017 at 12:36:37PM +0200, Takashi Iwai wrote:
> > Hi,
> > 
> > this is a revised patch set to cover the codes that may submit URBs
> > containing invalid EPs without validation, which result in the kernel
> > warning from the USB core.  The first patch adds a new helper for
> > simplifying the EP check, and the rest applies it at needed places.
> > 
> > The original issues were spotted by syzkaller, and I put a few others
> > for covering more similar cases.
> > 
> > The only updated code in v2 is about the first patch to add
> > usb_urb_ep_type_check() helper (in addition to tested-by tag from
> > Andrey).  Typos were fixed and it's called also from usb_submit_urb()
> > as Greg suggested, too.
> > 
> > USB devs: does this look OK now?
> > 
> > If yes, and if I get acks, I can take the patches to sound tree.  Or I
> > don't mind if you take all to usb tree, too.  Or maybe better, I'll
> > prepare an immutable branch based on 4.4.14-rc (rc4 for now) in case
> > you want to pull into both trees.  Let me know your wish.
> 
> Whole series looks good to me, feel free to take them in your tree if
> that's the easiest:
> 
> Acked-by: Greg Kroah-Hartman 
> 
> No need for a branch, merges in this area should be rare...

Great, thanks for a quick review!
I'll merge through sound git tree.


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 6/9] ALSA: usx2y: Add sanity checks for invalid EPs

2017-10-11 Thread Takashi Iwai
usx2y driver sets up URBs containing the fixed endpoints without
validation.  This may end up with an oops-like kernel warning when
submitted.

For avoiding it, this patch adds the calls of the new sanity-check
helper for URBs.

Signed-off-by: Takashi Iwai 
---
 sound/usb/usx2y/usbusx2y.c  | 8 
 sound/usb/usx2y/usbusx2yaudio.c | 3 +++
 2 files changed, 11 insertions(+)

diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index 4569c0efac0a..55a631ccfa25 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -244,6 +244,9 @@ static void i_usX2Y_In04Int(struct urb *urb)
  
usb_sndbulkpipe(usX2Y->dev, 0x04), &p4out->val.vol,
  p4out->type 
== eLT_Light ? sizeof(struct us428_lights) : 5,
  
i_usX2Y_Out04Int, usX2Y);
+   err = 
usb_urb_ep_type_check(usX2Y->AS04.urb[j]);
+   if (err < 0)
+   break;
err = 
usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC);
us428ctls->p4outSent = send;
break;
@@ -279,6 +282,9 @@ int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y)
usX2Y->AS04.buffer + 
URB_DataLen_AsyncSeq*i, 0,
i_usX2Y_Out04Int, usX2Y
);
+   err = usb_urb_ep_type_check(usX2Y->AS04.urb[i]);
+   if (err < 0)
+   break;
}
return err;
 }
@@ -298,6 +304,8 @@ int usX2Y_In04_init(struct usX2Ydev *usX2Y)
 usX2Y->In04Buf, 21,
 i_usX2Y_In04Int, usX2Y,
 10);
+   if (usb_urb_ep_type_check(usX2Y->In04urb))
+   return -EINVAL;
return usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
 }
 
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index f93b355756e6..345e439aa95b 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -677,6 +677,9 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate)
usb_fill_bulk_urb(us->urb[i], usX2Y->dev, 
usb_sndbulkpipe(usX2Y->dev, 4),
  usbdata + i, 2, i_usX2Y_04Int, usX2Y);
}
+   err = usb_urb_ep_type_check(us->urb[0]);
+   if (err < 0)
+   goto cleanup;
us->submitted = 0;
us->len =   NOOF_SETRATE_URBS;
usX2Y->US04 =   us;
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 7/9] ALSA: hiface: Add sanity checks for invalid EPs

2017-10-11 Thread Takashi Iwai
hiface usb-audio driver sets up URBs containing the fixed endpoints
without validation.  This may end up with an oops-like kernel warning
when submitted.

For avoiding it, this patch adds the calls of the new sanity-check
helper for URBs.

Signed-off-by: Takashi Iwai 
---
 sound/usb/hiface/pcm.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c
index 175d8d6b7f59..396c317115b1 100644
--- a/sound/usb/hiface/pcm.c
+++ b/sound/usb/hiface/pcm.c
@@ -541,6 +541,8 @@ static int hiface_pcm_init_urb(struct pcm_urb *urb,
usb_fill_bulk_urb(&urb->instance, chip->dev,
  usb_sndbulkpipe(chip->dev, ep), (void *)urb->buffer,
  PCM_PACKET_SIZE, handler, urb);
+   if (usb_urb_ep_type_check(&urb->instance))
+   return -EINVAL;
init_usb_anchor(&urb->submitted);
 
return 0;
@@ -599,9 +601,12 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 
extra_freq)
mutex_init(&rt->stream_mutex);
spin_lock_init(&rt->playback.lock);
 
-   for (i = 0; i < PCM_N_URBS; i++)
-   hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
+   for (i = 0; i < PCM_N_URBS; i++) {
+   ret = hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
hiface_pcm_out_urb_handler);
+   if (ret < 0)
+   return ret;
+   }
 
ret = snd_pcm_new(chip->card, "USB-SPDIF Audio", 0, 1, 0, &pcm);
if (ret < 0) {
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 5/9] ALSA: usb-audio: Add sanity checks for invalid EPs

2017-10-11 Thread Takashi Iwai
USB-audio driver may set up a URB containing the fixed EP without
validating its presence for some non-class-compliant devices.  This
may end up with an oops-like kernel warning when submitted.

For avoiding it, this patch adds the call of the new sanity-check
helper for URBs.  The checks are needed only for MIDI I/O as the other
places have already some other checks.

Signed-off-by: Takashi Iwai 
---
 sound/usb/midi.c | 38 ++
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index a92e2b2a91ec..7ab25de5ca0a 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -1282,6 +1282,7 @@ static int snd_usbmidi_in_endpoint_create(struct 
snd_usb_midi *umidi,
unsigned int pipe;
int length;
unsigned int i;
+   int err;
 
rep->in = NULL;
ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -1292,8 +1293,8 @@ static int snd_usbmidi_in_endpoint_create(struct 
snd_usb_midi *umidi,
for (i = 0; i < INPUT_URBS; ++i) {
ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
if (!ep->urbs[i]) {
-   snd_usbmidi_in_endpoint_delete(ep);
-   return -ENOMEM;
+   err = -ENOMEM;
+   goto error;
}
}
if (ep_info->in_interval)
@@ -1305,8 +1306,8 @@ static int snd_usbmidi_in_endpoint_create(struct 
snd_usb_midi *umidi,
buffer = usb_alloc_coherent(umidi->dev, length, GFP_KERNEL,
&ep->urbs[i]->transfer_dma);
if (!buffer) {
-   snd_usbmidi_in_endpoint_delete(ep);
-   return -ENOMEM;
+   err = -ENOMEM;
+   goto error;
}
if (ep_info->in_interval)
usb_fill_int_urb(ep->urbs[i], umidi->dev,
@@ -1318,10 +1319,20 @@ static int snd_usbmidi_in_endpoint_create(struct 
snd_usb_midi *umidi,
  pipe, buffer, length,
  snd_usbmidi_in_urb_complete, ep);
ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+   err = usb_urb_ep_type_check(ep->urbs[i]);
+   if (err < 0) {
+   dev_err(&umidi->dev->dev, "invalid MIDI in EP %x\n",
+   ep_info->in_ep);
+   goto error;
+   }
}
 
rep->in = ep;
return 0;
+
+ error:
+   snd_usbmidi_in_endpoint_delete(ep);
+   return -ENOMEM;
 }
 
 /*
@@ -1357,6 +1368,7 @@ static int snd_usbmidi_out_endpoint_create(struct 
snd_usb_midi *umidi,
unsigned int i;
unsigned int pipe;
void *buffer;
+   int err;
 
rep->out = NULL;
ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -1367,8 +1379,8 @@ static int snd_usbmidi_out_endpoint_create(struct 
snd_usb_midi *umidi,
for (i = 0; i < OUTPUT_URBS; ++i) {
ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ep->urbs[i].urb) {
-   snd_usbmidi_out_endpoint_delete(ep);
-   return -ENOMEM;
+   err = -ENOMEM;
+   goto error;
}
ep->urbs[i].ep = ep;
}
@@ -1406,8 +1418,8 @@ static int snd_usbmidi_out_endpoint_create(struct 
snd_usb_midi *umidi,
ep->max_transfer, GFP_KERNEL,
&ep->urbs[i].urb->transfer_dma);
if (!buffer) {
-   snd_usbmidi_out_endpoint_delete(ep);
-   return -ENOMEM;
+   err = -ENOMEM;
+   goto error;
}
if (ep_info->out_interval)
usb_fill_int_urb(ep->urbs[i].urb, umidi->dev,
@@ -1419,6 +1431,12 @@ static int snd_usbmidi_out_endpoint_create(struct 
snd_usb_midi *umidi,
  pipe, buffer, ep->max_transfer,
  snd_usbmidi_out_urb_complete,
  &ep->urbs[i]);
+   err = usb_urb_ep_type_check(ep->urbs[i].urb);
+   if (err < 0) {
+   dev_err(&umidi->dev->dev, "invalid MIDI out EP %x\n",
+   ep_info->out_ep);
+   goto error;
+   }
ep->urbs[i].urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
}
 
@@ -1437,6 +1455,10 @@ static int snd_usbmidi_out_endpoint_create(struct 
snd_usb_midi *umidi,
 
rep->out = ep;
return 0;
+
+ error:
+   snd_usbmidi_out_endpoint

[PATCH v2 2/9] ALSA: bcd2000: Add a sanity check for invalid EPs

2017-10-11 Thread Takashi Iwai
As syzkaller spotted, currently bcd2000 driver submits a URB with the
fixed EP without checking whether it's actually available, which may
result in a kernel warning like:
  usb 1-1: BOGUS urb xfer, pipe 1 != type 3
  [ cut here ]
  WARNING: CPU: 0 PID: 1846 at drivers/usb/core/urb.c:449
  usb_submit_urb+0xf8a/0x11d0
  Modules linked in:
  CPU: 0 PID: 1846 Comm: kworker/0:2 Not tainted
  4.14.0-rc2-42613-g1488251d1a98 #238
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
  Workqueue: usb_hub_wq hub_event
  Call Trace:
   bcd2000_init_device sound/usb/bcd2000/bcd2000.c:289
   bcd2000_init_midi sound/usb/bcd2000/bcd2000.c:345
   bcd2000_probe+0xe64/0x19e0 sound/usb/bcd2000/bcd2000.c:406
   usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
   

This patch adds a sanity check of validity of EPs at the device
initialization phase for avoiding the call with an invalid EP.

Reported-by: Andrey Konovalov 
Tested-by: Andrey Konovalov 
Signed-off-by: Takashi Iwai 
---
 sound/usb/bcd2000/bcd2000.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c
index 7371e5b06035..a6408209d7f1 100644
--- a/sound/usb/bcd2000/bcd2000.c
+++ b/sound/usb/bcd2000/bcd2000.c
@@ -342,6 +342,13 @@ static int bcd2000_init_midi(struct bcd2000 *bcd2k)
bcd2k->midi_out_buf, BUFSIZE,
bcd2000_output_complete, bcd2k, 1);
 
+   /* sanity checks of EPs before actually submitting */
+   if (usb_urb_ep_type_check(bcd2k->midi_in_urb) ||
+   usb_urb_ep_type_check(bcd2k->midi_out_urb)) {
+   dev_err(&bcd2k->dev->dev, "invalid MIDI EP\n");
+   return -EINVAL;
+   }
+
bcd2000_init_device(bcd2k);
 
return 0;
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 4/9] ALSA: line6: Add a sanity check for invalid EPs

2017-10-11 Thread Takashi Iwai
As syzkaller spotted, currently line6 drivers submit a URB with the
fixed EP without checking whether it's actually available, which may
result in a kernel warning like:
  usb 1-1: BOGUS urb xfer, pipe 3 != type 1
  [ cut here ]
  WARNING: CPU: 0 PID: 24 at drivers/usb/core/urb.c:449
  usb_submit_urb+0xf8a/0x11d0
  Modules linked in:
  CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 4.14.0-rc2-42613-g1488251d1a98 
#238
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
  Workqueue: usb_hub_wq hub_event
  Call Trace:
   line6_start_listen+0x55f/0x9e0 sound/usb/line6/driver.c:82
   line6_init_cap_control sound/usb/line6/driver.c:690
   line6_probe+0x7c9/0x1310 sound/usb/line6/driver.c:764
   podhd_probe+0x64/0x70 sound/usb/line6/podhd.c:474
   usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
   

This patch adds a sanity check of validity of EPs at the device
initialization phase for avoiding the call with an invalid EP.

Reported-by: Andrey Konovalov 
Tested-by: Andrey Konovalov 
Signed-off-by: Takashi Iwai 
---
 sound/usb/line6/driver.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 0ff5a7d2e19f..0da6f68761e3 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -78,6 +78,13 @@ static int line6_start_listen(struct usb_line6 *line6)
line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
line6_data_received, line6);
}
+
+   /* sanity checks of EP before actually submitting */
+   if (usb_urb_ep_type_check(line6->urb_listen)) {
+   dev_err(line6->ifcdev, "invalid control EP\n");
+   return -EINVAL;
+   }
+
line6->urb_listen->actual_length = 0;
err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC);
return err;
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 0/9] sound: Add sanity checks for invalid EPs

2017-10-11 Thread Takashi Iwai
Hi,

this is a revised patch set to cover the codes that may submit URBs
containing invalid EPs without validation, which result in the kernel
warning from the USB core.  The first patch adds a new helper for
simplifying the EP check, and the rest applies it at needed places.

The original issues were spotted by syzkaller, and I put a few others
for covering more similar cases.

The only updated code in v2 is about the first patch to add
usb_urb_ep_type_check() helper (in addition to tested-by tag from
Andrey).  Typos were fixed and it's called also from usb_submit_urb()
as Greg suggested, too.

USB devs: does this look OK now?

If yes, and if I get acks, I can take the patches to sound tree.  Or I
don't mind if you take all to usb tree, too.  Or maybe better, I'll
prepare an immutable branch based on 4.4.14-rc (rc4 for now) in case
you want to pull into both trees.  Let me know your wish.


thanks,

Takashi

===

Takashi Iwai (9):
  usb: core: Add a helper function to check the validity of EP type in
URB
  ALSA: bcd2000: Add a sanity check for invalid EPs
  ALSA: caiaq: Add a sanity check for invalid EPs
  ALSA: line6: Add a sanity check for invalid EPs
  ALSA: usb-audio: Add sanity checks for invalid EPs
  ALSA: usx2y: Add sanity checks for invalid EPs
  ALSA: hiface: Add sanity checks for invalid EPs
  ALSA: caiaq: Add yet more sanity checks for invalid EPs
  ALSA: line6: Add yet more sanity checks for invalid EPs

 drivers/usb/core/urb.c  | 30 ++
 include/linux/usb.h |  2 ++
 sound/usb/bcd2000/bcd2000.c |  7 +++
 sound/usb/caiaq/device.c|  7 +++
 sound/usb/caiaq/input.c |  9 +
 sound/usb/hiface/pcm.c  |  9 +++--
 sound/usb/line6/driver.c| 30 ++
 sound/usb/line6/midi.c  | 17 +++--
 sound/usb/midi.c| 38 ++
 sound/usb/usx2y/usbusx2y.c  |  8 
 sound/usb/usx2y/usbusx2yaudio.c |  3 +++
 11 files changed, 132 insertions(+), 28 deletions(-)

-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 9/9] ALSA: line6: Add yet more sanity checks for invalid EPs

2017-10-11 Thread Takashi Iwai
There are a few other places calling usb_submit_urb() with the URB
composed from the fixed endpoint without validation.  For avoiding the
spurious kernel warnings, add the sanity checks to appropriate
places.

Signed-off-by: Takashi Iwai 
---
 sound/usb/line6/driver.c | 23 +++
 sound/usb/line6/midi.c   | 17 +++--
 2 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 0da6f68761e3..7c682b219584 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -175,17 +175,24 @@ static int line6_send_raw_message_async_part(struct 
message *msg,
}
 
msg->done += bytes;
-   retval = usb_submit_urb(urb, GFP_ATOMIC);
 
-   if (retval < 0) {
-   dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n",
-   __func__, retval);
-   usb_free_urb(urb);
-   kfree(msg);
-   return retval;
-   }
+   /* sanity checks of EP before actually submitting */
+   retval = usb_urb_ep_type_check(urb);
+   if (retval < 0)
+   goto error;
+
+   retval = usb_submit_urb(urb, GFP_ATOMIC);
+   if (retval < 0)
+   goto error;
 
return 0;
+
+ error:
+   dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n",
+   __func__, retval);
+   usb_free_urb(urb);
+   kfree(msg);
+   return retval;
 }
 
 /*
diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c
index 1d3a23b02d68..6d7cde56a355 100644
--- a/sound/usb/line6/midi.c
+++ b/sound/usb/line6/midi.c
@@ -130,16 +130,21 @@ static int send_midi_async(struct usb_line6 *line6, 
unsigned char *data,
 transfer_buffer, length, midi_sent, line6,
 line6->interval);
urb->actual_length = 0;
-   retval = usb_submit_urb(urb, GFP_ATOMIC);
+   retval = usb_urb_ep_type_check(urb);
+   if (retval < 0)
+   goto error;
 
-   if (retval < 0) {
-   dev_err(line6->ifcdev, "usb_submit_urb failed\n");
-   usb_free_urb(urb);
-   return retval;
-   }
+   retval = usb_submit_urb(urb, GFP_ATOMIC);
+   if (retval < 0)
+   goto error;
 
++line6->line6midi->num_active_send_urbs;
return 0;
+
+ error:
+   dev_err(line6->ifcdev, "usb_submit_urb failed\n");
+   usb_free_urb(urb);
+   return retval;
 }
 
 static int line6_midi_output_open(struct snd_rawmidi_substream *substream)
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/9] usb: core: Add a helper function to check the validity of EP type in URB

2017-10-11 Thread Takashi Iwai
This patch adds a new helper function to perform a sanity check of the
given URB to see whether it contains a valid endpoint.  It's a light-
weight version of what usb_submit_urb() does, but without the kernel
warning followed by the stack trace, just returns an error code.

Especially for a driver that doesn't parse the descriptor but fills
the URB with the fixed endpoint (e.g. some quirks for non-compliant
devices), this kind of check is preferable at the probe phase before
actually submitting the urb.

Tested-by: Andrey Konovalov 
Signed-off-by: Takashi Iwai 
---
v1->v2:
* Fix function name typos
* Call usb_urb_ep_type_check() in usb_submit_urb(), too

 drivers/usb/core/urb.c | 30 ++
 include/linux/usb.h|  2 ++
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 47903d510955..8b800e34407b 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -187,6 +187,31 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
 
 /*---*/
 
+static const int pipetypes[4] = {
+   PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
+};
+
+/**
+ * usb_urb_ep_type_check - sanity check of endpoint in the given urb
+ * @urb: urb to be checked
+ *
+ * This performs a light-weight sanity check for the endpoint in the
+ * given urb.  It returns 0 if the urb contains a valid endpoint, otherwise
+ * a negative error code.
+ */
+int usb_urb_ep_type_check(const struct urb *urb)
+{
+   const struct usb_host_endpoint *ep;
+
+   ep = usb_pipe_endpoint(urb->dev, urb->pipe);
+   if (!ep)
+   return -EINVAL;
+   if (usb_pipetype(urb->pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
+   return -EINVAL;
+   return 0;
+}
+EXPORT_SYMBOL_GPL(usb_urb_ep_type_check);
+
 /**
  * usb_submit_urb - issue an asynchronous transfer request for an endpoint
  * @urb: pointer to the urb describing the request
@@ -326,9 +351,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  */
 int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 {
-   static int  pipetypes[4] = {
-   PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
-   };
int xfertype, max;
struct usb_device   *dev;
struct usb_host_endpoint*ep;
@@ -444,7 +466,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 */
 
/* Check that the pipe's type matches the endpoint's type */
-   if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+   if (usb_urb_ep_type_check(urb))
dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
usb_pipetype(urb->pipe), pipetypes[xfertype]);
 
diff --git a/include/linux/usb.h b/include/linux/usb.h
index cb9fbd54386e..2b861804fffa 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1728,6 +1728,8 @@ static inline int usb_urb_dir_out(struct urb *urb)
return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT;
 }
 
+int usb_urb_ep_type_check(const struct urb *urb);
+
 void *usb_alloc_coherent(struct usb_device *dev, size_t size,
gfp_t mem_flags, dma_addr_t *dma);
 void usb_free_coherent(struct usb_device *dev, size_t size,
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 8/9] ALSA: caiaq: Add yet more sanity checks for invalid EPs

2017-10-11 Thread Takashi Iwai
A few other places in caiaq driver have the URB handling with the
fixed endpoints without checking the validity, too.  Add the sanity
check with the new helper function at each appropriate place for
avoiding the spurious kernel warnings due to invalid EPs.

Signed-off-by: Takashi Iwai 
---
 sound/usb/caiaq/input.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
index 4b3fb91deecd..e883659ea6e7 100644
--- a/sound/usb/caiaq/input.c
+++ b/sound/usb/caiaq/input.c
@@ -718,6 +718,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
  usb_rcvbulkpipe(usb_dev, 0x4),
  cdev->ep4_in_buf, EP4_BUFSIZE,
  snd_usb_caiaq_ep4_reply_dispatch, cdev);
+   ret = usb_urb_ep_type_check(cdev->ep4_in_urb);
+   if (ret < 0)
+   goto exit_free_idev;
 
snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
 
@@ -757,6 +760,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
  usb_rcvbulkpipe(usb_dev, 0x4),
  cdev->ep4_in_buf, EP4_BUFSIZE,
  snd_usb_caiaq_ep4_reply_dispatch, cdev);
+   ret = usb_urb_ep_type_check(cdev->ep4_in_urb);
+   if (ret < 0)
+   goto exit_free_idev;
 
snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
 
@@ -802,6 +808,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
  usb_rcvbulkpipe(usb_dev, 0x4),
  cdev->ep4_in_buf, EP4_BUFSIZE,
  snd_usb_caiaq_ep4_reply_dispatch, cdev);
+   ret = usb_urb_ep_type_check(cdev->ep4_in_urb);
+   if (ret < 0)
+   goto exit_free_idev;
 
snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
break;
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 3/9] ALSA: caiaq: Add a sanity check for invalid EPs

2017-10-11 Thread Takashi Iwai
As syzkaller spotted, currently caiaq driver submits a URB with the
fixed EP without checking whether it's actually available, which may
result in a kernel warning like:
  usb 1-1: BOGUS urb xfer, pipe 3 != type 1
  [ cut here ]
  WARNING: CPU: 1 PID: 1150 at drivers/usb/core/urb.c:449
  usb_submit_urb+0xf8a/0x11d0
  Modules linked in:
  CPU: 1 PID: 1150 Comm: kworker/1:1 Not tainted
  4.14.0-rc2-42660-g24b7bd59eec0 #277
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
  Workqueue: usb_hub_wq hub_event
  Call Trace:
   init_card sound/usb/caiaq/device.c:467
   snd_probe+0x81c/0x1150 sound/usb/caiaq/device.c:525
   usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
   

This patch adds a sanity check of validity of EPs at the device
initialization phase for avoiding the call with an invalid EP.

Reported-by: Andrey Konovalov 
Tested-by: Andrey Konovalov 
Signed-off-by: Takashi Iwai 
---
 sound/usb/caiaq/device.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 0fb6b1b79261..a29674bf96e5 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -461,6 +461,13 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
  cdev->midi_out_buf, EP1_BUFSIZE,
  snd_usb_caiaq_midi_output_done, cdev);
 
+   /* sanity checks of EPs before actually submitting */
+   if (usb_urb_ep_type_check(&cdev->ep1_in_urb) ||
+   usb_urb_ep_type_check(&cdev->midi_out_urb)) {
+   dev_err(dev, "invalid EPs\n");
+   return -EINVAL;
+   }
+
init_waitqueue_head(&cdev->ep1_wait_queue);
init_waitqueue_head(&cdev->prepare_wait_queue);
 
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/8] Documentation: fix input related doc refs

2017-10-10 Thread Takashi Iwai
On Tue, 10 Oct 2017 19:36:23 +0200,
Tom Saeger wrote:
> 
> Make `input` document refs valid including:
>   - joystick
>   - joystick-parport
> 
> Signed-off-by: Tom Saeger 

For the sound part:
Reviewed-by: Takashi Iwai 


thanks,

Takashi

> ---
>  Documentation/admin-guide/kernel-parameters.txt | 10 +-
>  Documentation/hid/hiddev.txt|  2 +-
>  Documentation/input/devices/xpad.rst|  3 ++-
>  Documentation/sound/cards/joystick.rst  |  2 +-
>  4 files changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt 
> b/Documentation/admin-guide/kernel-parameters.txt
> index e857bbbc8575..411b41127eee 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -314,7 +314,7 @@
>   amijoy.map= [HW,JOY] Amiga joystick support
>   Map of devices attached to JOY0DAT and JOY1DAT
>   Format: ,
> - See also Documentation/input/joystick.txt
> + See also Documentation/input/joydev/joystick.rst
>  
>   analog.map= [HW,JOY] Analog joystick and gamepad support
>   Specifies type or capabilities of an analog joystick
> @@ -724,7 +724,7 @@
>   db9.dev[2|3]=   [HW,JOY] Multisystem joystick support via parallel port
>   (one device per port)
>   Format: ,
> - See also Documentation/input/joystick-parport.txt
> + See also 
> Documentation/input/devices/joystick-parport.rst
>  
>   ddebug_query=   [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot
>   time. See
> @@ -1220,7 +1220,7 @@
>   [HW,JOY] Multisystem joystick and NES/SNES/PSX pad
>   support via parallel port (up to 5 devices per port)
>   Format: ,
> - See also Documentation/input/joystick-parport.txt
> + See also 
> Documentation/input/devices/joystick-parport.rst
>  
>   gamma=  [HW,DRM]
>  
> @@ -1766,7 +1766,7 @@
>   ivrs_acpihid[00:14.5]=AMD0020:0
>  
>   js= [HW,JOY] Analog joystick
> - See Documentation/input/joystick.txt.
> + See Documentation/input/joydev/joystick.rst.
>  
>   nokaslr [KNL]
>   When CONFIG_RANDOMIZE_BASE is set, this disables
> @@ -4199,7 +4199,7 @@
>   TurboGraFX parallel port interface
>   Format:
>   ,,,
> - See also Documentation/input/joystick-parport.txt
> + See also 
> Documentation/input/devices/joystick-parport.rst
>  
>   udbg-immortal   [PPC] When debugging early kernel crashes that
>   happen after console_init() and before a proper
> diff --git a/Documentation/hid/hiddev.txt b/Documentation/hid/hiddev.txt
> index 6e8c9f1d2f22..638448707aa2 100644
> --- a/Documentation/hid/hiddev.txt
> +++ b/Documentation/hid/hiddev.txt
> @@ -12,7 +12,7 @@ To support these disparate requirements, the Linux USB 
> system provides
>  HID events to two separate interfaces:
>  * the input subsystem, which converts HID events into normal input
>  device interfaces (such as keyboard, mouse and joystick) and a
> -normalised event interface - see Documentation/input/input.txt
> +normalised event interface - see Documentation/input/input.rst
>  * the hiddev interface, which provides fairly raw HID events
>  
>  The data flow for a HID event produced by a device is something like
> diff --git a/Documentation/input/devices/xpad.rst 
> b/Documentation/input/devices/xpad.rst
> index 5a709ab77c8d..b8bd65962dd8 100644
> --- a/Documentation/input/devices/xpad.rst
> +++ b/Documentation/input/devices/xpad.rst
> @@ -230,4 +230,5 @@ Historic Edits
>  2005-03-19 - Dominic Cerquetti 
>   - added stuff for dance pads, new d-pad->axes mappings
>  
> -Later changes may be viewed with 'git log Documentation/input/xpad.txt'
> +Later changes may be viewed with
> +'git log --follow Documentation/input/devices/xpad.rst'
> diff --git a/Documentation/sound/cards/joystick.rst 
> b/Documentation/sound/cards/joystick.rst
> index a6e468c81d02..488946fc1079 100644
> --- a/Documentation/sound/cards/joystick.rst
> +++ b/Documentation/sound/cards/joystick.rst
> @@ -11,7 +11,7 @@ General
>  
>  First of all, you need to enable GAMEPORT support on Linux kernel for
>  using a joystick with the ALSA driver.  For the details of gameport
&g

Re: [PATCH 2/9] ALSA: bcd2000: Add a sanity check for invalid EPs

2017-10-10 Thread Takashi Iwai
On Tue, 10 Oct 2017 16:00:25 +0200,
Andrey Konovalov wrote:
> 
> On Tue, Oct 10, 2017 at 3:38 PM, Takashi Iwai  wrote:
> > As syzkaller spotted, currently bcd2000 driver submits a URB with the
> > fixed EP without checking whether it's actually available, which may
> > result in a kernel warning like:
> >   usb 1-1: BOGUS urb xfer, pipe 1 != type 3
> >   [ cut here ]
> >   WARNING: CPU: 0 PID: 1846 at drivers/usb/core/urb.c:449
> >   usb_submit_urb+0xf8a/0x11d0
> >   Modules linked in:
> >   CPU: 0 PID: 1846 Comm: kworker/0:2 Not tainted
> >   4.14.0-rc2-42613-g1488251d1a98 #238
> >   Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 
> > 01/01/2011
> >   Workqueue: usb_hub_wq hub_event
> >   Call Trace:
> >bcd2000_init_device sound/usb/bcd2000/bcd2000.c:289
> >bcd2000_init_midi sound/usb/bcd2000/bcd2000.c:345
> >bcd2000_probe+0xe64/0x19e0 sound/usb/bcd2000/bcd2000.c:406
> >usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
> >
> >
> > This patch adds a sanity check of validity of EPs at the device
> > initialization phase for avoiding the call with an invalid EP.
> >
> > Reported-by: Andrey Konovalov 
> > Signed-off-by: Takashi Iwai 
> 
> Hi Takashi,
> 
> I've applied patches #1 and #2 and for some reason get this when I try
> to build the kernel:
> 
>   LD  vmlinux.o
>   MODPOST vmlinux.o
> sound/usb/bcd2000/bcd2000.o: In function `bcd2000_init_midi':
> .../sound/usb/bcd2000/bcd2000.c:346: undefined reference to
> `usb_urb_ep_type_check'
> .../sound/usb/bcd2000/bcd2000.c:347: undefined reference to
> `usb_urb_ep_type_check'
> make: *** [vmlinux] Error 1
> 
> What could be wrong?

Mea culpa, I generated patches from the wrong branch.
Luckily only the first patch was wrong, the function name was
misspelled.

Below is the right patch for patch 1, which already includes Greg's
suggestions.  I'm going to send a v2 series in anyway later, so just
putting this one below.

Sorry for the inconvenience!


Takashi

-- 8< --
From: Takashi Iwai 
Subject: [PATCH 1/9] usb: core: Add a helper function to check the validity of 
EP type in URB

This patch adds a new helper function to perform a sanity check of the
given URB to see whether it contains a valid endpoint.  It's a light-
weight version of what usb_submit_urb() does, but without the kernel
warning followed by the stack trace, just returns an error code.

Especially for a driver that doesn't parse the descriptor but fills
the URB with the fixed endpoint (e.g. some quirks for non-compliant
devices), this kind of check is preferable at the probe phase before
actually submitting the urb.

Signed-off-by: Takashi Iwai 
---
 drivers/usb/core/urb.c | 30 ++
 include/linux/usb.h|  2 ++
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 47903d510955..8b800e34407b 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -187,6 +187,31 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
 
 /*---*/
 
+static const int pipetypes[4] = {
+   PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
+};
+
+/**
+ * usb_urb_ep_type_check - sanity check of endpoint in the given urb
+ * @urb: urb to be checked
+ *
+ * This performs a light-weight sanity check for the endpoint in the
+ * given urb.  It returns 0 if the urb contains a valid endpoint, otherwise
+ * a negative error code.
+ */
+int usb_urb_ep_type_check(const struct urb *urb)
+{
+   const struct usb_host_endpoint *ep;
+
+   ep = usb_pipe_endpoint(urb->dev, urb->pipe);
+   if (!ep)
+   return -EINVAL;
+   if (usb_pipetype(urb->pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
+   return -EINVAL;
+   return 0;
+}
+EXPORT_SYMBOL_GPL(usb_urb_ep_type_check);
+
 /**
  * usb_submit_urb - issue an asynchronous transfer request for an endpoint
  * @urb: pointer to the urb describing the request
@@ -326,9 +351,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  */
 int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 {
-   static int  pipetypes[4] = {
-   PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
-   };
int xfertype, max;
struct usb_device   *dev;
struct usb_host_endpoint*ep;
@@ -444,7 +466,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 */
 
/* Check that the pipe's type matches the endpoint's type */
-   if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+   if (usb_urb_ep_type_check(urb))
  

Re: [PATCH 1/9] usb: core: Add a helper function to check the validity of EP type in URB

2017-10-10 Thread Takashi Iwai
On Tue, 10 Oct 2017 15:53:49 +0200,
Greg KH wrote:
> 
> On Tue, Oct 10, 2017 at 03:38:11PM +0200, Takashi Iwai wrote:
> > This patch adds a new helper function to perform a sanity check of the
> > given URB to see whether it contains a valid endpoint.  It's a light-
> > weight version of what usb_submit_urb() does, but without the kernel
> > warning followed by the stack trace, just returns an error code.
> > 
> > Especially for a driver that doesn't parse the descriptor but fills
> > the URB with the fixed endpoint (e.g. some quirks for non-compliant
> > devices), this kind of check is preferable at the probe phase before
> > actually submitting the urb.
> > 
> > Signed-off-by: Takashi Iwai 
> > ---
> >  drivers/usb/core/urb.c | 28 +---
> >  include/linux/usb.h|  2 ++
> >  2 files changed, 27 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
> > index 47903d510955..580dfaec8af7 100644
> > --- a/drivers/usb/core/urb.c
> > +++ b/drivers/usb/core/urb.c
> > @@ -187,6 +187,31 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
> >  
> >  /*---*/
> >  
> > +static const int pipetypes[4] = {
> > +   PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
> > +};
> > +
> > +/**
> > + * usb_urb_ep_check_type - sanity check of endpoint in the given urb
> > + * @urb: urb to be checked
> > + *
> > + * This performs a light-weight sanity check for the endpoint in the
> > + * given urb.  It returns 0 if the urb contains a valid endpoint, otherwise
> > + * a negative error code.
> > + */
> > +int usb_urb_ep_check_type(const struct urb *urb)
> > +{
> > +   const struct usb_host_endpoint *ep;
> > +
> > +   ep = usb_pipe_endpoint(urb->dev, urb->pipe);
> > +   if (!ep)
> > +   return -EINVAL;
> > +   if (usb_pipetype(urb->pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
> > +   return -EINVAL;
> > +   return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(usb_urb_ep_check_type);
> > +
> >  /**
> >   * usb_submit_urb - issue an asynchronous transfer request for an endpoint
> >   * @urb: pointer to the urb describing the request
> > @@ -326,9 +351,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
> >   */
> >  int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
> >  {
> > -   static int  pipetypes[4] = {
> > -   PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
> > -   };
> > int xfertype, max;
> > struct usb_device   *dev;
> > struct usb_host_endpoint*ep;
> 
> Can you also call usb_urb_ep_check_type() in usb_submit_urb()?

OK, will do that in v2 patch.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/9] sound: Add sanity checks for invalid EPs

2017-10-10 Thread Takashi Iwai
Hi,

this is a patchset to cover the codes that may submit URBs containing
invalid EPs without validation, which result in the kernel warning
from the USB core.  The first patch adds a new helper for simplifying
the EP check, and the rest applies it at needed places.

USB devs: could you check the first patch?  I tried
usb_find_common_endpoints() and friends at first, but it made the code
more complex in the end, because we're dealing with the fixed
endpoints and the validation is required for them.

The original issues were spotted by syzkaller, and I put a few others
for covering more similar cases.

thanks,

Takashi

===

Takashi Iwai (9):
  usb: core: Add a helper function to check the validity of EP type in
URB
  ALSA: bcd2000: Add a sanity check for invalid EPs
  ALSA: caiaq: Add a sanity check for invalid EPs
  ALSA: line6: Add a sanity check for invalid EPs
  ALSA: usb-audio: Add sanity checks for invalid EPs
  ALSA: usx2y: Add sanity checks for invalid EPs
  ALSA: hiface: Add sanity checks for invalid EPs
  ALSA: caiaq: Add yet more sanity checks for invalid EPs
  ALSA: line6: Add yet more sanity checks for invalid EPs

 drivers/usb/core/urb.c  | 28 +---
 include/linux/usb.h |  2 ++
 sound/usb/bcd2000/bcd2000.c |  7 +++
 sound/usb/caiaq/device.c|  7 +++
 sound/usb/caiaq/input.c |  9 +
 sound/usb/hiface/pcm.c  |  9 +++--
 sound/usb/line6/driver.c| 30 ++
 sound/usb/line6/midi.c  | 17 +++--
 sound/usb/midi.c| 38 ++
 sound/usb/usx2y/usbusx2y.c  |  8 
 sound/usb/usx2y/usbusx2yaudio.c |  3 +++
 11 files changed, 131 insertions(+), 27 deletions(-)

-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/9] ALSA: hiface: Add sanity checks for invalid EPs

2017-10-10 Thread Takashi Iwai
hiface usb-audio driver sets up URBs containing the fixed endpoints
without validation.  This may end up with an oops-like kernel warning
when submitted.

For avoiding it, this patch adds the calls of the new sanity-check
helper for URBs.

Signed-off-by: Takashi Iwai 
---
 sound/usb/hiface/pcm.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c
index 175d8d6b7f59..396c317115b1 100644
--- a/sound/usb/hiface/pcm.c
+++ b/sound/usb/hiface/pcm.c
@@ -541,6 +541,8 @@ static int hiface_pcm_init_urb(struct pcm_urb *urb,
usb_fill_bulk_urb(&urb->instance, chip->dev,
  usb_sndbulkpipe(chip->dev, ep), (void *)urb->buffer,
  PCM_PACKET_SIZE, handler, urb);
+   if (usb_urb_ep_type_check(&urb->instance))
+   return -EINVAL;
init_usb_anchor(&urb->submitted);
 
return 0;
@@ -599,9 +601,12 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 
extra_freq)
mutex_init(&rt->stream_mutex);
spin_lock_init(&rt->playback.lock);
 
-   for (i = 0; i < PCM_N_URBS; i++)
-   hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
+   for (i = 0; i < PCM_N_URBS; i++) {
+   ret = hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
hiface_pcm_out_urb_handler);
+   if (ret < 0)
+   return ret;
+   }
 
ret = snd_pcm_new(chip->card, "USB-SPDIF Audio", 0, 1, 0, &pcm);
if (ret < 0) {
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/9] ALSA: usb-audio: Add sanity checks for invalid EPs

2017-10-10 Thread Takashi Iwai
USB-audio driver may set up a URB containing the fixed EP without
validating its presence for some non-class-compliant devices.  This
may end up with an oops-like kernel warning when submitted.

For avoiding it, this patch adds the call of the new sanity-check
helper for URBs.  The checks are needed only for MIDI I/O as the other
places have already some other checks.

Signed-off-by: Takashi Iwai 
---
 sound/usb/midi.c | 38 ++
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index a92e2b2a91ec..7ab25de5ca0a 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -1282,6 +1282,7 @@ static int snd_usbmidi_in_endpoint_create(struct 
snd_usb_midi *umidi,
unsigned int pipe;
int length;
unsigned int i;
+   int err;
 
rep->in = NULL;
ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -1292,8 +1293,8 @@ static int snd_usbmidi_in_endpoint_create(struct 
snd_usb_midi *umidi,
for (i = 0; i < INPUT_URBS; ++i) {
ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
if (!ep->urbs[i]) {
-   snd_usbmidi_in_endpoint_delete(ep);
-   return -ENOMEM;
+   err = -ENOMEM;
+   goto error;
}
}
if (ep_info->in_interval)
@@ -1305,8 +1306,8 @@ static int snd_usbmidi_in_endpoint_create(struct 
snd_usb_midi *umidi,
buffer = usb_alloc_coherent(umidi->dev, length, GFP_KERNEL,
&ep->urbs[i]->transfer_dma);
if (!buffer) {
-   snd_usbmidi_in_endpoint_delete(ep);
-   return -ENOMEM;
+   err = -ENOMEM;
+   goto error;
}
if (ep_info->in_interval)
usb_fill_int_urb(ep->urbs[i], umidi->dev,
@@ -1318,10 +1319,20 @@ static int snd_usbmidi_in_endpoint_create(struct 
snd_usb_midi *umidi,
  pipe, buffer, length,
  snd_usbmidi_in_urb_complete, ep);
ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+   err = usb_urb_ep_type_check(ep->urbs[i]);
+   if (err < 0) {
+   dev_err(&umidi->dev->dev, "invalid MIDI in EP %x\n",
+   ep_info->in_ep);
+   goto error;
+   }
}
 
rep->in = ep;
return 0;
+
+ error:
+   snd_usbmidi_in_endpoint_delete(ep);
+   return -ENOMEM;
 }
 
 /*
@@ -1357,6 +1368,7 @@ static int snd_usbmidi_out_endpoint_create(struct 
snd_usb_midi *umidi,
unsigned int i;
unsigned int pipe;
void *buffer;
+   int err;
 
rep->out = NULL;
ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -1367,8 +1379,8 @@ static int snd_usbmidi_out_endpoint_create(struct 
snd_usb_midi *umidi,
for (i = 0; i < OUTPUT_URBS; ++i) {
ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ep->urbs[i].urb) {
-   snd_usbmidi_out_endpoint_delete(ep);
-   return -ENOMEM;
+   err = -ENOMEM;
+   goto error;
}
ep->urbs[i].ep = ep;
}
@@ -1406,8 +1418,8 @@ static int snd_usbmidi_out_endpoint_create(struct 
snd_usb_midi *umidi,
ep->max_transfer, GFP_KERNEL,
&ep->urbs[i].urb->transfer_dma);
if (!buffer) {
-   snd_usbmidi_out_endpoint_delete(ep);
-   return -ENOMEM;
+   err = -ENOMEM;
+   goto error;
}
if (ep_info->out_interval)
usb_fill_int_urb(ep->urbs[i].urb, umidi->dev,
@@ -1419,6 +1431,12 @@ static int snd_usbmidi_out_endpoint_create(struct 
snd_usb_midi *umidi,
  pipe, buffer, ep->max_transfer,
  snd_usbmidi_out_urb_complete,
  &ep->urbs[i]);
+   err = usb_urb_ep_type_check(ep->urbs[i].urb);
+   if (err < 0) {
+   dev_err(&umidi->dev->dev, "invalid MIDI out EP %x\n",
+   ep_info->out_ep);
+   goto error;
+   }
ep->urbs[i].urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
}
 
@@ -1437,6 +1455,10 @@ static int snd_usbmidi_out_endpoint_create(struct 
snd_usb_midi *umidi,
 
rep->out = ep;
return 0;
+
+ error:
+   snd_usbmidi_out_endpoint

[PATCH 2/9] ALSA: bcd2000: Add a sanity check for invalid EPs

2017-10-10 Thread Takashi Iwai
As syzkaller spotted, currently bcd2000 driver submits a URB with the
fixed EP without checking whether it's actually available, which may
result in a kernel warning like:
  usb 1-1: BOGUS urb xfer, pipe 1 != type 3
  [ cut here ]
  WARNING: CPU: 0 PID: 1846 at drivers/usb/core/urb.c:449
  usb_submit_urb+0xf8a/0x11d0
  Modules linked in:
  CPU: 0 PID: 1846 Comm: kworker/0:2 Not tainted
  4.14.0-rc2-42613-g1488251d1a98 #238
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
  Workqueue: usb_hub_wq hub_event
  Call Trace:
   bcd2000_init_device sound/usb/bcd2000/bcd2000.c:289
   bcd2000_init_midi sound/usb/bcd2000/bcd2000.c:345
   bcd2000_probe+0xe64/0x19e0 sound/usb/bcd2000/bcd2000.c:406
   usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
   

This patch adds a sanity check of validity of EPs at the device
initialization phase for avoiding the call with an invalid EP.

Reported-by: Andrey Konovalov 
Signed-off-by: Takashi Iwai 
---
 sound/usb/bcd2000/bcd2000.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c
index 7371e5b06035..a6408209d7f1 100644
--- a/sound/usb/bcd2000/bcd2000.c
+++ b/sound/usb/bcd2000/bcd2000.c
@@ -342,6 +342,13 @@ static int bcd2000_init_midi(struct bcd2000 *bcd2k)
bcd2k->midi_out_buf, BUFSIZE,
bcd2000_output_complete, bcd2k, 1);
 
+   /* sanity checks of EPs before actually submitting */
+   if (usb_urb_ep_type_check(bcd2k->midi_in_urb) ||
+   usb_urb_ep_type_check(bcd2k->midi_out_urb)) {
+   dev_err(&bcd2k->dev->dev, "invalid MIDI EP\n");
+   return -EINVAL;
+   }
+
bcd2000_init_device(bcd2k);
 
return 0;
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 9/9] ALSA: line6: Add yet more sanity checks for invalid EPs

2017-10-10 Thread Takashi Iwai
There are a few other places calling usb_submit_urb() with the URB
composed from the fixed endpoint without validation.  For avoiding the
spurious kernel warnings, add the sanity checks to appropriate
places.

Signed-off-by: Takashi Iwai 
---
 sound/usb/line6/driver.c | 23 +++
 sound/usb/line6/midi.c   | 17 +++--
 2 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 167aebf8276e..8d5a454842f4 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -175,17 +175,24 @@ static int line6_send_raw_message_async_part(struct 
message *msg,
}
 
msg->done += bytes;
-   retval = usb_submit_urb(urb, GFP_ATOMIC);
 
-   if (retval < 0) {
-   dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n",
-   __func__, retval);
-   usb_free_urb(urb);
-   kfree(msg);
-   return retval;
-   }
+   /* sanity checks of EP before actually submitting */
+   retval = usb_urb_ep_type_check(urb);
+   if (retval < 0)
+   goto error;
+
+   retval = usb_submit_urb(urb, GFP_ATOMIC);
+   if (retval < 0)
+   goto error;
 
return 0;
+
+ error:
+   dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n",
+   __func__, retval);
+   usb_free_urb(urb);
+   kfree(msg);
+   return retval;
 }
 
 /*
diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c
index 1d3a23b02d68..6d7cde56a355 100644
--- a/sound/usb/line6/midi.c
+++ b/sound/usb/line6/midi.c
@@ -130,16 +130,21 @@ static int send_midi_async(struct usb_line6 *line6, 
unsigned char *data,
 transfer_buffer, length, midi_sent, line6,
 line6->interval);
urb->actual_length = 0;
-   retval = usb_submit_urb(urb, GFP_ATOMIC);
+   retval = usb_urb_ep_type_check(urb);
+   if (retval < 0)
+   goto error;
 
-   if (retval < 0) {
-   dev_err(line6->ifcdev, "usb_submit_urb failed\n");
-   usb_free_urb(urb);
-   return retval;
-   }
+   retval = usb_submit_urb(urb, GFP_ATOMIC);
+   if (retval < 0)
+   goto error;
 
++line6->line6midi->num_active_send_urbs;
return 0;
+
+ error:
+   dev_err(line6->ifcdev, "usb_submit_urb failed\n");
+   usb_free_urb(urb);
+   return retval;
 }
 
 static int line6_midi_output_open(struct snd_rawmidi_substream *substream)
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 8/9] ALSA: caiaq: Add yet more sanity checks for invalid EPs

2017-10-10 Thread Takashi Iwai
A few other places in caiaq driver have the URB handling with the
fixed endpoints without checking the validity, too.  Add the sanity
check with the new helper function at each appropriate place for
avoiding the spurious kernel warnings due to invalid EPs.

Signed-off-by: Takashi Iwai 
---
 sound/usb/caiaq/input.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
index 4b3fb91deecd..e883659ea6e7 100644
--- a/sound/usb/caiaq/input.c
+++ b/sound/usb/caiaq/input.c
@@ -718,6 +718,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
  usb_rcvbulkpipe(usb_dev, 0x4),
  cdev->ep4_in_buf, EP4_BUFSIZE,
  snd_usb_caiaq_ep4_reply_dispatch, cdev);
+   ret = usb_urb_ep_type_check(cdev->ep4_in_urb);
+   if (ret < 0)
+   goto exit_free_idev;
 
snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
 
@@ -757,6 +760,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
  usb_rcvbulkpipe(usb_dev, 0x4),
  cdev->ep4_in_buf, EP4_BUFSIZE,
  snd_usb_caiaq_ep4_reply_dispatch, cdev);
+   ret = usb_urb_ep_type_check(cdev->ep4_in_urb);
+   if (ret < 0)
+   goto exit_free_idev;
 
snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
 
@@ -802,6 +808,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
  usb_rcvbulkpipe(usb_dev, 0x4),
  cdev->ep4_in_buf, EP4_BUFSIZE,
  snd_usb_caiaq_ep4_reply_dispatch, cdev);
+   ret = usb_urb_ep_type_check(cdev->ep4_in_urb);
+   if (ret < 0)
+   goto exit_free_idev;
 
snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
break;
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/9] ALSA: usx2y: Add sanity checks for invalid EPs

2017-10-10 Thread Takashi Iwai
usx2y driver sets up URBs containing the fixed endpoints without
validation.  This may end up with an oops-like kernel warning when
submitted.

For avoiding it, this patch adds the calls of the new sanity-check
helper for URBs.

Signed-off-by: Takashi Iwai 
---
 sound/usb/usx2y/usbusx2y.c  | 8 
 sound/usb/usx2y/usbusx2yaudio.c | 3 +++
 2 files changed, 11 insertions(+)

diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index 4569c0efac0a..55a631ccfa25 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -244,6 +244,9 @@ static void i_usX2Y_In04Int(struct urb *urb)
  
usb_sndbulkpipe(usX2Y->dev, 0x04), &p4out->val.vol,
  p4out->type 
== eLT_Light ? sizeof(struct us428_lights) : 5,
  
i_usX2Y_Out04Int, usX2Y);
+   err = 
usb_urb_ep_type_check(usX2Y->AS04.urb[j]);
+   if (err < 0)
+   break;
err = 
usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC);
us428ctls->p4outSent = send;
break;
@@ -279,6 +282,9 @@ int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y)
usX2Y->AS04.buffer + 
URB_DataLen_AsyncSeq*i, 0,
i_usX2Y_Out04Int, usX2Y
);
+   err = usb_urb_ep_type_check(usX2Y->AS04.urb[i]);
+   if (err < 0)
+   break;
}
return err;
 }
@@ -298,6 +304,8 @@ int usX2Y_In04_init(struct usX2Ydev *usX2Y)
 usX2Y->In04Buf, 21,
 i_usX2Y_In04Int, usX2Y,
 10);
+   if (usb_urb_ep_type_check(usX2Y->In04urb))
+   return -EINVAL;
return usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
 }
 
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index f93b355756e6..345e439aa95b 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -677,6 +677,9 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate)
usb_fill_bulk_urb(us->urb[i], usX2Y->dev, 
usb_sndbulkpipe(usX2Y->dev, 4),
  usbdata + i, 2, i_usX2Y_04Int, usX2Y);
}
+   err = usb_urb_ep_type_check(us->urb[0]);
+   if (err < 0)
+   goto cleanup;
us->submitted = 0;
us->len =   NOOF_SETRATE_URBS;
usX2Y->US04 =   us;
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/9] ALSA: line6: Add a sanity check for invalid EPs

2017-10-10 Thread Takashi Iwai
As syzkaller spotted, currently line6 drivers submit a URB with the
fixed EP without checking whether it's actually available, which may
result in a kernel warning like:
  usb 1-1: BOGUS urb xfer, pipe 3 != type 1
  [ cut here ]
  WARNING: CPU: 0 PID: 24 at drivers/usb/core/urb.c:449
  usb_submit_urb+0xf8a/0x11d0
  Modules linked in:
  CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 4.14.0-rc2-42613-g1488251d1a98 
#238
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
  Workqueue: usb_hub_wq hub_event
  Call Trace:
   line6_start_listen+0x55f/0x9e0 sound/usb/line6/driver.c:82
   line6_init_cap_control sound/usb/line6/driver.c:690
   line6_probe+0x7c9/0x1310 sound/usb/line6/driver.c:764
   podhd_probe+0x64/0x70 sound/usb/line6/podhd.c:474
   usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
   

This patch adds a sanity check of validity of EPs at the device
initialization phase for avoiding the call with an invalid EP.

Reported-by: Andrey Konovalov 
Cc: 
Signed-off-by: Takashi Iwai 
---
 sound/usb/line6/driver.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index c8f723c3a033..167aebf8276e 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -78,6 +78,13 @@ static int line6_start_listen(struct usb_line6 *line6)
line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
line6_data_received, line6);
}
+
+   /* sanity checks of EP before actually submitting */
+   if (usb_urb_ep_type_check(line6->urb_listen)) {
+   dev_err(line6->ifcdev, "invalid control EP\n");
+   return -EINVAL;
+   }
+
line6->urb_listen->actual_length = 0;
err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC);
return err;
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/9] ALSA: caiaq: Add a sanity check for invalid EPs

2017-10-10 Thread Takashi Iwai
As syzkaller spotted, currently caiaq driver submits a URB with the
fixed EP without checking whether it's actually available, which may
result in a kernel warning like:
  usb 1-1: BOGUS urb xfer, pipe 3 != type 1
  [ cut here ]
  WARNING: CPU: 1 PID: 1150 at drivers/usb/core/urb.c:449
  usb_submit_urb+0xf8a/0x11d0
  Modules linked in:
  CPU: 1 PID: 1150 Comm: kworker/1:1 Not tainted
  4.14.0-rc2-42660-g24b7bd59eec0 #277
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
  Workqueue: usb_hub_wq hub_event
  Call Trace:
   init_card sound/usb/caiaq/device.c:467
   snd_probe+0x81c/0x1150 sound/usb/caiaq/device.c:525
   usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
   

This patch adds a sanity check of validity of EPs at the device
initialization phase for avoiding the call with an invalid EP.

Reported-by: Andrey Konovalov 
Signed-off-by: Takashi Iwai 
---
 sound/usb/caiaq/device.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 0fb6b1b79261..a29674bf96e5 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -461,6 +461,13 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
  cdev->midi_out_buf, EP1_BUFSIZE,
  snd_usb_caiaq_midi_output_done, cdev);
 
+   /* sanity checks of EPs before actually submitting */
+   if (usb_urb_ep_type_check(&cdev->ep1_in_urb) ||
+   usb_urb_ep_type_check(&cdev->midi_out_urb)) {
+   dev_err(dev, "invalid EPs\n");
+   return -EINVAL;
+   }
+
init_waitqueue_head(&cdev->ep1_wait_queue);
init_waitqueue_head(&cdev->prepare_wait_queue);
 
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/9] usb: core: Add a helper function to check the validity of EP type in URB

2017-10-10 Thread Takashi Iwai
This patch adds a new helper function to perform a sanity check of the
given URB to see whether it contains a valid endpoint.  It's a light-
weight version of what usb_submit_urb() does, but without the kernel
warning followed by the stack trace, just returns an error code.

Especially for a driver that doesn't parse the descriptor but fills
the URB with the fixed endpoint (e.g. some quirks for non-compliant
devices), this kind of check is preferable at the probe phase before
actually submitting the urb.

Signed-off-by: Takashi Iwai 
---
 drivers/usb/core/urb.c | 28 +---
 include/linux/usb.h|  2 ++
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 47903d510955..580dfaec8af7 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -187,6 +187,31 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
 
 /*---*/
 
+static const int pipetypes[4] = {
+   PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
+};
+
+/**
+ * usb_urb_ep_check_type - sanity check of endpoint in the given urb
+ * @urb: urb to be checked
+ *
+ * This performs a light-weight sanity check for the endpoint in the
+ * given urb.  It returns 0 if the urb contains a valid endpoint, otherwise
+ * a negative error code.
+ */
+int usb_urb_ep_check_type(const struct urb *urb)
+{
+   const struct usb_host_endpoint *ep;
+
+   ep = usb_pipe_endpoint(urb->dev, urb->pipe);
+   if (!ep)
+   return -EINVAL;
+   if (usb_pipetype(urb->pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
+   return -EINVAL;
+   return 0;
+}
+EXPORT_SYMBOL_GPL(usb_urb_ep_check_type);
+
 /**
  * usb_submit_urb - issue an asynchronous transfer request for an endpoint
  * @urb: pointer to the urb describing the request
@@ -326,9 +351,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  */
 int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 {
-   static int  pipetypes[4] = {
-   PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
-   };
int xfertype, max;
struct usb_device   *dev;
struct usb_host_endpoint*ep;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index cb9fbd54386e..2b861804fffa 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1728,6 +1728,8 @@ static inline int usb_urb_dir_out(struct urb *urb)
return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT;
 }
 
+int usb_urb_ep_type_check(const struct urb *urb);
+
 void *usb_alloc_coherent(struct usb_device *dev, size_t size,
gfp_t mem_flags, dma_addr_t *dma);
 void usb_free_coherent(struct usb_device *dev, size_t size,
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb/sound/bcd2000: warning in bcd2000_init_device

2017-10-04 Thread Takashi Iwai
On Wed, 04 Oct 2017 14:03:25 +0200,
Johan Hovold wrote:
> 
> On Wed, Oct 04, 2017 at 12:41:55PM +0200, Takashi Iwai wrote:
> > On Wed, 04 Oct 2017 12:23:11 +0200,
> > Johan Hovold wrote:
> > > 
> > > On Wed, Oct 04, 2017 at 12:04:06PM +0200, Takashi Iwai wrote:
> > > > On Wed, 04 Oct 2017 11:24:42 +0200, Johan Hovold wrote:
> > > > > On Wed, Oct 04, 2017 at 08:10:59AM +0200, Takashi Iwai wrote:
> > > 
> > > > > > Well, what I had in my mind is just a snippet from usb_submit_urb(),
> > > > > > something like:
> > > > > > 
> > > > > > bool usb_sanity_check_urb_pipe(struct urb *urb)
> > > > > > {
> > > > > > struct usb_host_endpoint *ep;
> > > > > > int xfertype;
> > > > > > static const int pipetypes[4] = {
> > > > > > PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, 
> > > > > > PIPE_INTERRUPT
> > > > > > };
> > > > > > 
> > > > > > ep = usb_pipe_endpoint(urb->dev, urb->pipe);
> > > > > > xfertype = usb_endpoint_type(&ep->desc);
> > > > > > return usb_pipetype(urb->pipe) != pipetypes[xfertype];
> > > > > > }
> > > > > > 
> > > > > > And calling this before usb_submit_urb() in each place that assigns
> > > > > > the fixed EP as device-specific quirks.
> > > > > > Does it make sense?
> > > > > 
> > > > > Not really. Your driver should not even bind to an interface which 
> > > > > lacks
> > > > > the expected endpoints (rather than check this at a potentially later
> > > > > point in time when URBs are submitted).
> > > > 
> > > > The endpoint may exist but it may be invalid, as the problem is
> > > > triggered by a VM.  It doesn't parse but tries a fixed EP as it's no
> > > > compliant device.
> > > 
> > > Yes, that's why a driver should verify that the endpoints it expects are
> > > indeed present (and of the right type) already at probe.
> > > 
> > > In Andrey's fuzzing it's triggered by in a VM using the dummy_hcd
> > > driver, but this could just as well be a (malicious) physical device
> > > with unexpected descriptors.
> > > 
> > > > > The new helper which Greg mentioned would allow this to implemented 
> > > > > with
> > > > > just a few lines of code. Just add it to bcd2000_init_midi() or 
> > > > > similar.  
> > > > 
> > > > Could you give an example?  Then I can ask Andrey whether such a call
> > > > really addresses the issue.
> > > 
> > > If you grep for usb_find_common_endpoints you'll find a few examples
> > > of how that function may be used (e.g. in drivers/usb/misc/usblcd.c).
> > > 
> > > The helper iterates of the endpoint descriptors of an interface
> > > alt-setting and returns a descriptor for each requested type if found.
> > > After a vetting of our current drivers I concluded that this would
> > > cover the needs of the vast majority of drivers.
> > > 
> > > So for the driver in question you'd only need to add something like:
> > > 
> > >   struct usb_endpoint_descriptor *int_in, *int_out;
> > >   int ret;
> > > 
> > >   ret = usb_find_common_endpoints(interface->cur_altsetting,
> > >   NULL, NULL, &int_in, &int_out);
> > >   if (ret) {
> > >   dev_err(&interface->dev, "required endpoints not found\n");
> > >   return -ENODEV;
> > >   }
> > > 
> > > Then you can use int_in->bEndpointAddress etc. when initialising your
> > > URBs.
> > 
> > OK, but in our cases, it's not about using the returned one but
> > checking whether it's the expected address, right?  The device is
> > non-compliant and that's the reason the driver takes the fixed EP.
> 
> There's nothing preventing you from verifying that the returned
> descriptors have the expected addresses if tightening the constraints
> this ways makes sense for your application.

OK.

> Or you can implement your own sanity checks, just do it at probe.
> 
> But note that you'd introduce NULL-deref that can be triggered by a
> malicious device with your outlined helper above, as
> 
>   ep = usb_pipe_endpoint(urb->dev, urb->pipe);
> 
> will be NULL when the corresponding descriptor is missing.

Yes, if we do that.  But I'm working on a version using
usb_find_*_endpoint*() instead.

> > In anyway, the check will be shortly before the URB submission because
> > the EP is often determined a late stage of probe, as most of errors
> > happened for the MIDI interface that are device-specific.
> 
> As long as you do the check during probe and refuse to bind to a
> non-compliant device you should be fine. Some drivers do not submit URBs
> until the user tries to use whatever interface the driver exposes (e.g.
> when opening a character device), which IMO is too late for such sanity
> checks.

Right, and this won't be a problem as the issue is triggered before
the actual device registration (ALSA has a staged registration
scheme).


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb/sound/bcd2000: warning in bcd2000_init_device

2017-10-04 Thread Takashi Iwai
On Wed, 04 Oct 2017 12:23:11 +0200,
Johan Hovold wrote:
> 
> On Wed, Oct 04, 2017 at 12:04:06PM +0200, Takashi Iwai wrote:
> > On Wed, 04 Oct 2017 11:24:42 +0200, Johan Hovold wrote:
> > > On Wed, Oct 04, 2017 at 08:10:59AM +0200, Takashi Iwai wrote:
> 
> > > > Well, what I had in my mind is just a snippet from usb_submit_urb(),
> > > > something like:
> > > > 
> > > > bool usb_sanity_check_urb_pipe(struct urb *urb)
> > > > {
> > > > struct usb_host_endpoint *ep;
> > > > int xfertype;
> > > > static const int pipetypes[4] = {
> > > > PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, 
> > > > PIPE_INTERRUPT
> > > > };
> > > > 
> > > > ep = usb_pipe_endpoint(urb->dev, urb->pipe);
> > > > xfertype = usb_endpoint_type(&ep->desc);
> > > > return usb_pipetype(urb->pipe) != pipetypes[xfertype];
> > > > }
> > > > 
> > > > And calling this before usb_submit_urb() in each place that assigns
> > > > the fixed EP as device-specific quirks.
> > > > Does it make sense?
> > > 
> > > Not really. Your driver should not even bind to an interface which lacks
> > > the expected endpoints (rather than check this at a potentially later
> > > point in time when URBs are submitted).
> > 
> > The endpoint may exist but it may be invalid, as the problem is
> > triggered by a VM.  It doesn't parse but tries a fixed EP as it's no
> > compliant device.
> 
> Yes, that's why a driver should verify that the endpoints it expects are
> indeed present (and of the right type) already at probe.
> 
> In Andrey's fuzzing it's triggered by in a VM using the dummy_hcd
> driver, but this could just as well be a (malicious) physical device
> with unexpected descriptors.
> 
> > > The new helper which Greg mentioned would allow this to implemented with
> > > just a few lines of code. Just add it to bcd2000_init_midi() or similar.  
> > 
> > Could you give an example?  Then I can ask Andrey whether such a call
> > really addresses the issue.
> 
> If you grep for usb_find_common_endpoints you'll find a few examples
> of how that function may be used (e.g. in drivers/usb/misc/usblcd.c).
> 
> The helper iterates of the endpoint descriptors of an interface
> alt-setting and returns a descriptor for each requested type if found.
> After a vetting of our current drivers I concluded that this would
> cover the needs of the vast majority of drivers.
> 
> So for the driver in question you'd only need to add something like:
> 
>   struct usb_endpoint_descriptor *int_in, *int_out;
>   int ret;
> 
>   ret = usb_find_common_endpoints(interface->cur_altsetting,
>   NULL, NULL, &int_in, &int_out);
>   if (ret) {
>   dev_err(&interface->dev, "required endpoints not found\n");
>   return -ENODEV;
>   }
> 
> Then you can use int_in->bEndpointAddress etc. when initialising your
> URBs.

OK, but in our cases, it's not about using the returned one but
checking whether it's the expected address, right?  The device is
non-compliant and that's the reason the driver takes the fixed EP.

In anyway, the check will be shortly before the URB submission because
the EP is often determined a late stage of probe, as most of errors
happened for the MIDI interface that are device-specific.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb/sound/bcd2000: warning in bcd2000_init_device

2017-10-04 Thread Takashi Iwai
On Wed, 04 Oct 2017 11:24:42 +0200,
Johan Hovold wrote:
> 
> On Wed, Oct 04, 2017 at 08:10:59AM +0200, Takashi Iwai wrote:
> > On Tue, 03 Oct 2017 19:42:21 +0200,
> > Greg Kroah-Hartman wrote:
> > > 
> > > On Tue, Oct 03, 2017 at 12:50:08PM -0400, Alan Stern wrote:
> > > > On Tue, 3 Oct 2017, Takashi Iwai wrote:
> > > > 
> > > > > > It's a dev_WARN because it indicates a potentially serious error in 
> > > > > > the 
> > > > > > driver: The driver has submitted an interrupt URB to a bulk 
> > > > > > endpoint.  
> > > > > > That may not sound bad, but the same check gets triggered if a 
> > > > > > driver 
> > > > > > submits a bulk URB to an isochronous endpoint, or any other invalid 
> > > > > > combination.
> > > > > > 
> > > > > > Most likely the explanation here is that the driver doesn't bother 
> > > > > > to
> > > > > > check the endpoint type because it expects the endpoint will always 
> > > > > > be
> > > > > > interrupt.  But that is not a safe strategy.  USB devices and their
> > > > > > firmware should not be trusted unnecessarily.
> > > > > > 
> > > > > > The best fix is, like you said, to add a sanity check in the caller.
> > > > > 
> > > > > OK, but then do we have some handy helper for the check?
> > > > > As other bug reports by syzkaller suggest, there are a few other
> > > > > drivers that do the same, submitting a urb with naive assumption of
> > > > > the fixed EP for specific devices.  In the end we'll need to put the
> > > > > very same checks there in multiple places.
> > > > 
> > > > Perhaps we could add a helper routine that would take a list of 
> > > > expected endpoint types and check that the actual endpoints match the 
> > > > types.  But of course, all the drivers you're talking about would have 
> > > > to add a call to this helper routine.
> > > 
> > > We have almost this type of function, usb_find_common_endpoints(),
> > > what's wrong with using that?  Johan has already swept the tree and
> > > added a lot of these checks, odds are no one looked at the sound/
> > > subdir...
> 
> Yeah, I only swept the tree for instances were a missing endpoint could
> lead to a NULL-deref. This is not the case here were the endpoint
> addresses are hardcoded in the driver.
> 
> I also never got around to applying the new helper outside of
> drivers/usb.
> 
> > Well, what I had in my mind is just a snippet from usb_submit_urb(),
> > something like:
> > 
> > bool usb_sanity_check_urb_pipe(struct urb *urb)
> > {
> > struct usb_host_endpoint *ep;
> > int xfertype;
> > static const int pipetypes[4] = {
> > PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
> > };
> > 
> > ep = usb_pipe_endpoint(urb->dev, urb->pipe);
> > xfertype = usb_endpoint_type(&ep->desc);
> > return usb_pipetype(urb->pipe) != pipetypes[xfertype];
> > }
> > 
> > And calling this before usb_submit_urb() in each place that assigns
> > the fixed EP as device-specific quirks.
> > Does it make sense?
> 
> Not really. Your driver should not even bind to an interface which lacks
> the expected endpoints (rather than check this at a potentially later
> point in time when URBs are submitted).

The endpoint may exist but it may be invalid, as the problem is
triggered by a VM.  It doesn't parse but tries a fixed EP as it's no
compliant device.

> The new helper which Greg mentioned would allow this to implemented with
> just a few lines of code. Just add it to bcd2000_init_midi() or similar.  

Could you give an example?  Then I can ask Andrey whether such a call
really addresses the issue.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb/sound/bcd2000: warning in bcd2000_init_device

2017-10-04 Thread Takashi Iwai
On Wed, 04 Oct 2017 09:52:36 +0200,
Greg Kroah-Hartman wrote:
> 
> On Wed, Oct 04, 2017 at 08:10:59AM +0200, Takashi Iwai wrote:
> > On Tue, 03 Oct 2017 19:42:21 +0200,
> > Greg Kroah-Hartman wrote:
> > > 
> > > On Tue, Oct 03, 2017 at 12:50:08PM -0400, Alan Stern wrote:
> > > > On Tue, 3 Oct 2017, Takashi Iwai wrote:
> > > > 
> > > > > > It's a dev_WARN because it indicates a potentially serious error in 
> > > > > > the 
> > > > > > driver: The driver has submitted an interrupt URB to a bulk 
> > > > > > endpoint.  
> > > > > > That may not sound bad, but the same check gets triggered if a 
> > > > > > driver 
> > > > > > submits a bulk URB to an isochronous endpoint, or any other invalid 
> > > > > > combination.
> > > > > > 
> > > > > > Most likely the explanation here is that the driver doesn't bother 
> > > > > > to
> > > > > > check the endpoint type because it expects the endpoint will always 
> > > > > > be
> > > > > > interrupt.  But that is not a safe strategy.  USB devices and their
> > > > > > firmware should not be trusted unnecessarily.
> > > > > > 
> > > > > > The best fix is, like you said, to add a sanity check in the caller.
> > > > > 
> > > > > OK, but then do we have some handy helper for the check?
> > > > > As other bug reports by syzkaller suggest, there are a few other
> > > > > drivers that do the same, submitting a urb with naive assumption of
> > > > > the fixed EP for specific devices.  In the end we'll need to put the
> > > > > very same checks there in multiple places.
> > > > 
> > > > Perhaps we could add a helper routine that would take a list of 
> > > > expected endpoint types and check that the actual endpoints match the 
> > > > types.  But of course, all the drivers you're talking about would have 
> > > > to add a call to this helper routine.
> > > 
> > > We have almost this type of function, usb_find_common_endpoints(),
> > > what's wrong with using that?  Johan has already swept the tree and
> > > added a lot of these checks, odds are no one looked at the sound/
> > > subdir...
> > 
> > Well, what I had in my mind is just a snippet from usb_submit_urb(),
> > something like:
> > 
> > bool usb_sanity_check_urb_pipe(struct urb *urb)
> > {
> > struct usb_host_endpoint *ep;
> > int xfertype;
> > static const int pipetypes[4] = {
> > PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
> > };
> > 
> > ep = usb_pipe_endpoint(urb->dev, urb->pipe);
> > xfertype = usb_endpoint_type(&ep->desc);
> > return usb_pipetype(urb->pipe) != pipetypes[xfertype];
> > }
> > 
> > And calling this before usb_submit_urb() in each place that assigns
> > the fixed EP as device-specific quirks.
> > Does it make sense?
> 
> Yes, kind of, but checking the endpoint type/direction is what you are
> expecting it to be as you "know" what the type should be for each
> driver as it is unique.

Yes, it can be simplified, but if we want a common helper function,
this style would have an advantage that it can be used generically for
all drivers.

> Anyway, a "real" patch might make more sense to me.

I can cook up a patch if you find it a good idea to add such a common
function to usb core side.  OTOH, if each driver should open-code this
in each place, I can work on that, too.  Which would you prefer?


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb/sound/bcd2000: warning in bcd2000_init_device

2017-10-03 Thread Takashi Iwai
On Tue, 03 Oct 2017 19:42:21 +0200,
Greg Kroah-Hartman wrote:
> 
> On Tue, Oct 03, 2017 at 12:50:08PM -0400, Alan Stern wrote:
> > On Tue, 3 Oct 2017, Takashi Iwai wrote:
> > 
> > > > It's a dev_WARN because it indicates a potentially serious error in the 
> > > > driver: The driver has submitted an interrupt URB to a bulk endpoint.  
> > > > That may not sound bad, but the same check gets triggered if a driver 
> > > > submits a bulk URB to an isochronous endpoint, or any other invalid 
> > > > combination.
> > > > 
> > > > Most likely the explanation here is that the driver doesn't bother to
> > > > check the endpoint type because it expects the endpoint will always be
> > > > interrupt.  But that is not a safe strategy.  USB devices and their
> > > > firmware should not be trusted unnecessarily.
> > > > 
> > > > The best fix is, like you said, to add a sanity check in the caller.
> > > 
> > > OK, but then do we have some handy helper for the check?
> > > As other bug reports by syzkaller suggest, there are a few other
> > > drivers that do the same, submitting a urb with naive assumption of
> > > the fixed EP for specific devices.  In the end we'll need to put the
> > > very same checks there in multiple places.
> > 
> > Perhaps we could add a helper routine that would take a list of 
> > expected endpoint types and check that the actual endpoints match the 
> > types.  But of course, all the drivers you're talking about would have 
> > to add a call to this helper routine.
> 
> We have almost this type of function, usb_find_common_endpoints(),
> what's wrong with using that?  Johan has already swept the tree and
> added a lot of these checks, odds are no one looked at the sound/
> subdir...

Well, what I had in my mind is just a snippet from usb_submit_urb(),
something like:

bool usb_sanity_check_urb_pipe(struct urb *urb)
{
struct usb_host_endpoint *ep;
int xfertype;
static const int pipetypes[4] = {
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
};

ep = usb_pipe_endpoint(urb->dev, urb->pipe);
xfertype = usb_endpoint_type(&ep->desc);
return usb_pipetype(urb->pipe) != pipetypes[xfertype];
}

And calling this before usb_submit_urb() in each place that assigns
the fixed EP as device-specific quirks.
Does it make sense?


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb/sound/bcd2000: warning in bcd2000_init_device

2017-10-03 Thread Takashi Iwai
On Tue, 03 Oct 2017 16:21:57 +0200,
Alan Stern wrote:
> 
> On Tue, 3 Oct 2017, Takashi Iwai wrote:
> 
> > On Mon, 25 Sep 2017 14:39:51 +0200,
> > Andrey Konovalov wrote:
> > > 
> > > Hi!
> > > 
> > > I've got the following report while fuzzing the kernel with syzkaller.
> > > 
> > > On commit e19b205be43d11bff638cad4487008c48d21c103 (4.14-rc2).
> > > 
> > > It seems that there's no check of the endpoint type.
> > > 
> > > usb 1-1: BOGUS urb xfer, pipe 1 != type 3
> > > [ cut here ]
> > > WARNING: CPU: 0 PID: 1846 at drivers/usb/core/urb.c:449
> > 
> > How is this bug triggered?  As it's syzkaller with QEMU, it looks
> > hitting an inconsistent state the driver didn't expect (it sets the
> > fixed endpoint), then USB-core detects the inconsistency and spews the
> > kernel warning with stack trace.  If so, it's no serious problem as it
> > appears.
> > 
> > Suppose my guess is right, I'm not sure what's the best way to fix
> > this.  Certainly we can add more sanity check in the caller side.
> > OTOH, I find the reaction of USB core too aggressive, it's not
> > necessary to be dev_WARN() but a normal dev_err().
> > Or I might be looking at a wrong place?
> 
> It's a dev_WARN because it indicates a potentially serious error in the 
> driver: The driver has submitted an interrupt URB to a bulk endpoint.  
> That may not sound bad, but the same check gets triggered if a driver 
> submits a bulk URB to an isochronous endpoint, or any other invalid 
> combination.
> 
> Most likely the explanation here is that the driver doesn't bother to
> check the endpoint type because it expects the endpoint will always be
> interrupt.  But that is not a safe strategy.  USB devices and their
> firmware should not be trusted unnecessarily.
> 
> The best fix is, like you said, to add a sanity check in the caller.

OK, but then do we have some handy helper for the check?
As other bug reports by syzkaller suggest, there are a few other
drivers that do the same, submitting a urb with naive assumption of
the fixed EP for specific devices.  In the end we'll need to put the
very same checks there in multiple places.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb/sound/bcd2000: warning in bcd2000_init_device

2017-10-03 Thread Takashi Iwai
On Mon, 25 Sep 2017 14:39:51 +0200,
Andrey Konovalov wrote:
> 
> Hi!
> 
> I've got the following report while fuzzing the kernel with syzkaller.
> 
> On commit e19b205be43d11bff638cad4487008c48d21c103 (4.14-rc2).
> 
> It seems that there's no check of the endpoint type.
> 
> usb 1-1: BOGUS urb xfer, pipe 1 != type 3
> [ cut here ]
> WARNING: CPU: 0 PID: 1846 at drivers/usb/core/urb.c:449

How is this bug triggered?  As it's syzkaller with QEMU, it looks
hitting an inconsistent state the driver didn't expect (it sets the
fixed endpoint), then USB-core detects the inconsistency and spews the
kernel warning with stack trace.  If so, it's no serious problem as it
appears.

Suppose my guess is right, I'm not sure what's the best way to fix
this.  Certainly we can add more sanity check in the caller side.
OTOH, I find the reaction of USB core too aggressive, it's not
necessary to be dev_WARN() but a normal dev_err().
Or I might be looking at a wrong place?

Adding USB guys to Cc for hearing their comments.


thanks,

Takashi


> usb_submit_urb+0xf8a/0x11d0
> Modules linked in:
> CPU: 0 PID: 1846 Comm: kworker/0:2 Not tainted
> 4.14.0-rc2-42613-g1488251d1a98 #238
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
> Workqueue: usb_hub_wq hub_event
> task: 880064296300 task.stack: 8800643b
> RIP: 0010:usb_submit_urb+0xf8a/0x11d0 drivers/usb/core/urb.c:448
> RSP: 0018:8800643b6140 EFLAGS: 00010286
> RAX: 0029 RBX: 880063842400 RCX: 
> RDX: 0029 RSI: 85a58800 RDI: ed000c876c1a
> RBP: 8800643b6240 R08: 11000c876ac0 R09: 
> R10:  R11:  R12: 11000c876c2f
> R13: 0003 R14: 0001 R15: 88006325c768
> FS:  () GS:88006c80() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 7fa2a51c CR3: 6acc8000 CR4: 06f0
> Call Trace:
>  bcd2000_init_device sound/usb/bcd2000/bcd2000.c:289
>  bcd2000_init_midi sound/usb/bcd2000/bcd2000.c:345
>  bcd2000_probe+0xe64/0x19e0 sound/usb/bcd2000/bcd2000.c:406
>  usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
>  really_probe drivers/base/dd.c:413
>  driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
>  __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
>  bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
>  __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
>  device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
>  bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
>  device_add+0xd0b/0x1660 drivers/base/core.c:1835
>  usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
>  generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
>  usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
>  really_probe drivers/base/dd.c:413
>  driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
>  __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
>  bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
>  __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
>  device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
>  bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
>  device_add+0xd0b/0x1660 drivers/base/core.c:1835
>  usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
>  hub_port_connect drivers/usb/core/hub.c:4903
>  hub_port_connect_change drivers/usb/core/hub.c:5009
>  port_event drivers/usb/core/hub.c:5115
>  hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
>  process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119
>  worker_thread+0x221/0x1850 kernel/workqueue.c:2253
>  kthread+0x3a1/0x470 kernel/kthread.c:231
>  ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
> Code: 48 8b 85 30 ff ff ff 48 8d b8 98 00 00 00 e8 6e 91 8b ff 45 89
> e8 44 89 f1 4c 89 fa 48 89 c6 48 c7 c7 c0 5a c8 85 e8 10 50 dd fd <0f>
> ff e9 9b f7 ff ff e8 ba cf 26 fe e9 80 f7 ff ff e8 a0 a5 f4
> ---[ end trace bad127706d5fe2d6 ]---
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [alsa-devel] [PATCH] ALSA: hda - Fix applying MSI dual-codec mobo quirk

2017-06-01 Thread Takashi Iwai
On Thu, 01 Jun 2017 22:58:24 +0200,
Takashi Iwai wrote:
> 
> The previous commit [63691587f7b0: ALSA: hda - Apply dual-codec quirk
> for MSI Z270-Gaming mobo] attempted to apply the existing dual-codec
> quirk for a MSI mobo.  But it turned out that this isn't applied
> properly due to the MSI-vendor quirk before this entry.  I overlooked
> such two MSI entries just because they were put in the wrong position,
> although we have a list ordered by PCI SSID numbers.
> 
> This patch fixes it by rearranging the unordered entries.
> 
> Fixes: 63691587f7b0 ("ALSA: hda - Apply dual-codec quirk for MSI Z270-Gaming 
> mobo")
> Reported-by: Rudolf Schmidt 
> Signed-off-by: Takashi Iwai 

Gah, an irrelevant patch I wanted to submit slipped into the patch
series.  Please disregard one, sorry.


Takashi

> ---
>  sound/pci/hda/patch_realtek.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index 918e45268915..a57988d617e9 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -2324,11 +2324,11 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] 
> = {
>   SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
>  
>   SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
> - SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
> - SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
>   SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", 
> ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
>   SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", 
> ALC1220_FIXUP_GB_DUAL_CODECS),
> + SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
>   SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", 
> ALC1220_FIXUP_GB_DUAL_CODECS),
> + SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
>   SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", 
> ALC882_FIXUP_ABIT_AW9D_MAX),
>   SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
>   SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
> -- 
> 2.13.0
> 
> ___
> Alsa-devel mailing list
> alsa-de...@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 02/27] ALSA: pcm: Introduce copy_user, copy_kernel and fill_silence ops

2017-06-01 Thread Takashi Iwai
For supporting the explicit in-kernel copy of PCM buffer data, and
also for further code refactoring, three new PCM ops, copy_user,
copy_kernel and fill_silence, are introduced.  The old copy and
silence ops will be deprecated and removed later once when all callers
are converted.

The copy_kernel ops is the new one, and it's supposed to transfer the
PCM data from the given kernel buffer to the hardware ring-buffer (or
vice-versa depending on the stream direction), while the copy_user ops
is equivalent with the former copy ops, to transfer the data from the
user-space buffer.

The major difference of the new copy_* and fill_silence ops from the
previous ops is that the new ops take bytes instead of frames for size
and position arguments.  It has two merits: first, it allows the
callback implementation often simpler (just call directly memcpy() &
co), and second, it may unify the implementations of both interleaved
and non-interleaved cases, as we'll see in the later patch.

As of this stage, copy_kernel ops isn't referred yet, but only
copy_user is used.

Signed-off-by: Takashi Iwai 
---
 include/sound/pcm.h  |  7 +
 sound/core/pcm_lib.c | 89 +++-
 sound/soc/soc-pcm.c  |  3 ++
 3 files changed, 84 insertions(+), 15 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index c609b891c4c2..a065415191d8 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -83,6 +83,13 @@ struct snd_pcm_ops {
void __user *buf, snd_pcm_uframes_t count);
int (*silence)(struct snd_pcm_substream *substream, int channel, 
   snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
+   int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
+   unsigned long pos, unsigned long bytes);
+   int (*copy_user)(struct snd_pcm_substream *substream, int channel,
+unsigned long pos, void __user *buf,
+unsigned long bytes);
+   int (*copy_kernel)(struct snd_pcm_substream *substream, int channel,
+  unsigned long pos, void *buf, unsigned long bytes);
struct page *(*page)(struct snd_pcm_substream *substream,
 unsigned long offset);
int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct 
*vma);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index ab4b1d1e44ee..9334fc2c20c8 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -55,6 +55,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
 {
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t frames, ofs, transfer;
+   char *hwbuf;
+   int err;
 
if (runtime->silence_size < runtime->boundary) {
snd_pcm_sframes_t noise_dist, n;
@@ -109,27 +111,37 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
transfer = ofs + frames > runtime->buffer_size ? 
runtime->buffer_size - ofs : frames;
if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-   if (substream->ops->silence) {
-   int err;
+   if (substream->ops->fill_silence) {
+   err = substream->ops->fill_silence(substream, 0,
+  
frames_to_bytes(runtime, ofs),
+  
frames_to_bytes(runtime, transfer));
+   snd_BUG_ON(err < 0);
+   } else if (substream->ops->silence) {
err = substream->ops->silence(substream, -1, 
ofs, transfer);
snd_BUG_ON(err < 0);
} else {
-   char *hwbuf = runtime->dma_area + 
frames_to_bytes(runtime, ofs);
+   hwbuf = runtime->dma_area + 
frames_to_bytes(runtime, ofs);
snd_pcm_format_set_silence(runtime->format, 
hwbuf, transfer * runtime->channels);
}
} else {
unsigned int c;
unsigned int channels = runtime->channels;
-   if (substream->ops->silence) {
+   if (substream->ops->fill_silence) {
+   for (c = 0; c < channels; ++c) {
+   err = 
substream->ops->fill_silence(substream, c,
+  
samples_to_bytes(runtime

[PATCH v2 12/27] ALSA: sb: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
For avoiding the code redundancy, slightly hackish macros are
introduced.

Signed-off-by: Takashi Iwai 
---
 sound/isa/sb/emu8000_pcm.c | 190 ++---
 1 file changed, 109 insertions(+), 81 deletions(-)

diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index c480024422af..2ee8d67871ec 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -422,121 +422,148 @@ do { \
return -EAGAIN;\
 } while (0)
 
+enum {
+   COPY_USER, COPY_KERNEL, FILL_SILENCE,
+};
+
+#define GET_VAL(sval, buf, mode)   \
+   do {\
+   switch (mode) { \
+   case FILL_SILENCE:  \
+   sval = 0;   \
+   break;  \
+   case COPY_KERNEL:   \
+   sval = *buf++;  \
+   break;  \
+   default:\
+   if (get_user(sval, (unsigned short __user *)buf)) \
+   return -EFAULT; \
+   buf++;  \
+   break;  \
+   }   \
+   } while (0)
 
 #ifdef USE_NONINTERLEAVE
-/* copy one channel block */
-static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned 
short *buf, int count)
-{
-   EMU8000_SMALW_WRITE(emu, offset);
-   while (count > 0) {
-   unsigned short sval;
-   CHECK_SCHEDULER();
-   if (get_user(sval, buf))
-   return -EFAULT;
-   EMU8000_SMLD_WRITE(emu, sval);
-   buf++;
-   count--;
-   }
-   return 0;
-}
 
+#define LOOP_WRITE(rec, offset, _buf, count, mode) \
+   do {\
+   struct snd_emu8000 *emu = (rec)->emu;   \
+   unsigned short *buf = (unsigned short *)(_buf); \
+   snd_emu8000_write_wait(emu, 1); \
+   EMU8000_SMALW_WRITE(emu, offset);   \
+   while (count > 0) { \
+   unsigned short sval;\
+   CHECK_SCHEDULER();  \
+   GET_VAL(sval, buf, mode);   \
+   EMU8000_SMLD_WRITE(emu, sval);  \
+   count--;\
+   }   \
+   } while (0)
+
+/* copy one channel block */
 static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
- int voice,
- snd_pcm_uframes_t pos,
- void *src,
- snd_pcm_uframes_t count)
+ int voice, unsigned long pos,
+ void __user *src, unsigned long count)
 {
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
-   struct snd_emu8000 *emu = rec->emu;
 
-   snd_emu8000_write_wait(emu, 1);
-   return emu8k_transfer_block(emu, pos + rec->loop_start[voice], src,
-   count);
+   /* convert to word unit */
+   pos = (pos << 1) + rec->loop_start[voice];
+   count <<= 1;
+   LOOP_WRITE(rec, pos, src, count, COPY_UESR);
+   return 0;
 }
 
-/* make a channel block silence */
-static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count)
+static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs,
+int voice, unsigned long pos,
+void *src, unsigned long count)
 {
-   EMU8000_SMALW_WRITE(emu, offset);
-   while (count > 0) {
-   CHECK_SCHEDULER();
-   EMU8000_SMLD_WRITE(emu, 0);
-   count--;
-   }
+   struct snd_emu8k_pcm *rec = subs->runtime->private_data;
+
+   /* convert to word unit */
+   pos = (pos << 1) + rec->loop_start[voice];
+   count <<= 1;
+   LOOP_WRITE(rec, pos, src, count, COPY_KERNEL);
return 0;
 }
 
+/* make a channel block silence */
 static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
-int voice,
-snd_pcm_uframes

[PATCH v2 03/27] ALSA: dummy: Convert to new PCM copy ops

2017-06-01 Thread Takashi Iwai
It's a dummy ops, so just replacing it.

Signed-off-by: Takashi Iwai 
---
 sound/drivers/dummy.c | 20 ++--
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 172dacd925f5..dd5ed037adf2 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -644,15 +644,22 @@ static int alloc_fake_buffer(void)
 }
 
 static int dummy_pcm_copy(struct snd_pcm_substream *substream,
- int channel, snd_pcm_uframes_t pos,
- void __user *dst, snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long bytes)
+{
+   return 0; /* do nothing */
+}
+
+static int dummy_pcm_copy_kernel(struct snd_pcm_substream *substream,
+int channel, unsigned long pos,
+void *dst, unsigned long bytes)
 {
return 0; /* do nothing */
 }
 
 static int dummy_pcm_silence(struct snd_pcm_substream *substream,
-int channel, snd_pcm_uframes_t pos,
-snd_pcm_uframes_t count)
+int channel, unsigned long pos,
+unsigned long bytes)
 {
return 0; /* do nothing */
 }
@@ -683,8 +690,9 @@ static struct snd_pcm_ops dummy_pcm_ops_no_buf = {
.prepare =  dummy_pcm_prepare,
.trigger =  dummy_pcm_trigger,
.pointer =  dummy_pcm_pointer,
-   .copy = dummy_pcm_copy,
-   .silence =  dummy_pcm_silence,
+   .copy_user =dummy_pcm_copy,
+   .copy_kernel =  dummy_pcm_copy_kernel,
+   .fill_silence = dummy_pcm_silence,
.page = dummy_pcm_page,
 };
 
-- 
2.13.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] ALSA: hda - Fix applying MSI dual-codec mobo quirk

2017-06-01 Thread Takashi Iwai
The previous commit [63691587f7b0: ALSA: hda - Apply dual-codec quirk
for MSI Z270-Gaming mobo] attempted to apply the existing dual-codec
quirk for a MSI mobo.  But it turned out that this isn't applied
properly due to the MSI-vendor quirk before this entry.  I overlooked
such two MSI entries just because they were put in the wrong position,
although we have a list ordered by PCI SSID numbers.

This patch fixes it by rearranging the unordered entries.

Fixes: 63691587f7b0 ("ALSA: hda - Apply dual-codec quirk for MSI Z270-Gaming 
mobo")
Reported-by: Rudolf Schmidt 
Signed-off-by: Takashi Iwai 
---
 sound/pci/hda/patch_realtek.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 918e45268915..a57988d617e9 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2324,11 +2324,11 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
 
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
-   SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
-   SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", 
ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", 
ALC1220_FIXUP_GB_DUAL_CODECS),
+   SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", 
ALC1220_FIXUP_GB_DUAL_CODECS),
+   SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", 
ALC882_FIXUP_ABIT_AW9D_MAX),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
-- 
2.13.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 15/27] [media] solo6x10: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
The device supports only 1 channel and 8bit sample, so it's always
bytes=frames, and we need no conversion of unit in the callback.
Also, it's a capture stream, thus no silence is needed.

Signed-off-by: Takashi Iwai 
---
 drivers/media/pci/solo6x10/solo6x10-g723.c | 32 ++
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c 
b/drivers/media/pci/solo6x10/solo6x10-g723.c
index 36e93540bb49..3ca947092775 100644
--- a/drivers/media/pci/solo6x10/solo6x10-g723.c
+++ b/drivers/media/pci/solo6x10/solo6x10-g723.c
@@ -223,9 +223,9 @@ static snd_pcm_uframes_t snd_solo_pcm_pointer(struct 
snd_pcm_substream *ss)
return idx * G723_FRAMES_PER_PAGE;
 }
 
-static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel,
-snd_pcm_uframes_t pos, void __user *dst,
-snd_pcm_uframes_t count)
+static int __snd_solo_pcm_copy(struct snd_pcm_substream *ss,
+  unsigned long pos, void *dst,
+  unsigned long count, bool in_kernel)
 {
struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
struct solo_dev *solo_dev = solo_pcm->solo_dev;
@@ -242,16 +242,31 @@ static int snd_solo_pcm_copy(struct snd_pcm_substream 
*ss, int channel,
if (err)
return err;
 
-   err = copy_to_user(dst + (i * G723_PERIOD_BYTES),
-  solo_pcm->g723_buf, G723_PERIOD_BYTES);
-
-   if (err)
+   if (in_kernel)
+   memcpy(dst, solo_pcm->g723_buf, G723_PERIOD_BYTES);
+   else if (copy_to_user((void __user *)dst,
+ solo_pcm->g723_buf, G723_PERIOD_BYTES))
return -EFAULT;
+   dst += G723_PERIOD_BYTES;
}
 
return 0;
 }
 
+static int snd_solo_pcm_copy_user(struct snd_pcm_substream *ss, int channel,
+ unsigned long pos, void __user *dst,
+ unsigned long count)
+{
+   return __snd_solo_pcm_copy(ss, pos, (void *)dst, count, false);
+}
+
+static int snd_solo_pcm_copy_kernel(struct snd_pcm_substream *ss, int channel,
+   unsigned long pos, void *dst,
+   unsigned long count)
+{
+   return __snd_solo_pcm_copy(ss, pos, dst, count, true);
+}
+
 static const struct snd_pcm_ops snd_solo_pcm_ops = {
.open = snd_solo_pcm_open,
.close = snd_solo_pcm_close,
@@ -261,7 +276,8 @@ static const struct snd_pcm_ops snd_solo_pcm_ops = {
.prepare = snd_solo_pcm_prepare,
.trigger = snd_solo_pcm_trigger,
.pointer = snd_solo_pcm_pointer,
-   .copy = snd_solo_pcm_copy,
+   .copy_user = snd_solo_pcm_copy_user,
+   .copy_kernel = snd_solo_pcm_copy_kernel,
 };
 
 static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol,
-- 
2.13.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 04/27] ALSA: es1938: Convert to the new PCM copy ops

2017-06-01 Thread Takashi Iwai
Replace the copy ops with the new copy_user and copy_kernel ops.
It's used only for a capture stream (for some hardware workaround),
thus we need no silence operation.

Signed-off-by: Takashi Iwai 
---
 sound/pci/es1938.c | 33 +
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index e8d943071a8c..a544cd52f73a 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -839,15 +839,12 @@ static snd_pcm_uframes_t 
snd_es1938_playback_pointer(struct snd_pcm_substream *s
 }
 
 static int snd_es1938_capture_copy(struct snd_pcm_substream *substream,
-  int channel,
-  snd_pcm_uframes_t pos,
-  void __user *dst,
-  snd_pcm_uframes_t count)
+  int channel, unsigned long pos,
+  void __user *dst, unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct es1938 *chip = snd_pcm_substream_chip(substream);
-   pos <<= chip->dma1_shift;
-   count <<= chip->dma1_shift;
+
if (snd_BUG_ON(pos + count > chip->dma1_size))
return -EINVAL;
if (pos + count < chip->dma1_size) {
@@ -856,12 +853,31 @@ static int snd_es1938_capture_copy(struct 
snd_pcm_substream *substream,
} else {
if (copy_to_user(dst, runtime->dma_area + pos + 1, count - 1))
return -EFAULT;
-   if (put_user(runtime->dma_area[0], ((unsigned char __user 
*)dst) + count - 1))
+   if (put_user(runtime->dma_area[0],
+((unsigned char __user *)dst) + count - 1))
return -EFAULT;
}
return 0;
 }
 
+static int snd_es1938_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct es1938 *chip = snd_pcm_substream_chip(substream);
+
+   if (snd_BUG_ON(pos + count > chip->dma1_size))
+   return -EINVAL;
+   if (pos + count < chip->dma1_size) {
+   memcpy(dst, runtime->dma_area + pos + 1, count);
+   } else {
+   memcpy(dst, runtime->dma_area + pos + 1, count - 1);
+   runtime->dma_area[0] = *((unsigned char *)dst + count - 1);
+   }
+   return 0;
+}
+
 /*
  * buffer management
  */
@@ -1012,7 +1028,8 @@ static const struct snd_pcm_ops snd_es1938_capture_ops = {
.prepare =  snd_es1938_capture_prepare,
.trigger =  snd_es1938_capture_trigger,
.pointer =  snd_es1938_capture_pointer,
-   .copy = snd_es1938_capture_copy,
+   .copy_user =snd_es1938_capture_copy,
+   .copy_kernel =  snd_es1938_capture_copy_kernel,
 };
 
 static int snd_es1938_new_pcm(struct es1938 *chip, int device)
-- 
2.13.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 10/27] ALSA: hdsp: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
The conversion is straightforward with standard helper functions.

Signed-off-by: Takashi Iwai 
---
 sound/pci/rme9652/hdsp.c | 67 
 1 file changed, 50 insertions(+), 17 deletions(-)

diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index fc0face6cdc6..b9644e0e 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -3913,42 +3913,73 @@ static char *hdsp_channel_buffer_location(struct hdsp 
*hdsp,
return hdsp->playback_buffer + (mapped_channel * 
HDSP_CHANNEL_BUFFER_BYTES);
 }
 
-static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int 
channel,
- snd_pcm_uframes_t pos, void __user *src, 
snd_pcm_uframes_t count)
+static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *src, unsigned long count)
 {
struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
 
-   if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4))
+   if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES))
return -EINVAL;
 
channel_buf = hdsp_channel_buffer_location (hdsp, 
substream->pstr->stream, channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_from_user(channel_buf + pos * 4, src, count * 4))
+   if (copy_from_user(channel_buf + pos, src, count))
return -EFAULT;
-   return count;
+   return 0;
 }
 
-static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int 
channel,
-snd_pcm_uframes_t pos, void __user *dst, 
snd_pcm_uframes_t count)
+static int snd_hdsp_playback_copy_kernel(struct snd_pcm_substream *substream,
+int channel, unsigned long pos,
+void *src, unsigned long count)
 {
struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
 
-   if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4))
+   channel_buf = hdsp_channel_buffer_location(hdsp, 
substream->pstr->stream, channel);
+   if (snd_BUG_ON(!channel_buf))
+   return -EIO;
+   memcpy(channel_buf + pos, src, count);
+   return 0;
+}
+
+static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream,
+int channel, unsigned long pos,
+void __user *dst, unsigned long count)
+{
+   struct hdsp *hdsp = snd_pcm_substream_chip(substream);
+   char *channel_buf;
+
+   if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES))
return -EINVAL;
 
channel_buf = hdsp_channel_buffer_location (hdsp, 
substream->pstr->stream, channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
+   if (copy_to_user(dst, channel_buf + pos, count))
return -EFAULT;
-   return count;
+   return 0;
 }
 
-static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int 
channel,
- snd_pcm_uframes_t pos, snd_pcm_uframes_t 
count)
+static int snd_hdsp_capture_copy_kernel(struct snd_pcm_substream *substream,
+   int channel, unsigned long pos,
+   void *dst, unsigned long count)
+{
+   struct hdsp *hdsp = snd_pcm_substream_chip(substream);
+   char *channel_buf;
+
+   channel_buf = hdsp_channel_buffer_location(hdsp, 
substream->pstr->stream, channel);
+   if (snd_BUG_ON(!channel_buf))
+   return -EIO;
+   memcpy(dst, channel_buf + pos, count);
+   return 0;
+}
+
+static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  unsigned long count)
 {
struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
@@ -3956,8 +3987,8 @@ static int snd_hdsp_hw_silence(struct snd_pcm_substream 
*substream, int channel,
channel_buf = hdsp_channel_buffer_location (hdsp, 
substream->pstr->stream, channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   memset(channel_buf + pos * 4, 0, count * 4);
-   return count;
+   memset(channel_buf + pos, 0, count);
+   return 0;
 }
 
 static int snd_hdsp_reset(struct snd_pcm_substream *substream)
@@ -4869,8 +4900,9 @@ static const struct snd_pcm_ops snd_hdsp_playback_ops = {
.prepare =  snd_hdsp_prepare,
.trigger =  snd_hdsp_trigger,
.pointer =  snd_hdsp_hw_pointer,
-   .copy = snd_hdsp_playback_copy

[PATCH v2 08/27] ALSA: rme96: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
The conversion is straightforward with standard helper functions, and
now we can drop the bytes <-> frames conversions in callbacks.

Signed-off-by: Takashi Iwai 
---
 sound/pci/rme96.c | 70 ++-
 1 file changed, 44 insertions(+), 26 deletions(-)

diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 05b9da30990d..24f1349a8e1b 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -327,13 +327,10 @@ snd_rme96_capture_ptr(struct rme96 *rme96)
 
 static int
 snd_rme96_playback_silence(struct snd_pcm_substream *substream,
-  int channel, /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  snd_pcm_uframes_t count)
+  int channel, unsigned long pos, unsigned long count)
 {
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
-   count <<= rme96->playback_frlog;
-   pos <<= rme96->playback_frlog;
+
memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
  0, count);
return 0;
@@ -341,32 +338,49 @@ snd_rme96_playback_silence(struct snd_pcm_substream 
*substream,
 
 static int
 snd_rme96_playback_copy(struct snd_pcm_substream *substream,
-   int channel, /* not used (interleaved data) */
-   snd_pcm_uframes_t pos,
-   void __user *src,
-   snd_pcm_uframes_t count)
+   int channel, unsigned long pos,
+   void __user *src, unsigned long count)
 {
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
-   count <<= rme96->playback_frlog;
-   pos <<= rme96->playback_frlog;
-   return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, 
src,
-  count);
+
+   return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
+  src, count);
+}
+
+static int
+snd_rme96_playback_copy_kernel(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void *src, unsigned long count)
+{
+   struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+
+   memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, count);
+   return 0;
 }
 
 static int
 snd_rme96_capture_copy(struct snd_pcm_substream *substream,
-  int channel, /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  void __user *dst,
-  snd_pcm_uframes_t count)
+  int channel, unsigned long pos,
+  void __user *dst, unsigned long count)
 {
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
-   count <<= rme96->capture_frlog;
-   pos <<= rme96->capture_frlog;
-   return copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + 
pos,
+
+   return copy_to_user_fromio(dst,
+  rme96->iobase + RME96_IO_REC_BUFFER + pos,
   count);
 }
 
+static int
+snd_rme96_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+   struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+
+   memcpy_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, count);
+   return 0;
+}
+
 /*
  * Digital output capabilities (S/PDIF)
  */
@@ -1513,8 +1527,9 @@ static const struct snd_pcm_ops 
snd_rme96_playback_spdif_ops = {
.prepare =  snd_rme96_playback_prepare,
.trigger =  snd_rme96_playback_trigger,
.pointer =  snd_rme96_playback_pointer,
-   .copy = snd_rme96_playback_copy,
-   .silence =  snd_rme96_playback_silence,
+   .copy_user =snd_rme96_playback_copy,
+   .copy_kernel =  snd_rme96_playback_copy_kernel,
+   .fill_silence = snd_rme96_playback_silence,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1526,7 +1541,8 @@ static const struct snd_pcm_ops 
snd_rme96_capture_spdif_ops = {
.prepare =  snd_rme96_capture_prepare,
.trigger =  snd_rme96_capture_trigger,
.pointer =  snd_rme96_capture_pointer,
-   .copy = snd_rme96_capture_copy,
+   .copy_user =snd_rme96_capture_copy,
+   .copy_kernel =  snd_rme96_capture_copy_kernel,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1538,8 +1554,9 @@ static const struct snd_pcm_ops 
snd_rme96_playback_adat_ops = {
.prepare =  snd_rme96_playback_prepare,
.trigger =  snd_rme96_playback_trigger,
.pointer =  snd_rme96_playback_pointer,
-   .copy =   

[PATCH v2 14/27] ASoC: blackfin: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
In AC97 and I2S-TDM mode, we need to convert back to frames, but
otherwise the conversion is pretty straightforward.

Signed-off-by: Takashi Iwai 
---
 sound/soc/blackfin/bf5xx-ac97-pcm.c | 27 +++
 sound/soc/blackfin/bf5xx-i2s-pcm.c  | 36 
 2 files changed, 43 insertions(+), 20 deletions(-)

diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c 
b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 02ad2606fa19..913e29275f4e 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -279,23 +279,33 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream 
*substream,
return 0 ;
 }
 #else
-static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos,
-   void __user *buf, snd_pcm_uframes_t count)
+static int bf5xx_pcm_copy(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void *buf, unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
+   struct ac97_frame *dst;
+
pr_debug("%s copy pos:0x%lx count:0x%lx\n",
substream->stream ? "Capture" : "Playback", pos, count);
+   dst = (struct ac97_frame *)runtime->dma_area +
+   bytes_to_frames(runtime, pos);
+   count = bytes_to_frames(runtime, count);
 
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-   bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos,
-   (__u16 *)buf, count, chan_mask);
+   bf5xx_pcm_to_ac97(dst, buf, count, chan_mask);
else
-   bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos,
-   (__u16 *)buf, count);
+   bf5xx_ac97_to_pcm(dst, buf, count);
return 0;
 }
+
+static int bf5xx_pcm_copy_user(struct snd_pcm_substream *substream,
+   int channel, unsigned long pos,
+   void __user *buf, unsigned long count)
+{
+   return bf5xx_pcm_copy(substream, channel, pos, (void *)buf, count);
+}
 #endif
 
 static struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
@@ -309,7 +319,8 @@ static struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
 #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
.mmap   = bf5xx_pcm_mmap,
 #else
-   .copy   = bf5xx_pcm_copy,
+   .copy_user  = bf5xx_pcm_copy_user,
+   .copy_kernel= bf5xx_pcm_copy,
 #endif
 };
 
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c 
b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 6cba211da32e..470d99abf6f6 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -225,8 +225,9 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream 
*substream,
return 0 ;
 }
 
-static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
+static int bf5xx_pcm_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *buf, unsigned long count)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -238,6 +239,8 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream 
*substream, int channel,
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
if (dma_data->tdm_mode) {
+   pos = bytes_to_frames(runtime, pos);
+   count = bytes_to_frames(runtime, count);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
src = buf;
dst = runtime->dma_area;
@@ -269,21 +272,29 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream 
*substream, int channel,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
src = buf;
dst = runtime->dma_area;
-   dst += frames_to_bytes(runtime, pos);
+   dst += pos;
} else {
src = runtime->dma_area;
-   src += frames_to_bytes(runtime, pos);
+   src += pos;
dst = buf;
}
 
-   memcpy(dst, src, frames_to_bytes(runtime, count));
+   memcpy(dst, src, count);
}
 
return 0;
 }
 
+static int bf5xx_pcm_copy_user(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void __user *buf, unsigned long count)
+{
+   return bf5xx_pcm_copy(substream, channel, pos, (v

[PATCH v2 20/27] ALSA: pcm: More unification of PCM transfer codes

2017-06-01 Thread Takashi Iwai
This patch proceeds more abstraction of PCM read/write loop codes.

For both interleaved and non-interleaved transfers, the same copy or
silence transfer code (which is defined as pcm_transfer_f) is used
now.  This became possible since we switched to byte size to copy_*
and fill_silence ops argument instead of frames.

And, for both read and write, we can use the same copy function (which
is defined as pcm_copy_f), just depending on whether interleaved or
non-interleaved mode.

The transfer function is determined at the beginning of the loop,
depending on whether the driver gives the specific copy ops or it's
the standard read/write.

Another bonus by this change is that we now guarantee the silencing
behavior when NULL buffer is passed to write helpers.  It'll simplify
some codes later.

Signed-off-by: Takashi Iwai 
---
 sound/core/pcm_lib.c | 254 +--
 1 file changed, 123 insertions(+), 131 deletions(-)

diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 1bd7244324d5..eb9cbc2d9d7b 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1991,77 +1991,100 @@ static int wait_for_avail(struct snd_pcm_substream 
*substream,
return err;
 }

-typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int 
hwoff,
- void  *data, unsigned int off,
- snd_pcm_uframes_t size);
+typedef int (*pcm_transfer_f)(struct snd_pcm_substream *substream,
+ int channel, unsigned long hwoff,
+ void *buf, unsigned long bytes);
 
-static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
- unsigned int hwoff,
- void *data, unsigned int off,
- snd_pcm_uframes_t frames)
+typedef int (*pcm_copy_f)(struct snd_pcm_substream *, snd_pcm_uframes_t, void 
*,
+ snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f);
+
+/* calculate the target DMA-buffer position to be written/read */
+static void *get_dma_ptr(struct snd_pcm_runtime *runtime,
+  int channel, unsigned long hwoff)
+{
+   return runtime->dma_area + hwoff +
+   channel * (runtime->dma_bytes / runtime->channels);
+}
+
+/* default copy_user ops for write */
+static int default_write_copy_user(struct snd_pcm_substream *substream,
+  int channel, unsigned long hwoff,
+  void __user *buf, unsigned long bytes)
+{
+   if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff),
+  buf, bytes))
+   return -EFAULT;
+   return 0;
+}
+
+/* fill silence instead of copy data; called as a transfer helper
+ * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when
+ * a NULL buffer is passed
+ */
+static int fill_silence(struct snd_pcm_substream *substream, int channel,
+   unsigned long hwoff, void *buf, unsigned long bytes)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
-   int err;
-   char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
-   if (substream->ops->copy_user) {
-   hwoff = frames_to_bytes(runtime, hwoff);
-   frames = frames_to_bytes(runtime, frames);
-   err = substream->ops->copy_user(substream, 0, hwoff, buf, 
frames);
-   if (err < 0)
-   return err;
-   } else {
-   char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, 
hwoff);
-   if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, 
frames)))
-   return -EFAULT;
-   }
+
+   if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+   return 0;
+   if (substream->ops->fill_silence)
+   return substream->ops->fill_silence(substream, channel,
+   hwoff, bytes);
+
+   snd_pcm_format_set_silence(runtime->format,
+  get_dma_ptr(runtime, channel, hwoff),
+  bytes_to_samples(runtime, bytes));
return 0;
 }
- 
-static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
-  unsigned int hwoff,
-  void *data, unsigned int off,
-  snd_pcm_uframes_t frames)
+
+/* call transfer function with the converted pointers and sizes;
+ * for interleaved mode, it's one shot for all samples
+ */
+static int interleaved_copy(struct snd_pcm_substream *substream,
+   snd_pcm_uframes_t hwoff, void *data,
+   snd_pcm_uframes_t off,
+   sn

[PATCH v2 13/27] ALSA: sh: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
Fixed also the user-space buffer copy with the proper
copy_from_user*() variant.

Signed-off-by: Takashi Iwai 
---
 sound/sh/sh_dac_audio.c | 54 +++--
 1 file changed, 30 insertions(+), 24 deletions(-)

diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c
index 461b310c7872..c1e00ed715ee 100644
--- a/sound/sh/sh_dac_audio.c
+++ b/sound/sh/sh_dac_audio.c
@@ -184,23 +184,36 @@ static int snd_sh_dac_pcm_trigger(struct 
snd_pcm_substream *substream, int cmd)
return 0;
 }
 
-static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int 
channel,
-   snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
+static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void __user *src, unsigned long count)
 {
/* channel is not used (interleaved data) */
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
-   ssize_t b_count = frames_to_bytes(runtime , count);
-   ssize_t b_pos = frames_to_bytes(runtime , pos);
 
-   if (count < 0)
-   return -EINVAL;
+   if (copy_from_user_toio(chip->data_buffer + pos, src, count))
+   return -EFAULT;
+   chip->buffer_end = chip->data_buffer + pos + count;
 
-   if (!count)
-   return 0;
+   if (chip->empty) {
+   chip->empty = 0;
+   dac_audio_start_timer(chip);
+   }
+
+   return 0;
+}
 
-   memcpy_toio(chip->data_buffer + b_pos, src, b_count);
-   chip->buffer_end = chip->data_buffer + b_pos + b_count;
+static int snd_sh_dac_pcm_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *src, unsigned long count)
+{
+   /* channel is not used (interleaved data) */
+   struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
+   struct snd_pcm_runtime *runtime = substream->runtime;
+
+   memcpy_toio(chip->data_buffer + pos, src, count);
+   chip->buffer_end = chip->data_buffer + pos + count;
 
if (chip->empty) {
chip->empty = 0;
@@ -211,23 +224,15 @@ static int snd_sh_dac_pcm_copy(struct snd_pcm_substream 
*substream, int channel,
 }
 
 static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream,
- int channel, snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ unsigned long count)
 {
/* channel is not used (interleaved data) */
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
-   ssize_t b_count = frames_to_bytes(runtime , count);
-   ssize_t b_pos = frames_to_bytes(runtime , pos);
-
-   if (count < 0)
-   return -EINVAL;
-
-   if (!count)
-   return 0;
 
-   memset_io(chip->data_buffer + b_pos, 0, b_count);
-   chip->buffer_end = chip->data_buffer + b_pos + b_count;
+   memset_io(chip->data_buffer + pos, 0, count);
+   chip->buffer_end = chip->data_buffer + pos + count;
 
if (chip->empty) {
chip->empty = 0;
@@ -256,8 +261,9 @@ static struct snd_pcm_ops snd_sh_dac_pcm_ops = {
.prepare= snd_sh_dac_pcm_prepare,
.trigger= snd_sh_dac_pcm_trigger,
.pointer= snd_sh_dac_pcm_pointer,
-   .copy   = snd_sh_dac_pcm_copy,
-   .silence= snd_sh_dac_pcm_silence,
+   .copy_user  = snd_sh_dac_pcm_copy,
+   .copy_kernel= snd_sh_dac_pcm_copy_kernel,
+   .fill_silence   = snd_sh_dac_pcm_silence,
.mmap   = snd_pcm_lib_mmap_iomem,
 };
 
-- 
2.13.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 11/27] ALSA: gus: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
For simplifying the code a bit, two local helpers are introduced here:
get_bpos() and playback_copy_ack().

Signed-off-by: Takashi Iwai 
---
 sound/isa/gus/gus_pcm.c | 97 ++---
 1 file changed, 59 insertions(+), 38 deletions(-)

diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 0cc3f272edf1..b9f6dcbef889 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -353,26 +353,25 @@ static int snd_gf1_pcm_poke_block(struct snd_gus_card 
*gus, unsigned char *buf,
return 0;
 }
 
-static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream,
-int voice,
-snd_pcm_uframes_t pos,
-void __user *src,
-snd_pcm_uframes_t count)
+static int get_bpos(struct gus_pcm_private *pcmp, int voice, unsigned int pos,
+   unsigned int len)
 {
-   struct snd_pcm_runtime *runtime = substream->runtime;
-   struct gus_pcm_private *pcmp = runtime->private_data;
-   struct snd_gus_card *gus = pcmp->gus;
-   unsigned int bpos, len;
-   int w16, invert;
-   
-   bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
-   len = samples_to_bytes(runtime, count);
+   unsigned int bpos = pos + (voice * (pcmp->dma_size / 2));
if (snd_BUG_ON(bpos > pcmp->dma_size))
return -EIO;
if (snd_BUG_ON(bpos + len > pcmp->dma_size))
return -EIO;
-   if (copy_from_user(runtime->dma_area + bpos, src, len))
-   return -EFAULT;
+   return bpos;
+}
+
+static int playback_copy_ack(struct snd_pcm_substream *substream,
+unsigned int bpos, unsigned int len)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct gus_pcm_private *pcmp = runtime->private_data;
+   struct snd_gus_card *gus = pcmp->gus;
+   int w16, invert;
+
if (len > 32)
return snd_gf1_pcm_block_change(substream, bpos,
pcmp->memory + bpos, len);
@@ -383,33 +382,54 @@ static int snd_gf1_pcm_playback_copy(struct 
snd_pcm_substream *substream,
  pcmp->memory + bpos, len, w16, invert);
 }
 
+static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream,
+int voice, unsigned long pos,
+void __user *src, unsigned long count)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct gus_pcm_private *pcmp = runtime->private_data;
+   unsigned int len = count;
+   int bpos;
+
+   bpos = get_bpos(pcmp, voice, pos, len);
+   if (bpos < 0)
+   return pos;
+   if (copy_from_user(runtime->dma_area + bpos, src, len))
+   return -EFAULT;
+   return playback_copy_ack(substream, bpos, len);
+}
+
+static int snd_gf1_pcm_playback_copy_kernel(struct snd_pcm_substream 
*substream,
+   int voice, unsigned long pos,
+   void *src, unsigned long count)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct gus_pcm_private *pcmp = runtime->private_data;
+   unsigned int len = count;
+   int bpos;
+
+   bpos = get_bpos(pcmp, voice, pos, len);
+   if (bpos < 0)
+   return pos;
+   memcpy(runtime->dma_area + bpos, src, len);
+   return playback_copy_ack(substream, bpos, len);
+}
+
 static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream,
-   int voice,
-   snd_pcm_uframes_t pos,
-   snd_pcm_uframes_t count)
+   int voice, unsigned long pos,
+   unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct gus_pcm_private *pcmp = runtime->private_data;
-   struct snd_gus_card *gus = pcmp->gus;
-   unsigned int bpos, len;
-   int w16, invert;
+   unsigned int len = count;
+   int bpos;

-   bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
-   len = samples_to_bytes(runtime, count);
-   if (snd_BUG_ON(bpos > pcmp->dma_size))
-   return -EIO;
-   if (snd_BUG_ON(bpos + len > pcmp->dma_size))
-   return -EIO;
+   bpos = get_bpos(pcmp, voice, pos, len);
+   if (bpos < 0)
+   return pos;
snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos,
-  

[PATCH v2 17/27] ALSA: pcm: Check PCM state by a common helper function

2017-06-01 Thread Takashi Iwai
Signed-off-by: Takashi Iwai 
---
 sound/core/pcm_lib.c | 81 +++-
 1 file changed, 29 insertions(+), 52 deletions(-)

diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 0db8d4e0fca2..e4f5c43b6448 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2017,6 +2017,22 @@ typedef int (*transfer_f)(struct snd_pcm_substream 
*substream, unsigned int hwof
  unsigned long data, unsigned int off,
  snd_pcm_uframes_t size);
 
+static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
+{
+   switch (runtime->status->state) {
+   case SNDRV_PCM_STATE_PREPARED:
+   case SNDRV_PCM_STATE_RUNNING:
+   case SNDRV_PCM_STATE_PAUSED:
+   return 0;
+   case SNDRV_PCM_STATE_XRUN:
+   return -EPIPE;
+   case SNDRV_PCM_STATE_SUSPENDED:
+   return -ESTRPIPE;
+   default:
+   return -EBADFD;
+   }
+}
+
 static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream 
*substream, 
unsigned long data,
snd_pcm_uframes_t size,
@@ -2033,21 +2049,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct 
snd_pcm_substream *substream,
return 0;
 
snd_pcm_stream_lock_irq(substream);
-   switch (runtime->status->state) {
-   case SNDRV_PCM_STATE_PREPARED:
-   case SNDRV_PCM_STATE_RUNNING:
-   case SNDRV_PCM_STATE_PAUSED:
-   break;
-   case SNDRV_PCM_STATE_XRUN:
-   err = -EPIPE;
-   goto _end_unlock;
-   case SNDRV_PCM_STATE_SUSPENDED:
-   err = -ESTRPIPE;
-   goto _end_unlock;
-   default:
-   err = -EBADFD;
+   err = pcm_accessible_state(runtime);
+   if (err < 0)
goto _end_unlock;
-   }
 
runtime->twake = runtime->control->avail_min ? : 1;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
@@ -2083,16 +2087,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct 
snd_pcm_substream *substream,
snd_pcm_stream_lock_irq(substream);
if (err < 0)
goto _end_unlock;
-   switch (runtime->status->state) {
-   case SNDRV_PCM_STATE_XRUN:
-   err = -EPIPE;
-   goto _end_unlock;
-   case SNDRV_PCM_STATE_SUSPENDED:
-   err = -ESTRPIPE;
+   err = pcm_accessible_state(runtime);
+   if (err < 0)
goto _end_unlock;
-   default:
-   break;
-   }
appl_ptr += frames;
if (appl_ptr >= runtime->boundary)
appl_ptr -= runtime->boundary;
@@ -2263,27 +2260,14 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct 
snd_pcm_substream *substream,
return 0;
 
snd_pcm_stream_lock_irq(substream);
-   switch (runtime->status->state) {
-   case SNDRV_PCM_STATE_PREPARED:
-   if (size >= runtime->start_threshold) {
-   err = snd_pcm_start(substream);
-   if (err < 0)
-   goto _end_unlock;
-   }
-   break;
-   case SNDRV_PCM_STATE_DRAINING:
-   case SNDRV_PCM_STATE_RUNNING:
-   case SNDRV_PCM_STATE_PAUSED:
-   break;
-   case SNDRV_PCM_STATE_XRUN:
-   err = -EPIPE;
-   goto _end_unlock;
-   case SNDRV_PCM_STATE_SUSPENDED:
-   err = -ESTRPIPE;
-   goto _end_unlock;
-   default:
-   err = -EBADFD;
+   err = pcm_accessible_state(runtime);
+   if (err < 0)
goto _end_unlock;
+   if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
+   size >= runtime->start_threshold) {
+   err = snd_pcm_start(substream);
+   if (err < 0)
+   goto _end_unlock;
}
 
runtime->twake = runtime->control->avail_min ? : 1;
@@ -2327,16 +2311,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct 
snd_pcm_substream *substream,
snd_pcm_stream_lock_irq(substream);
if (err < 0)
goto _end_unlock;
-   switch (runtime->status->state) {
-   case SNDRV_PCM_STATE_XRUN:
-   err = -EPIPE;
-   goto _end_unlock;
-   case SNDRV_PCM_STATE_SUSPENDED:
-   err = -ESTRPIPE;
+   err = pcm_accessible_state(runtime);
+   if (err < 0)
goto _end_unlock;
-   default:
-   break;
-   }
a

[PATCH v2 05/27] ALSA: nm256: Convert to new PCM copy ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new ops.
The conversion is straightforward with standard helper functions, and
now we can drop the bytes <-> frames conversions in callbacks.

Signed-off-by: Takashi Iwai 
---
 sound/pci/nm256/nm256.c | 57 -
 1 file changed, 37 insertions(+), 20 deletions(-)

diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 103fe311e5a9..63f0985dae27 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -695,53 +695,68 @@ snd_nm256_capture_pointer(struct snd_pcm_substream 
*substream)
  */
 static int
 snd_nm256_playback_silence(struct snd_pcm_substream *substream,
-  int channel, /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  snd_pcm_uframes_t count)
+  int channel, unsigned long pos, unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
-   count = frames_to_bytes(runtime, count);
-   pos = frames_to_bytes(runtime, pos);
+
memset_io(s->bufptr + pos, 0, count);
return 0;
 }
 
 static int
 snd_nm256_playback_copy(struct snd_pcm_substream *substream,
-   int channel, /* not used (interleaved data) */
-   snd_pcm_uframes_t pos,
-   void __user *src,
-   snd_pcm_uframes_t count)
+   int channel, unsigned long pos,
+   void __user *src, unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
-   count = frames_to_bytes(runtime, count);
-   pos = frames_to_bytes(runtime, pos);
+
if (copy_from_user_toio(s->bufptr + pos, src, count))
return -EFAULT;
return 0;
 }
 
+static int
+snd_nm256_playback_copy_kernel(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void *src, unsigned long count)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct nm256_stream *s = runtime->private_data;
+
+   memcpy_toio(s->bufptr + pos, src, count);
+   return 0;
+}
+
 /*
  * copy to user
  */
 static int
 snd_nm256_capture_copy(struct snd_pcm_substream *substream,
-  int channel, /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  void __user *dst,
-  snd_pcm_uframes_t count)
+  int channel, unsigned long pos,
+  void __user *dst, unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
-   count = frames_to_bytes(runtime, count);
-   pos = frames_to_bytes(runtime, pos);
+
if (copy_to_user_fromio(dst, s->bufptr + pos, count))
return -EFAULT;
return 0;
 }
 
+static int
+snd_nm256_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct nm256_stream *s = runtime->private_data;
+
+   memcpy_fromio(dst, s->bufptr + pos, count);
+   return 0;
+}
+
 #endif /* !__i386__ */
 
 
@@ -911,8 +926,9 @@ static const struct snd_pcm_ops snd_nm256_playback_ops = {
.trigger =  snd_nm256_playback_trigger,
.pointer =  snd_nm256_playback_pointer,
 #ifndef __i386__
-   .copy = snd_nm256_playback_copy,
-   .silence =  snd_nm256_playback_silence,
+   .copy_user =snd_nm256_playback_copy,
+   .copy_kernel =  snd_nm256_playback_copy_kernel,
+   .fill_silence = snd_nm256_playback_silence,
 #endif
.mmap = snd_pcm_lib_mmap_iomem,
 };
@@ -926,7 +942,8 @@ static const struct snd_pcm_ops snd_nm256_capture_ops = {
.trigger =  snd_nm256_capture_trigger,
.pointer =  snd_nm256_capture_pointer,
 #ifndef __i386__
-   .copy = snd_nm256_capture_copy,
+   .copy_user =snd_nm256_capture_copy,
+   .copy_kernel =  snd_nm256_capture_copy_kernel,
 #endif
.mmap = snd_pcm_lib_mmap_iomem,
 };
-- 
2.13.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 19/27] ALSA: pcm: Call directly the common read/write helpers

2017-06-01 Thread Takashi Iwai
Make snd_pcm_lib_read() and *_write() static inline functions that
call the common helper functions directly.  This reduces a slight
amount of codes, and at the same time, it's a preparation for the
further cleanups / fixes.

Signed-off-by: Takashi Iwai 
---
 include/sound/pcm.h  |  43 +++---
 sound/core/pcm_lib.c | 156 ++-
 2 files changed, 89 insertions(+), 110 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 953ebfc83184..cb4eff8ffd2e 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1088,15 +1088,40 @@ int snd_pcm_update_state(struct snd_pcm_substream 
*substream,
 int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
 void snd_pcm_playback_silence(struct snd_pcm_substream *substream, 
snd_pcm_uframes_t new_hw_ptr);
 void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
-snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream,
-   const void __user *buf,
-   snd_pcm_uframes_t frames);
-snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream,
-  void __user *buf, snd_pcm_uframes_t frames);
-snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
-void __user **bufs, snd_pcm_uframes_t 
frames);
-snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
-   void __user **bufs, snd_pcm_uframes_t 
frames);
+snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ void *buf, bool interleaved,
+ snd_pcm_uframes_t frames);
+snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
+void *buf, bool interleaved,
+snd_pcm_uframes_t frames);
+
+static inline snd_pcm_sframes_t
+snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ const void __user *buf, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_write(substream, (void *)buf, true, frames);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_lib_read(struct snd_pcm_substream *substream,
+void __user *buf, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_read(substream, (void *)buf, true, frames);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_lib_writev(struct snd_pcm_substream *substream,
+  void __user **bufs, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_write(substream, (void *)bufs, false, frames);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_lib_readv(struct snd_pcm_substream *substream,
+ void __user **bufs, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_read(substream, (void *)bufs, false, frames);
+}
 
 extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
 
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 1f5251cca607..1bd7244324d5 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1992,12 +1992,12 @@ static int wait_for_avail(struct snd_pcm_substream 
*substream,
 }

 typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int 
hwoff,
- unsigned long data, unsigned int off,
+ void  *data, unsigned int off,
  snd_pcm_uframes_t size);
 
 static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
  unsigned int hwoff,
- unsigned long data, unsigned int off,
+ void *data, unsigned int off,
  snd_pcm_uframes_t frames)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -2019,7 +2019,7 @@ static int snd_pcm_lib_write_transfer(struct 
snd_pcm_substream *substream,
  
 static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
   unsigned int hwoff,
-  unsigned long data, unsigned int off,
+  void *data, unsigned int off,
   snd_pcm_uframes_t frames)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -2096,21 +2096,39 @@ static int pcm_accessible_state(struct snd_pcm_runtime 
*runtime)
}
 }
 
-static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream 
*substream, 
-   unsigned long data,
-   snd_pcm_uframes_t size,
-   int nonblock,
-   transfer_f transfer)
+snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
+

[PATCH v2 24/27] usb: gadget: u_uac1: Kill set_fs() usage

2017-06-01 Thread Takashi Iwai
With the new API to perform the in-kernel buffer copy, we can get rid
of set_fs() usage in this driver, finally.

Signed-off-by: Takashi Iwai 
---
 drivers/usb/gadget/function/u_uac1.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/function/u_uac1.c 
b/drivers/usb/gadget/function/u_uac1.c
index c78c84138a28..ca88e4c0fd1e 100644
--- a/drivers/usb/gadget/function/u_uac1.c
+++ b/drivers/usb/gadget/function/u_uac1.c
@@ -157,7 +157,6 @@ size_t u_audio_playback(struct gaudio *card, void *buf, 
size_t count)
struct gaudio_snd_dev   *snd = &card->playback;
struct snd_pcm_substream *substream = snd->substream;
struct snd_pcm_runtime *runtime = substream->runtime;
-   mm_segment_t old_fs;
ssize_t result;
snd_pcm_sframes_t frames;
 
@@ -174,15 +173,11 @@ size_t u_audio_playback(struct gaudio *card, void *buf, 
size_t count)
}
 
frames = bytes_to_frames(runtime, count);
-   old_fs = get_fs();
-   set_fs(KERNEL_DS);
-   result = snd_pcm_lib_write(snd->substream, (void __user *)buf, frames);
+   result = snd_pcm_kernel_write(snd->substream, buf, frames);
if (result != frames) {
ERROR(card, "Playback error: %d\n", (int)result);
-   set_fs(old_fs);
goto try_again;
}
-   set_fs(old_fs);
 
return 0;
 }
-- 
2.13.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 23/27] ALSA: pcm: Direct in-kernel read/write support

2017-06-01 Thread Takashi Iwai
Now all materials are ready, let's allow the direct in-kernel
read/write, i.e. a kernel-space buffer is passed for read or write,
instead of the normal user-space buffer.  This feature is used by OSS
layer and UAC1 driver, for example.

The __snd_pcm_lib_xfer() takes in_kernel argument that indicates the
in-kernel buffer copy.  When this flag is set, another transfer code
is used.  It's either via copy_kernel PCM ops or the normal memcpy(),
depending on the driver setup.

As external API, snd_pcm_kernel_read(), *_write() and other variants
are provided.

That's all.  This support is really simple because of the code
refactoring until now.

Signed-off-by: Takashi Iwai 
---
 include/sound/pcm.h  | 38 +-
 sound/core/pcm_lib.c | 26 +-
 2 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 173c6a6ebf35..e3a7269824c7 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1090,34 +1090,62 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
 void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
 snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
 void *buf, bool interleaved,
-snd_pcm_uframes_t frames);
+snd_pcm_uframes_t frames, bool in_kernel);
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_write(struct snd_pcm_substream *substream,
  const void __user *buf, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, false);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_read(struct snd_pcm_substream *substream,
 void __user *buf, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, false);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_writev(struct snd_pcm_substream *substream,
   void __user **bufs, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames, 
false);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_readv(struct snd_pcm_substream *substream,
  void __user **bufs, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames, 
false);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_kernel_write(struct snd_pcm_substream *substream,
+const void *buf, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, true);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_kernel_read(struct snd_pcm_substream *substream,
+   void *buf, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_xfer(substream, buf, true, frames, true);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_kernel_writev(struct snd_pcm_substream *substream,
+ void **bufs, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_xfer(substream, bufs, false, frames, true);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_kernel_readv(struct snd_pcm_substream *substream,
+void **bufs, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_xfer(substream, bufs, false, frames, true);
 }
 
 extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index a592d3308474..ba08b246d153 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1992,6 +1992,15 @@ static int default_write_copy(struct snd_pcm_substream 
*substream,
return 0;
 }
 
+/* default copy_kernel ops for write */
+static int default_write_copy_kernel(struct snd_pcm_substream *substream,
+int channel, unsigned long hwoff,
+void *buf, unsigned long bytes)
+{
+   memcpy(get_dma_ptr(substream->runtime, channel, hwoff), buf, bytes);
+   return 0;
+}
+
 /* fill silence instead of copy data; called as a transfer helper
  * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when
  * a NULL buffer is passed
@@ -2025,6 +2034,15 @@ static int default_read_copy(struct snd_pcm_substream 
*substream,
return 0;
 }
 
+/* default copy_kernel ops for read */
+static int default_read_copy_kernel(struct snd_pcm_substream *substream,
+   int channel, unsigned long hwoff,
+   void *buf, unsigned long bytes)
+{
+   memcpy(buf, get_dma_ptr(substream->runtime, channel, hwoff), byt

[PATCH v2 22/27] ALSA: pcm: Simplify snd_pcm_playback_silence()

2017-06-01 Thread Takashi Iwai
Use the existing silence helper codes for simplification.

Signed-off-by: Takashi Iwai 
---
 sound/core/pcm_lib.c | 50 --
 1 file changed, 20 insertions(+), 30 deletions(-)

diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index f15460eaf8b5..a592d3308474 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -42,6 +42,9 @@
 #define trace_hw_ptr_error(substream, reason)
 #endif
 
+static int fill_silence_frames(struct snd_pcm_substream *substream,
+  snd_pcm_uframes_t off, snd_pcm_uframes_t frames);
+
 /*
  * fill ring buffer with silence
  * runtime->silence_start: starting pointer to silence area
@@ -55,7 +58,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
 {
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t frames, ofs, transfer;
-   char *hwbuf;
int err;
 
if (runtime->silence_size < runtime->boundary) {
@@ -109,35 +111,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
ofs = runtime->silence_start % runtime->buffer_size;
while (frames > 0) {
transfer = ofs + frames > runtime->buffer_size ? 
runtime->buffer_size - ofs : frames;
-   if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
-   runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-   if (substream->ops->fill_silence) {
-   err = substream->ops->fill_silence(substream, 0,
-  
frames_to_bytes(runtime, ofs),
-  
frames_to_bytes(runtime, transfer));
-   snd_BUG_ON(err < 0);
-   } else {
-   hwbuf = runtime->dma_area + 
frames_to_bytes(runtime, ofs);
-   snd_pcm_format_set_silence(runtime->format, 
hwbuf, transfer * runtime->channels);
-   }
-   } else {
-   unsigned int c;
-   unsigned int channels = runtime->channels;
-   if (substream->ops->fill_silence) {
-   for (c = 0; c < channels; ++c) {
-   err = 
substream->ops->fill_silence(substream, c,
-  
samples_to_bytes(runtime, ofs),
-  
samples_to_bytes(runtime, transfer));
-   snd_BUG_ON(err < 0);
-   }
-   } else {
-   size_t dma_csize = runtime->dma_bytes / 
channels;
-   for (c = 0; c < channels; ++c) {
-   hwbuf = runtime->dma_area + (c * 
dma_csize) + samples_to_bytes(runtime, ofs);
-   
snd_pcm_format_set_silence(runtime->format, hwbuf, transfer);
-   }
-   }
-   }
+   err = fill_silence_frames(substream, ofs, transfer);
+   snd_BUG_ON(err < 0);
runtime->silence_filled += transfer;
frames -= transfer;
ofs = 0;
@@ -2101,6 +2076,21 @@ static int noninterleaved_copy(struct snd_pcm_substream 
*substream,
return 0;
 }
 
+/* fill silence on the given buffer position;
+ * called from snd_pcm_playback_silence()
+ */
+static int fill_silence_frames(struct snd_pcm_substream *substream,
+  snd_pcm_uframes_t off, snd_pcm_uframes_t frames)
+{
+   if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
+   substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED)
+   return interleaved_copy(substream, off, NULL, 0, frames,
+   fill_silence);
+   else
+   return noninterleaved_copy(substream, off, NULL, 0, frames,
+  fill_silence);
+}
+
 /* sanity-check for read/write methods */
 static int pcm_sanity_check(struct snd_pcm_substream *substream)
 {
-- 
2.13.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 07/27] ALSA: rme32: Convert to the new PCM copy ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new ops.
The conversion is straightforward with standard helper functions, and
now we can drop the bytes <-> frames conversions in callbacks.

Signed-off-by: Takashi Iwai 
---
 sound/pci/rme32.c | 65 ---
 1 file changed, 43 insertions(+), 22 deletions(-)

diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 96d15db65dfd..ce438c62b0b3 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -254,39 +254,46 @@ static inline unsigned int snd_rme32_pcm_byteptr(struct 
rme32 * rme32)
 }
 
 /* silence callback for halfduplex mode */
-static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int 
channel,/* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+static int snd_rme32_playback_silence(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ unsigned long count)
 {
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
-   count <<= rme32->playback_frlog;
-   pos <<= rme32->playback_frlog;
+
memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count);
return 0;
 }
 
 /* copy callback for halfduplex mode */
-static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, int 
channel,   /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  void __user *src, snd_pcm_uframes_t count)
+static int snd_rme32_playback_copy(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void __user *src, unsigned long count)
 {
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
-   count <<= rme32->playback_frlog;
-   pos <<= rme32->playback_frlog;
+
if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
-   src, count))
+   src, count))
return -EFAULT;
return 0;
 }
 
+static int snd_rme32_playback_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *src, unsigned long count)
+{
+   struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+
+   memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, src, count);
+   return 0;
+}
+
 /* copy callback for halfduplex mode */
-static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int 
channel,/* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- void __user *dst, snd_pcm_uframes_t count)
+static int snd_rme32_capture_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long count)
 {
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
-   count <<= rme32->capture_frlog;
-   pos <<= rme32->capture_frlog;
+
if (copy_to_user_fromio(dst,
rme32->iobase + RME32_IO_DATA_BUFFER + pos,
count))
@@ -294,6 +301,16 @@ static int snd_rme32_capture_copy(struct snd_pcm_substream 
*substream, int chann
return 0;
 }
 
+static int snd_rme32_capture_copy_kernel(struct snd_pcm_substream *substream,
+int channel, unsigned long pos,
+void *dst, unsigned long count)
+{
+   struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+
+   memcpy_fromio(dst, rme32->iobase + RME32_IO_DATA_BUFFER + pos, count);
+   return 0;
+}
+
 /*
  * SPDIF I/O capabilities (half-duplex mode)
  */
@@ -1205,8 +1222,9 @@ static const struct snd_pcm_ops 
snd_rme32_playback_spdif_ops = {
.prepare =  snd_rme32_playback_prepare,
.trigger =  snd_rme32_pcm_trigger,
.pointer =  snd_rme32_playback_pointer,
-   .copy = snd_rme32_playback_copy,
-   .silence =  snd_rme32_playback_silence,
+   .copy_user =snd_rme32_playback_copy,
+   .copy_kernel =  snd_rme32_playback_copy_kernel,
+   .fill_silence = snd_rme32_playback_silence,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1219,7 +1237,8 @@ static const struct snd_pcm_ops 
snd_rme32_capture_spdif_ops = {
.prepare =  snd_rme32_capture_prepare,
.trigger =  snd_rme32_pcm_trigger,
.pointer =  snd_rme32_capture_pointer,
-   .copy = snd_rme32_capture_copy,
+   .copy_user =snd_rme32_capture_copy,
+   .copy_kernel =  sn

[PATCH v2 27/27] ALSA: doc: Update copy_user, copy_kernel and fill_silence PCM ops

2017-06-01 Thread Takashi Iwai
Signed-off-by: Takashi Iwai 
---
 .../sound/kernel-api/writing-an-alsa-driver.rst| 111 ++---
 1 file changed, 76 insertions(+), 35 deletions(-)

diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst 
b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
index 95c5443eff38..58ffa3f5bda7 100644
--- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
+++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
@@ -2080,8 +2080,8 @@ sleeping poll threads, etc.
 
 This callback is also atomic as default.
 
-copy and silence callbacks
-~~
+copy_user, copy_kernel and fill_silence ops
+~~~
 
 These callbacks are not mandatory, and can be omitted in most cases.
 These callbacks are used when the hardware buffer cannot be in the
@@ -3532,8 +3532,9 @@ external hardware buffer in interrupts (or in tasklets, 
preferably).
 
 The first case works fine if the external hardware buffer is large
 enough. This method doesn't need any extra buffers and thus is more
-effective. You need to define the ``copy`` and ``silence`` callbacks
-for the data transfer. However, there is a drawback: it cannot be
+effective. You need to define the ``copy_user`` and ``copy_kernel``
+callbacks for the data transfer, in addition to ``fill_silence``
+callback for playback. However, there is a drawback: it cannot be
 mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM.
 
 The second case allows for mmap on the buffer, although you have to
@@ -3545,30 +3546,34 @@ Another case is when the chip uses a PCI memory-map 
region for the
 buffer instead of the host memory. In this case, mmap is available only
 on certain architectures like the Intel one. In non-mmap mode, the data
 cannot be transferred as in the normal way. Thus you need to define the
-``copy`` and ``silence`` callbacks as well, as in the cases above. The
-examples are found in ``rme32.c`` and ``rme96.c``.
+``copy_user``, ``copy_kernel`` and ``fill_silence`` callbacks as well,
+as in the cases above. The examples are found in ``rme32.c`` and
+``rme96.c``.
 
-The implementation of the ``copy`` and ``silence`` callbacks depends
-upon whether the hardware supports interleaved or non-interleaved
-samples. The ``copy`` callback is defined like below, a bit
-differently depending whether the direction is playback or capture:
+The implementation of the ``copy_user``, ``copy_kernel`` and
+``silence`` callbacks depends upon whether the hardware supports
+interleaved or non-interleaved samples. The ``copy_user`` callback is
+defined like below, a bit differently depending whether the direction
+is playback or capture:
 
 ::
 
-  static int playback_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count);
-  static int capture_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count);
+  static int playback_copy_user(struct snd_pcm_substream *substream,
+   int channel, unsigned long pos,
+   void __user *src, unsigned long count);
+  static int capture_copy_user(struct snd_pcm_substream *substream,
+   int channel, unsigned long pos,
+   void __user *dst, unsigned long count);
 
 In the case of interleaved samples, the second argument (``channel``) is
 not used. The third argument (``pos``) points the current position
-offset in frames.
+offset in bytes.
 
 The meaning of the fourth argument is different between playback and
 capture. For playback, it holds the source data pointer, and for
 capture, it's the destination data pointer.
 
-The last argument is the number of frames to be copied.
+The last argument is the number of bytes to be copied.
 
 What you have to do in this callback is again different between playback
 and capture directions. In the playback case, you copy the given amount
@@ -3578,8 +3583,7 @@ way, the copy would be like:
 
 ::
 
-  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src,
-frames_to_bytes(runtime, count));
+  my_memcpy_from_user(my_buffer + pos, src, count);
 
 For the capture direction, you copy the given amount of data (``count``)
 at the specified offset (``pos``) on the hardware buffer to the
@@ -3587,31 +3591,68 @@ specified pointer (``dst``).
 
 ::
 
-  my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos),
-frames_to_bytes(runtime, count));
+  my_memcpy_to_user(dst, my_buffer + pos, count);
+
+Here the functions are named as ``from_user`` and ``to_user`` because
+it's the user-space buffer that is passed to these callbacks.  That
+is, the callback is supposed to copy from/to the user-space data
+directly to/from the hardware buffer.
 
-Note that both the position and the amount of data are given in frames.
+Careful readers might notice that these callbacks receive the
+argument

[PATCH v2 25/27] ALSA: pcm: Kill set_fs() in PCM OSS layer

2017-06-01 Thread Takashi Iwai
This is the last-standing one: kill the set_fs() usage in PCM OSS
layer by replacing with the new API functions to deal with the direct
in-kernel buffer copying.

The code to fill the silence can be replaced even to a one-liner to
pass NULL buffer instead of the manual copying.

Signed-off-by: Takashi Iwai 
---
 sound/core/oss/pcm_oss.c | 77 
 1 file changed, 12 insertions(+), 65 deletions(-)

diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index e306f05ce51d..2d6a825cfe88 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -67,18 +67,6 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file 
*pcm_oss_file);
 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
 
-static inline mm_segment_t snd_enter_user(void)
-{
-   mm_segment_t fs = get_fs();
-   set_fs(get_ds());
-   return fs;
-}
-
-static inline void snd_leave_user(mm_segment_t fs)
-{
-   set_fs(fs);
-}
-
 /*
  * helper functions to process hw_params
  */
@@ -1191,14 +1179,8 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct 
snd_pcm_substream *substream, const
if (ret < 0)
break;
}
-   if (in_kernel) {
-   mm_segment_t fs;
-   fs = snd_enter_user();
-   ret = snd_pcm_lib_write(substream, (void __force __user 
*)ptr, frames);
-   snd_leave_user(fs);
-   } else {
-   ret = snd_pcm_lib_write(substream, (void __force __user 
*)ptr, frames);
-   }
+   ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
+frames, in_kernel);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
/* test, if we can't store new data, because the stream */
@@ -1234,14 +1216,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct 
snd_pcm_substream *substream, char *p
ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
if (ret < 0)
break;
-   if (in_kernel) {
-   mm_segment_t fs;
-   fs = snd_enter_user();
-   ret = snd_pcm_lib_read(substream, (void __force __user 
*)ptr, frames);
-   snd_leave_user(fs);
-   } else {
-   ret = snd_pcm_lib_read(substream, (void __force __user 
*)ptr, frames);
-   }
+   ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
+frames, in_kernel);
if (ret == -EPIPE) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) 
{
ret = snd_pcm_kernel_ioctl(substream, 
SNDRV_PCM_IOCTL_DROP, NULL);
@@ -1273,14 +1249,8 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct 
snd_pcm_substream *substream, void
if (ret < 0)
break;
}
-   if (in_kernel) {
-   mm_segment_t fs;
-   fs = snd_enter_user();
-   ret = snd_pcm_lib_writev(substream, (void __user 
**)bufs, frames);
-   snd_leave_user(fs);
-   } else {
-   ret = snd_pcm_lib_writev(substream, (void __user 
**)bufs, frames);
-   }
+   ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
+in_kernel);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
 
@@ -1313,14 +1283,8 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct 
snd_pcm_substream *substream, void *
if (ret < 0)
break;
}
-   if (in_kernel) {
-   mm_segment_t fs;
-   fs = snd_enter_user();
-   ret = snd_pcm_lib_readv(substream, (void __user 
**)bufs, frames);
-   snd_leave_user(fs);
-   } else {
-   ret = snd_pcm_lib_readv(substream, (void __user 
**)bufs, frames);
-   }
+   ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
+in_kernel);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
}
@@ -1650,27 +1614,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file 
*pcm_oss_file)
size = runtime->control->appl_ptr % runtime->period_size;
if (size > 0) {
size = runtime->period_size - size;
-   

[PATCH v2 16/27] ALSA: pcm: Drop the old copy and silence ops

2017-06-01 Thread Takashi Iwai
Now that all users of old copy and silence ops have been converted to
the new PCM ops, the old stuff can be retired and go away.

Signed-off-by: Takashi Iwai 
---
 include/sound/pcm.h  |  5 -
 sound/core/pcm_lib.c | 38 +-
 sound/soc/soc-pcm.c  |  2 --
 3 files changed, 1 insertion(+), 44 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index a065415191d8..953ebfc83184 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -78,11 +78,6 @@ struct snd_pcm_ops {
struct timespec *system_ts, struct timespec *audio_ts,
struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
struct snd_pcm_audio_tstamp_report 
*audio_tstamp_report);
-   int (*copy)(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos,
-   void __user *buf, snd_pcm_uframes_t count);
-   int (*silence)(struct snd_pcm_substream *substream, int channel, 
-  snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
unsigned long pos, unsigned long bytes);
int (*copy_user)(struct snd_pcm_substream *substream, int channel,
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 9334fc2c20c8..0db8d4e0fca2 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -116,9 +116,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
   
frames_to_bytes(runtime, ofs),
   
frames_to_bytes(runtime, transfer));
snd_BUG_ON(err < 0);
-   } else if (substream->ops->silence) {
-   err = substream->ops->silence(substream, -1, 
ofs, transfer);
-   snd_BUG_ON(err < 0);
} else {
hwbuf = runtime->dma_area + 
frames_to_bytes(runtime, ofs);
snd_pcm_format_set_silence(runtime->format, 
hwbuf, transfer * runtime->channels);
@@ -133,11 +130,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
   
samples_to_bytes(runtime, transfer));
snd_BUG_ON(err < 0);
}
-   } else if (substream->ops->silence) {
-   for (c = 0; c < channels; ++c) {
-   err = 
substream->ops->silence(substream, c, ofs, transfer);
-   snd_BUG_ON(err < 0);
-   }
} else {
size_t dma_csize = runtime->dma_bytes / 
channels;
for (c = 0; c < channels; ++c) {
@@ -2013,9 +2005,6 @@ static int snd_pcm_lib_write_transfer(struct 
snd_pcm_substream *substream,
err = substream->ops->copy_user(substream, 0, hwoff, buf, 
frames);
if (err < 0)
return err;
-   } else if (substream->ops->copy) {
-   if ((err = substream->ops->copy(substream, -1, hwoff, buf, 
frames)) < 0)
-   return err;
} else {
char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, 
hwoff);
if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, 
frames)))
@@ -2137,8 +2126,7 @@ static int pcm_sanity_check(struct snd_pcm_substream 
*substream)
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
-   if (snd_BUG_ON(!substream->ops->copy_user && !substream->ops->copy
-  && !runtime->dma_area))
+   if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
return -EINVAL;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
@@ -2198,19 +2186,6 @@ static int snd_pcm_lib_writev_transfer(struct 
snd_pcm_substream *substream,
if (err < 0)
return err;
}
-   } else if (substream->ops->copy) {
-   if (snd_BUG_ON(!substream->ops->silence))
-   return -EINVAL;
-   for (c = 0; c < channels; ++c, ++bufs) {
-   if (*bufs == NULL) {
-   if ((err = substream->ops->silence(substream, 
c, hwoff, frames)) < 0)
-   return err;
- 

[PATCH v2 18/27] ALSA: pcm: Shuffle codes

2017-06-01 Thread Takashi Iwai
Just shuffle the codes, without any change otherwise.

Signed-off-by: Takashi Iwai 
---
 sound/core/pcm_lib.c | 212 +--
 1 file changed, 106 insertions(+), 106 deletions(-)

diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index e4f5c43b6448..1f5251cca607 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1991,6 +1991,10 @@ static int wait_for_avail(struct snd_pcm_substream 
*substream,
return err;
 }

+typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int 
hwoff,
+ unsigned long data, unsigned int off,
+ snd_pcm_uframes_t size);
+
 static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
  unsigned int hwoff,
  unsigned long data, unsigned int off,
@@ -2013,9 +2017,68 @@ static int snd_pcm_lib_write_transfer(struct 
snd_pcm_substream *substream,
return 0;
 }
  
-typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int 
hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t size);
+static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
+  unsigned int hwoff,
+  unsigned long data, unsigned int off,
+  snd_pcm_uframes_t frames)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   int err;
+   void __user **bufs = (void __user **)data;
+   int channels = runtime->channels;
+   char __user *buf;
+   int c;
+
+   if (substream->ops->copy_user) {
+   hwoff = samples_to_bytes(runtime, hwoff);
+   off = samples_to_bytes(runtime, off);
+   frames = samples_to_bytes(runtime, frames);
+   for (c = 0; c < channels; ++c, ++bufs) {
+   buf = *bufs + off;
+   if (!*bufs) {
+   if (snd_BUG_ON(!substream->ops->fill_silence))
+   return -EINVAL;
+   err = substream->ops->fill_silence(substream, c,
+  hwoff,
+  frames);
+   } else {
+   err = substream->ops->copy_user(substream, c,
+   hwoff, buf,
+   frames);
+   }
+   if (err < 0)
+   return err;
+   }
+   } else {
+   /* default transfer behaviour */
+   size_t dma_csize = runtime->dma_bytes / channels;
+   for (c = 0; c < channels; ++c, ++bufs) {
+   char *hwbuf = runtime->dma_area + (c * dma_csize) + 
samples_to_bytes(runtime, hwoff);
+   if (*bufs == NULL) {
+   snd_pcm_format_set_silence(runtime->format, 
hwbuf, frames);
+   } else {
+   char __user *buf = *bufs + 
samples_to_bytes(runtime, off);
+   if (copy_from_user(hwbuf, buf, 
samples_to_bytes(runtime, frames)))
+   return -EFAULT;
+   }
+   }
+   }
+   return 0;
+}
+
+/* sanity-check for read/write methods */
+static int pcm_sanity_check(struct snd_pcm_substream *substream)
+{
+   struct snd_pcm_runtime *runtime;
+   if (PCM_RUNTIME_CHECK(substream))
+   return -ENXIO;
+   runtime = substream->runtime;
+   if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
+   return -EINVAL;
+   if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+   return -EBADFD;
+   return 0;
+}
 
 static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
 {
@@ -2116,20 +2179,6 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct 
snd_pcm_substream *substream,
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
 }
 
-/* sanity-check for read/write methods */
-static int pcm_sanity_check(struct snd_pcm_substream *substream)
-{
-   struct snd_pcm_runtime *runtime;
-   if (PCM_RUNTIME_CHECK(substream))
-   return -ENXIO;
-   runtime = substream->runtime;
-   if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
-   return -EINVAL;
-   if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
-   return -EBADFD;
-   return 0;
-}
-
 snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream 

[PATCH v2 26/27] ALSA: pcm: Build OSS writev/readv helpers conditionally

2017-06-01 Thread Takashi Iwai
The snd_pcm_oss_writev3() and snd_pcm_oss_readv3() are used only in
io.c with CONFIG_SND_PCM_OSS_PLUGINS=y.  Add an ifdef to reduce the
build of these functions.

Along with it, since they are called always for in-kernel copy, reduce
the argument and call snd_pcm_kernel_writev() and *_readv() directly
instead.

Signed-off-by: Takashi Iwai 
---
 sound/core/oss/io.c |  4 ++--
 sound/core/oss/pcm_oss.c| 12 ++--
 sound/core/oss/pcm_plugin.h |  6 ++
 3 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
index 6faa1d719206..d870b2d93135 100644
--- a/sound/core/oss/io.c
+++ b/sound/core/oss/io.c
@@ -26,9 +26,9 @@
 #include "pcm_plugin.h"
 
 #define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
-#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1)
+#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count)
 #define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1)
-#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1)
+#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count)
 
 /*
  *  Basic io plugin
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 2d6a825cfe88..5e1009d959a8 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1232,7 +1232,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct 
snd_pcm_substream *substream, char *p
return ret;
 }
 
-snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, 
void **bufs, snd_pcm_uframes_t frames, int in_kernel)
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, 
void **bufs, snd_pcm_uframes_t frames)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
@@ -1249,8 +1250,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct 
snd_pcm_substream *substream, void
if (ret < 0)
break;
}
-   ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
-in_kernel);
+   ret = snd_pcm_kernel_writev(substream, bufs, frames);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
 
@@ -1262,7 +1262,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct 
snd_pcm_substream *substream, void
return ret;
 }

-snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void 
**bufs, snd_pcm_uframes_t frames, int in_kernel)
+snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void 
**bufs, snd_pcm_uframes_t frames)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
@@ -1283,13 +1283,13 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct 
snd_pcm_substream *substream, void *
if (ret < 0)
break;
}
-   ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
-in_kernel);
+   ret = snd_pcm_kernel_readv(substream, bufs, frames);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
}
return ret;
 }
+#endif /* CONFIG_SND_PCM_OSS_PLUGINS */
 
 static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const 
char *buf, size_t bytes, int in_kernel)
 {
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index 73c068abaca5..c9cd29d86efd 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -162,11 +162,9 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct 
snd_pcm_substream *substream,
 snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream,
char *ptr, snd_pcm_uframes_t size, int 
in_kernel);
 snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream,
- void **bufs, snd_pcm_uframes_t frames,
- int in_kernel);
+ void **bufs, snd_pcm_uframes_t frames);
 snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
-void **bufs, snd_pcm_uframes_t frames,
-int in_kernel);
+void **bufs, snd_pcm_uframes_t frames);
 
 #else
 
-- 
2.13.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 09/27] ALSA: rme9652: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
The conversion is straightforward with standard helper functions.

Signed-off-by: Takashi Iwai 
---
 sound/pci/rme9652/rme9652.c | 71 ++---
 1 file changed, 54 insertions(+), 17 deletions(-)

diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 55172c689991..59684bf5cac0 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -1883,13 +1883,14 @@ static char *rme9652_channel_buffer_location(struct 
snd_rme9652 *rme9652,
}
 }
 
-static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int 
channel,
-snd_pcm_uframes_t pos, void __user *src, 
snd_pcm_uframes_t count)
+static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream,
+int channel, unsigned long pos,
+void __user *src, unsigned long count)
 {
struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
 
-   if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4))
+   if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES))
return -EINVAL;
 
channel_buf = rme9652_channel_buffer_location (rme9652,
@@ -1897,18 +1898,35 @@ static int snd_rme9652_playback_copy(struct 
snd_pcm_substream *substream, int ch
   channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_from_user(channel_buf + pos * 4, src, count * 4))
+   if (copy_from_user(channel_buf + pos, src, count))
return -EFAULT;
-   return count;
+   return 0;
 }
 
-static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int 
channel,
-   snd_pcm_uframes_t pos, void __user *dst, 
snd_pcm_uframes_t count)
+static int snd_rme9652_playback_copy_kernel(struct snd_pcm_substream 
*substream,
+   int channel, unsigned long pos,
+   void *src, unsigned long count)
 {
struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
 
-   if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4))
+   channel_buf = rme9652_channel_buffer_location(rme9652,
+ substream->pstr->stream,
+ channel);
+   if (snd_BUG_ON(!channel_buf))
+   return -EIO;
+   memcpy(channel_buf + pos, src, count);
+   return 0;
+}
+
+static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream,
+   int channel, unsigned long pos,
+   void __user *dst, unsigned long count)
+{
+   struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
+   char *channel_buf;
+
+   if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES))
return -EINVAL;
 
channel_buf = rme9652_channel_buffer_location (rme9652,
@@ -1916,13 +1934,30 @@ static int snd_rme9652_capture_copy(struct 
snd_pcm_substream *substream, int cha
   channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
+   if (copy_to_user(dst, channel_buf + pos, count))
return -EFAULT;
-   return count;
+   return 0;
 }
 
-static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int 
channel,
- snd_pcm_uframes_t pos, snd_pcm_uframes_t 
count)
+static int snd_rme9652_capture_copy_kernel(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void *dst, unsigned long count)
+{
+   struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
+   char *channel_buf;
+
+   channel_buf = rme9652_channel_buffer_location(rme9652,
+ substream->pstr->stream,
+ channel);
+   if (snd_BUG_ON(!channel_buf))
+   return -EIO;
+   memcpy(dst, channel_buf + pos, count);
+   return 0;
+}
+
+static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ unsigned long count)
 {
struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
@@ -1932,8 +1967,8 @@ static int snd_rme9652_hw_silence(struct 
snd_pcm_substream *substream, int chann
   channel)

[PATCH v2 00/27] Revised full patchset for PCM in-kernel copy support

2017-06-01 Thread Takashi Iwai
Hi,

this is a full patchset of what I sent previously, containing the all
changes instead of the snippet.  The main purpose of this patchset is
to eliminate the remaining usages of set_fs().  They are basically
used for in-kernel PCM data transfer, and this patch provides the new
API functions and replaces the hackish set_fs() calls with them.

Unlike the first patchset with the unified copy_silence ops, this adds
a new copy_kernel ops instead.  At the same time, copy/silence are
changed to receive the position and size in bytes instead of frames.
This allows us to simplify the PCM core code.  As a result, a good
amount of code could be removed from pcm_lib.c.

The difference from the previous patchset is that this is a full
patchset, i.e. all relevant drivers have been covered, and also some
small issues have been addressed, in addition, the documentation
update is provided, too.

I'm Cc'ing the media and the USB people since it touches solo6x10 and
usb-gadget drivers.

The previous ACK was dropped as each patch was rewritten again.  Sorry
for the doubly patch-review labours.


thanks,

Takashi

===

Takashi Iwai (26):
  ALSA: pcm: Introduce copy_user, copy_kernel and fill_silence ops
  ALSA: dummy: Convert to new PCM copy ops
  ALSA: es1938: Convert to the new PCM copy ops
  ALSA: nm256: Convert to new PCM copy ops
  ALSA: korg1212: Convert to the new PCM ops
  ALSA: rme32: Convert to the new PCM copy ops
  ALSA: rme96: Convert to the new PCM ops
  ALSA: rme9652: Convert to the new PCM ops
  ALSA: hdsp: Convert to the new PCM ops
  ALSA: gus: Convert to the new PCM ops
  ALSA: sb: Convert to the new PCM ops
  ALSA: sh: Convert to the new PCM ops
  ASoC: blackfin: Convert to the new PCM ops
  [media] solo6x10: Convert to the new PCM ops
  ALSA: pcm: Drop the old copy and silence ops
  ALSA: pcm: Check PCM state by a common helper function
  ALSA: pcm: Shuffle codes
  ALSA: pcm: Call directly the common read/write helpers
  ALSA: pcm: More unification of PCM transfer codes
  ALSA: pcm: Unify read/write loop
  ALSA: pcm: Simplify snd_pcm_playback_silence()
  ALSA: pcm: Direct in-kernel read/write support
  usb: gadget: u_uac1: Kill set_fs() usage
  ALSA: pcm: Kill set_fs() in PCM OSS layer
  ALSA: pcm: Build OSS writev/readv helpers conditionally
  ALSA: doc: Update copy_user, copy_kernel and fill_silence PCM ops

 .../sound/kernel-api/writing-an-alsa-driver.rst| 111 ++--
 drivers/media/pci/solo6x10/solo6x10-g723.c |  32 +-
 drivers/usb/gadget/function/u_uac1.c   |   7 +-
 include/sound/pcm.h|  80 ++-
 sound/core/oss/io.c|   4 +-
 sound/core/oss/pcm_oss.c   |  81 +--
 sound/core/oss/pcm_plugin.h|   6 +-
 sound/core/pcm_lib.c   | 564 -
 sound/drivers/dummy.c  |  20 +-
 sound/isa/gus/gus_pcm.c|  97 ++--
 sound/isa/sb/emu8000_pcm.c | 190 ---
 sound/pci/es1938.c |  33 +-
 sound/pci/korg1212/korg1212.c  | 112 ++--
 sound/pci/nm256/nm256.c|  57 ++-
 sound/pci/rme32.c  |  65 ++-
 sound/pci/rme96.c  |  70 ++-
 sound/pci/rme9652/hdsp.c   |  67 ++-
 sound/pci/rme9652/rme9652.c|  71 ++-
 sound/sh/sh_dac_audio.c|  54 +-
 sound/soc/blackfin/bf5xx-ac97-pcm.c|  27 +-
 sound/soc/blackfin/bf5xx-i2s-pcm.c |  36 +-
 sound/soc/soc-pcm.c|   5 +-
 22 files changed, 977 insertions(+), 812 deletions(-)

-- 
2.13.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 06/27] ALSA: korg1212: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
Although we can refactor this messy code, at this time, the changes
are kept as small as possible.  Let's clean up later.

Signed-off-by: Takashi Iwai 
---
 sound/pci/korg1212/korg1212.c | 112 --
 1 file changed, 65 insertions(+), 47 deletions(-)

diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 1e25095fd144..b28fe4914d6b 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -1299,13 +1299,21 @@ static int snd_korg1212_silence(struct snd_korg1212 
*korg1212, int pos, int coun
return 0;
 }
 
-static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user 
*dst, int pos, int count, int offset, int size)
+static int snd_korg1212_copy_to(struct snd_pcm_substream *substream,
+   void __user *dst, int pos, int count,
+   bool in_kernel)
 {
-   struct KorgAudioFrame * src =  
korg1212->recordDataBufsPtr[0].bufferData + pos;
-   int i, rc;
-
-   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d 
offset=%d size=%d\n",
-  pos, offset, size);
+   struct snd_pcm_runtime *runtime = substream->runtime;
+struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
+   struct KorgAudioFrame *src;
+   int i, size;
+
+   pos = bytes_to_frames(runtime, pos);
+   count = bytes_to_frames(runtime, count);
+   size = korg1212->channels * 2;
+   src = korg1212->recordDataBufsPtr[0].bufferData + pos;
+   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d 
size=%d count=%d\n",
+  pos, size, count);
if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES))
return -EINVAL;
 
@@ -1317,11 +1325,10 @@ static int snd_korg1212_copy_to(struct snd_korg1212 
*korg1212, void __user *dst,
return -EFAULT;
}
 #endif
-   rc = copy_to_user(dst + offset, src, size);
-   if (rc) {
-   K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_to 
USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i);
+   if (in_kernel)
+   memcpy((void *)dst, src, size);
+   else if (copy_to_user(dst, src, size))
return -EFAULT;
-   }
src++;
dst += size;
}
@@ -1329,13 +1336,22 @@ static int snd_korg1212_copy_to(struct snd_korg1212 
*korg1212, void __user *dst,
return 0;
 }
 
-static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user 
*src, int pos, int count, int offset, int size)
+static int snd_korg1212_copy_from(struct snd_pcm_substream *substream,
+ void __user *src, int pos, int count,
+ bool in_kernel)
 {
-   struct KorgAudioFrame * dst =  korg1212->playDataBufsPtr[0].bufferData 
+ pos;
-   int i, rc;
+struct snd_pcm_runtime *runtime = substream->runtime;
+   struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
+   struct KorgAudioFrame *dst;
+   int i, size;
 
-   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d 
offset=%d size=%d count=%d\n",
-  pos, offset, size, count);
+   pos = bytes_to_frames(runtime, pos);
+   count = bytes_to_frames(runtime, count);
+   size = korg1212->channels * 2;
+   dst = korg1212->playDataBufsPtr[0].bufferData + pos;
+
+   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d 
size=%d count=%d\n",
+  pos, size, count);
 
if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES))
return -EINVAL;
@@ -1348,11 +1364,10 @@ static int snd_korg1212_copy_from(struct snd_korg1212 
*korg1212, void __user *sr
return -EFAULT;
}
 #endif
-   rc = copy_from_user((void*) dst + offset, src, size);
-   if (rc) {
-   K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_from 
USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i);
+   if (in_kernel)
+   memcpy((void *)dst, src, size);
+   else if (copy_from_user(dst, src, size))
return -EFAULT;
-   }
dst++;
src += size;
}
@@ -1640,45 +1655,46 @@ static snd_pcm_uframes_t 
snd_korg1212_capture_pointer(struct snd_pcm_substream *
 }
 
 static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream,
-int channel, /* not used (interleaved data) */
-snd_pcm_uframes_t p

[PATCH v2 21/27] ALSA: pcm: Unify read/write loop

2017-06-01 Thread Takashi Iwai
Both __snd_pcm_lib_read() and __snd_pcm_write() functions have almost
the same code to loop over samples.  For simplification, this patch
unifies both as the single helper, __snd_pcm_lib_xfer().

Other than that, there should be no functional change by this patch.

Signed-off-by: Takashi Iwai 
---
 include/sound/pcm.h  |  13 ++--
 sound/core/pcm_lib.c | 184 +--
 2 files changed, 51 insertions(+), 146 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index cb4eff8ffd2e..173c6a6ebf35 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1088,10 +1088,7 @@ int snd_pcm_update_state(struct snd_pcm_substream 
*substream,
 int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
 void snd_pcm_playback_silence(struct snd_pcm_substream *substream, 
snd_pcm_uframes_t new_hw_ptr);
 void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
-snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
- void *buf, bool interleaved,
- snd_pcm_uframes_t frames);
-snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
+snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
 void *buf, bool interleaved,
 snd_pcm_uframes_t frames);
 
@@ -1099,28 +1096,28 @@ static inline snd_pcm_sframes_t
 snd_pcm_lib_write(struct snd_pcm_substream *substream,
  const void __user *buf, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_write(substream, (void *)buf, true, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_read(struct snd_pcm_substream *substream,
 void __user *buf, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_read(substream, (void *)buf, true, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_writev(struct snd_pcm_substream *substream,
   void __user **bufs, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_write(substream, (void *)bufs, false, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_readv(struct snd_pcm_substream *substream,
  void __user **bufs, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_read(substream, (void *)bufs, false, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
 }
 
 extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index eb9cbc2d9d7b..f15460eaf8b5 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2006,13 +2006,13 @@ static void *get_dma_ptr(struct snd_pcm_runtime 
*runtime,
channel * (runtime->dma_bytes / runtime->channels);
 }
 
-/* default copy_user ops for write */
-static int default_write_copy_user(struct snd_pcm_substream *substream,
-  int channel, unsigned long hwoff,
-  void __user *buf, unsigned long bytes)
+/* default copy_user ops for write; used for both interleaved and non- modes */
+static int default_write_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long hwoff,
+ void *buf, unsigned long bytes)
 {
if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff),
-  buf, bytes))
+  (void __user *)buf, bytes))
return -EFAULT;
return 0;
 }
@@ -2038,6 +2038,18 @@ static int fill_silence(struct snd_pcm_substream 
*substream, int channel,
return 0;
 }
 
+/* default copy_user ops for read; used for both interleaved and non- modes */
+static int default_read_copy(struct snd_pcm_substream *substream,
+int channel, unsigned long hwoff,
+void *buf, unsigned long bytes)
+{
+   if (copy_to_user((void __user *)buf,
+get_dma_ptr(substream->runtime, channel, hwoff),
+bytes))
+   return -EFAULT;
+   return 0;
+}
+
 /* call transfer function with the converted pointers and sizes;
  * for interleaved mode, it's one shot for all samples
  */
@@ -2119,9 +2131,10 @@ static int pcm_accessible_state(struct snd_pcm_runtime 
*runtime)
}
 }
 
-snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
- void *data, bool interleaved,
- snd_pcm_uframes_t size)
+/* the common loop for read/write data */
+snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_sub

Re: [alsa-devel] Distorted audio from microphone (Logitech C310)

2017-05-15 Thread Takashi Iwai
On Tue, 16 May 2017 07:58:43 +0200,
Greg KH wrote:
> 
> On Mon, May 15, 2017 at 03:29:09PM +0200, Domker_ wrote:
> > My webcam Logitech C310 have a distored microphone audio on kernel 4.10.15-1
> > and 4.11.0-1. (on 4.9.27-1 and the older ones is fine).
> > The distortion effect is as if I spoke very, very fast (like a damn Mickey
> > Mouse)
> > 
> > I checked and the bug occurs on both computers I have. (with the same
> > camera/different sound cards, hardware and different Linux distributions)
> > The bug always occurs when running a system with a kernel newer than 4.9.x.
> > 
> > The camera has two internal microphones.
> > Secound kernel 4.11.0-1 (x86_64) compiled from kernel.org!
> > 
> > (tested under Linux Arch and Linux Manjaro)
> 
> Hm, maybe the Linux sound developers can help out here (added to cc:)

Through a quick look, there only a few commits between 4.9.27 and
4.10.15 regarding USB-audio.  The suspicious one is

commit fd1a5059610cd3887f1050171a840ca864108730
ALSA: usb-audio: more tolerant packetsize

Could you try to revert this?


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 6/6] sound: replace /proc/bus/usb by /dev/bus/usb

2017-04-17 Thread Takashi Iwai
On Mon, 17 Apr 2017 02:51:11 +0200,
Mauro Carvalho Chehab wrote:
> 
> The /proc/bus/usb devices don't exist anymore, since when we
> got rid of usbfs. Those devices are now seen at
> /dev/bus/usb.
> 
> Signed-off-by: Mauro Carvalho Chehab 

Since it's a driver fix, I applied it to sound tree now.


thanks,

Takashi

> ---
>  sound/usb/usx2y/us122l.c| 2 +-
>  sound/usb/usx2y/usX2Yhwdep.c| 2 +-
>  sound/usb/usx2y/usx2yhwdeppcm.c | 2 +-
>  3 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
> index cf45bf1f7ee0..e118bdca983d 100644
> --- a/sound/usb/usx2y/us122l.c
> +++ b/sound/usb/usx2y/us122l.c
> @@ -472,7 +472,7 @@ static int usb_stream_hwdep_new(struct snd_card *card)
>   hw->ops.mmap = usb_stream_hwdep_mmap;
>   hw->ops.poll = usb_stream_hwdep_poll;
>  
> - sprintf(hw->name, "/proc/bus/usb/%03d/%03d/hwdeppcm",
> + sprintf(hw->name, "/dev/bus/usb/%03d/%03d/hwdeppcm",
>   dev->bus->busnum, dev->devnum);
>   return 0;
>  }
> diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
> index 605e1047c01d..f4b3cda412fc 100644
> --- a/sound/usb/usx2y/usX2Yhwdep.c
> +++ b/sound/usb/usx2y/usX2Yhwdep.c
> @@ -258,7 +258,7 @@ int usX2Y_hwdep_new(struct snd_card *card, struct 
> usb_device* device)
>   hw->ops.mmap = snd_us428ctls_mmap;
>   hw->ops.poll = snd_us428ctls_poll;
>   hw->exclusive = 1;
> - sprintf(hw->name, "/proc/bus/usb/%03d/%03d", device->bus->busnum, 
> device->devnum);
> + sprintf(hw->name, "/dev/bus/usb/%03d/%03d", device->bus->busnum, 
> device->devnum);
>   return 0;
>  }
>  
> diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
> index f95164b91152..d51c7fd7835b 100644
> --- a/sound/usb/usx2y/usx2yhwdeppcm.c
> +++ b/sound/usb/usx2y/usx2yhwdeppcm.c
> @@ -723,7 +723,7 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card)
>   hw->ops.release = snd_usX2Y_hwdep_pcm_release;
>   hw->ops.mmap = snd_usX2Y_hwdep_pcm_mmap;
>   hw->exclusive = 1;
> - sprintf(hw->name, "/proc/bus/usb/%03d/%03d/hwdeppcm", dev->bus->busnum, 
> dev->devnum);
> + sprintf(hw->name, "/dev/bus/usb/%03d/%03d/hwdeppcm", dev->bus->busnum, 
> dev->devnum);
>  
>   err = snd_pcm_new(card, NAME_ALLCAPS" hwdep Audio", 2, 1, 1, &pcm);
>   if (err < 0) {
> -- 
> 2.9.3
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] ALSA: line6: Always setup isochronous transfer properties

2017-02-07 Thread Takashi Iwai
On Mon, 06 Feb 2017 22:54:59 +0100,
Andrej Kruták wrote:
> 
> On Mon, Feb 6, 2017 at 10:19 PM, Takashi Iwai  wrote:
> > On Mon, 06 Feb 2017 20:34:58 +0100,
> > Andrej Krutak wrote:
> >>
> >> While not all line6 devices currently support PCM, it causes no
> >> harm to 'have it prepared'.
> >>
> >> This also fixes toneport, which only has PCM - in which case
> >> we previously skipped the USB transfer properties detection completely.
> >>
> >> Signed-off-by: Andrej Krutak 
> >
> > Well, this looks too complex and vague as a regression fix.  If it
> > were 4.10-rc1, I could take it.  But now it's already rc7 and the next
> > might be final, so I prefer a shorter and easier solution.
> >
> 
> In the end, the patch is just "careful", so that the endpoint
> structures are not read if the devices is not "marked" as having them.

Yes, but it's still not very clear what actually "fixes".

> > That said, we can revert the commit as a clear fix at first for 4.10
> > (with Cc to stable), then take this on top as an enhancement for
> > 4.11.
> >
> > Still it's important to know whether this works on Igor's system, so
> > Igor, please give this one try.
> >
> 
> Thanks to zero-init of toneport_properties_table, the proposed simple
> revert should be enough for toneport, and shouldn't break other
> devices (perhaps HD300-HD500 may start showing the dev_err from
> line6_get_interval()).
> 
> So do as you like - e.g. simple revert for 4.10 and apply this patch
> for 4.11. But I don't mind if you won't :-)

Yes, I now queued the revert patch to for-linus branch, and yours to
for-next branch on top of it.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   3   >