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(>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(),
> +))
> + goto err_free;
> + buf = kmalloc(len, GFP_KERNEL);
> +  

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 = >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, >urb->transfer_dma);
> - if (!u->urb->transfer_buffer)
> + buf = usb_alloc_coherent(ep->chip->dev, u->buffer_size,
> +  GFP_KERNEL, >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(>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 <ti...@suse.de>
---
 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 <ti...@suse.de>
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 <registo.maill...@gmail.com>
Cc: <sta...@vger.kernel.org>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 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(

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, >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, >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 <ti...@suse.de>
> > 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 <jo...@kernel.org>
> > Signed-off-by: Takashi Iwai <ti...@suse.de>
> 
> Looks good to me:
> 
> Reviewed-by: Johan Hovold <jo...@kernel.org>

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 <andreyk...@google.com>
> > > > Tested-by: Andrey Konovalov <andreyk...@google.com>
> > > > Signed-off-by: Takashi Iwai <ti...@suse.de>
> > > > ---
> > > >  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 <ti...@suse.de>
> > ---
> >  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 <andreyk...@google.com>
> > Tested-by: Andrey Konovalov <andreyk...@google.com>
> > Signed-off-by: Takashi Iwai <ti...@suse.de>
> > ---
> >  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 <ti...@suse.de>
> > ---
> >  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), >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 <andreyk...@google.com>
> > Tested-by: Andrey Konovalov <andreyk...@google.com>
> > Signed-off-by: Takashi Iwai <ti...@suse.de>
> > ---
> >  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(>ep1_in_urb) ||
> > +   usb_urb_ep_type_check(>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 <ti...@suse.de>
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 <jo...@kernel.org>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 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(>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 <andreyk...@google.com>
> > Signed-off-by: Takashi Iwai <ti...@suse.de>
> > ---
> > 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(>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, "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 <gre...@linuxfoundation.org>
> 
> 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 <ti...@suse.de>
---
 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), >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 <ti...@suse.de>
---
 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(>instance, chip->dev,
  usb_sndbulkpipe(chip->dev, ep), (void *)urb->buffer,
  PCM_PACKET_SIZE, handler, urb);
+   if (usb_urb_ep_type_check(>instance))
+   return -EINVAL;
init_usb_anchor(>submitted);
 
return 0;
@@ -599,9 +601,12 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 
extra_freq)
mutex_init(>stream_mutex);
spin_lock_init(>playback.lock);
 
-   for (i = 0; i < PCM_N_URBS; i++)
-   hiface_pcm_init_urb(>out_urbs[i], chip, OUT_EP,
+   for (i = 0; i < PCM_N_URBS; i++) {
+   ret = hiface_pcm_init_urb(>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, );
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 <ti...@suse.de>
---
 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,
>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(>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,
>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,
  >urbs[i]);
+   err = usb_urb_ep_type_check(ep->urbs[i].urb);
+   if (err < 0) {
+   dev_err(>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_delete(ep);
+   return err;

[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 <andreyk...@google.com>
Tested-by: Andrey Konovalov <andreyk...@google.com>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 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(>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 <andreyk...@google.com>
Tested-by: Andrey Konovalov <andreyk...@google.com>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 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 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 <ti...@suse.de>
---
 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 <andreyk...@google.com>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
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(>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, "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 <ti...@suse.de>
---
 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 <andreyk...@google.com>
Tested-by: Andrey Konovalov <andreyk...@google.com>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 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(>ep1_in_urb) ||
+   usb_urb_ep_type_check(>midi_out_urb)) {
+   dev_err(dev, "invalid EPs\n");
+   return -EINVAL;
+   }
+
init_waitqueue_head(>ep1_wait_queue);
init_waitqueue_head(>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 <tom.sae...@oracle.com>

For the sound part:
Reviewed-by: Takashi Iwai <ti...@suse.de>


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: <port#>,
> - 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: <port#>,
> - 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:
>   <port#>,,,
> - 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 <binary1...@yahoo.com>
>   - 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 s

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 <ti...@suse.de> 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 <andreyk...@google.com>
> > Signed-off-by: Takashi Iwai <ti...@suse.de>
> 
> 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 <ti...@suse.de>
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 <ti...@suse.de>
---
 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(>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])
+

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 <ti...@suse.de>
> > ---
> >  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(>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 <ti...@suse.de>
---
 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(>instance, chip->dev,
  usb_sndbulkpipe(chip->dev, ep), (void *)urb->buffer,
  PCM_PACKET_SIZE, handler, urb);
+   if (usb_urb_ep_type_check(>instance))
+   return -EINVAL;
init_usb_anchor(>submitted);
 
return 0;
@@ -599,9 +601,12 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 
extra_freq)
mutex_init(>stream_mutex);
spin_lock_init(>playback.lock);
 
-   for (i = 0; i < PCM_N_URBS; i++)
-   hiface_pcm_init_urb(>out_urbs[i], chip, OUT_EP,
+   for (i = 0; i < PCM_N_URBS; i++) {
+   ret = hiface_pcm_init_urb(>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, );
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 <ti...@suse.de>
---
 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,
>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(>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,
>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,
  >urbs[i]);
+   err = usb_urb_ep_type_check(ep->urbs[i].urb);
+   if (err < 0) {
+   dev_err(>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_delete(ep);
+   return err;

[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 <andreyk...@google.com>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 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(>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 <ti...@suse.de>
---
 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 <ti...@suse.de>
---
 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 <ti...@suse.de>
---
 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), >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 <andreyk...@google.com>
Cc: <sta...@vger.kernel.org>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 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 <andreyk...@google.com>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 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(>ep1_in_urb) ||
+   usb_urb_ep_type_check(>midi_out_urb)) {
+   dev_err(dev, "invalid EPs\n");
+   return -EINVAL;
+   }
+
init_waitqueue_head(>ep1_wait_queue);
init_waitqueue_head(>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 <ti...@suse.de>
---
 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(>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(>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, _in, _out);
> > >   if (ret) {
> > >   dev_err(>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(>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, _in, _out);
>   if (ret) {
>   dev_err(>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(>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(>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-04 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(>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 <i...@rudolfschmidt.com>
> Signed-off-by: Takashi Iwai <ti...@suse.de>

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 <ti...@suse.de>
---
 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, ofs),
+

[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 <ti...@suse.de>
---
 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_u

[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 <ti...@suse.de>
---
 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 <i...@rudolfschmidt.com>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 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 <ti...@suse.de>
---
 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 <ti...@suse.de>
---
 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 <ti...@suse.de>
---
 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

[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 <ti...@suse.de>
---
 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_rm

[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 <ti...@suse.de>
---
 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(sub

[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 <ti...@suse.de>
---
 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 

[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 <ti...@suse.de>
---
 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 <ti...@suse.de>
---
 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 <ti...@suse.de>
---
 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:
-  

[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 <ti...@suse.de>
---
 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 <ti...@suse.de>
---
 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_substrea

[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 <ti...@suse.de>
---
 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 = >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 <ti...@suse.de>
---
 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, h

[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 <ti...@suse.de>
---
 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, );
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 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 <ti...@suse.de>
---
 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 <ti...@suse.de>
---
 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_c

[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 <ti...@suse.de>
---
 .../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
+arguments in

[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 <ti...@suse.de>
---
 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 <ti...@suse.de>
---
 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

[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 <ti...@suse.de>
---
 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 <ti...@suse.de>
---
 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

[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 <ti...@suse.de>
---
 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 

[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 <ti...@suse.de>
---
 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_su

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

2017-05-16 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, );
>   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 <ti...@suse.de> 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 <d...@andree.sk>
> >
> > 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


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

2017-02-06 Thread Takashi Iwai
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.

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,

Takashi

> ---
>  sound/usb/line6/driver.c | 49 
> ++--
>  1 file changed, 27 insertions(+), 22 deletions(-)
> 
> diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
> index 90009c0..0ff5a7d 100644
> --- a/sound/usb/line6/driver.c
> +++ b/sound/usb/line6/driver.c
> @@ -492,42 +492,46 @@ static void line6_destruct(struct snd_card *card)
>   usb_put_dev(usbdev);
>  }
>  
> -/* get data from endpoint descriptor (see usb_maxpacket): */
> -static void line6_get_interval(struct usb_line6 *line6)
> +static void line6_get_usb_properties(struct usb_line6 *line6)
>  {
>   struct usb_device *usbdev = line6->usbdev;
>   const struct line6_properties *properties = line6->properties;
>   int pipe;
> - struct usb_host_endpoint *ep;
> + struct usb_host_endpoint *ep = NULL;
>  
> - if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
> - pipe =
> - usb_rcvintpipe(line6->usbdev, 
> line6->properties->ep_ctrl_r);
> - } else {
> - pipe =
> - usb_rcvbulkpipe(line6->usbdev, 
> line6->properties->ep_ctrl_r);
> + if (properties->capabilities & LINE6_CAP_CONTROL) {
> + if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
> + pipe = usb_rcvintpipe(line6->usbdev,
> + line6->properties->ep_ctrl_r);
> + } else {
> + pipe = usb_rcvbulkpipe(line6->usbdev,
> + line6->properties->ep_ctrl_r);
> + }
> + ep = usbdev->ep_in[usb_pipeendpoint(pipe)];
>   }
> - ep = usbdev->ep_in[usb_pipeendpoint(pipe)];
>  
> + /* Control data transfer properties */
>   if (ep) {
>   line6->interval = ep->desc.bInterval;
> - if (usbdev->speed == USB_SPEED_LOW) {
> - line6->intervals_per_second = 
> USB_LOW_INTERVALS_PER_SECOND;
> - line6->iso_buffers = USB_LOW_ISO_BUFFERS;
> - } else {
> - line6->intervals_per_second = 
> USB_HIGH_INTERVALS_PER_SECOND;
> - line6->iso_buffers = USB_HIGH_ISO_BUFFERS;
> - }
> -
>   line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
>   } else {
> - dev_err(line6->ifcdev,
> - "endpoint not available, using fallback values");
> + if (properties->capabilities & LINE6_CAP_CONTROL) {
> + dev_err(line6->ifcdev,
> + "endpoint not available, using fallback 
> values");
> + }
>   line6->interval = LINE6_FALLBACK_INTERVAL;
>   line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE;
>   }
> -}
>  
> + /* Isochronous transfer properties */
> + if (usbdev->speed == USB_SPEED_LOW) {
> + line6->intervals_per_second = USB_LOW_INTERVALS_PER_SECOND;
> + line6->iso_buffers = USB_LOW_ISO_BUFFERS;
> + } else {
> + line6->intervals_per_second = USB_HIGH_INTERVALS_PER_SECOND;
> + line6->iso_buffers = USB_HIGH_ISO_BUFFERS;
> + }
> +}
>  
>  /* Enable buffering of incoming messages, flush the buffer */
>  static int line6_hwdep_open(struct snd_hwdep *hw, struct file *file)
> @@ -754,8 +758,9 @@ int line6_probe(struct usb_interface *interface,
>   goto error;
>   }
>  
> + line6_get_usb_properties(line6);
> +
>   if (properties->capabilities & LINE6_CAP_CONTROL) {
> - line6_get_interval(line6);
>   ret = line6_init_cap_control(line6);
>   if (ret < 0)
>   goto error;
> -- 
> 2.7.4
> 
--
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: Fwd: Regression: Line6 Toneport stops working on 4.10-rc5

2017-02-06 Thread Takashi Iwai
On Mon, 06 Feb 2017 12:04:29 +0100,
Andrej Kruták wrote:
> 
> On Mon, Feb 6, 2017 at 12:01 PM, Takashi Iwai <ti...@suse.de> wrote:
> > On Mon, 06 Feb 2017 11:18:44 +0100,
> > Greg KH wrote:
> >>
> >> On Mon, Feb 06, 2017 at 01:01:56PM +0300, Igor Zinovev wrote:
> >> > Hello again!
> >> >
> >> > Thanks for the advice, but bisecting the whole tree took me quite a
> >> > while and I ended up stuck because booting on some bisect states has
> >> > led my system to run without some devices, like wireless and sound. So
> >> > I tried to bisect the sound/usb/line6 path. It turns out that this
> >> > commit is the point where it breaks for me:
> >> > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/sound/usb/line6?id=f6a0dd107ad0c8b59d1c9735eea4b8cb9f460949
> >> >
> >> > In fact, when I apply the reverse patch on top of 4.10-rc7, it fixes
> >> > the problem for me.
> >>
> >> Wonderful, thanks so much for tracking this down!
> >>
> >> > Should I bring some of the people that are mentioned in the commit
> >> > into this conversation?
> >>
> >> I've done so now.  Andrej and Takashi, the above patch causes a
> >> regression for Igor, any thoughts?  Should we just revert it?
> >
> > Yeah, the patch looks wrong, the function line6_get_interval() should
> > be called unconditionally.
> >
> > I'm going to queue a revert for 4.10-final.
> >
> 
> Yep, on the first look it's suspicious. I'll have a look on it in the
> evening - not sure simple revert is the ideal solution... I'll get
> back to you.

I guess in this case the revert is the best option.
But I'll postpone it until tomorrow.  If you find a better solution,
please let me know.

> PS: Thanks for the bisecting, Igor!
> PPS: Maybe this should go also to 4.9 stable, once resolved...

Yes, definitely.


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: Fwd: Regression: Line6 Toneport stops working on 4.10-rc5

2017-02-06 Thread Takashi Iwai
On Mon, 06 Feb 2017 11:18:44 +0100,
Greg KH wrote:
> 
> On Mon, Feb 06, 2017 at 01:01:56PM +0300, Igor Zinovev wrote:
> > Hello again!
> > 
> > Thanks for the advice, but bisecting the whole tree took me quite a
> > while and I ended up stuck because booting on some bisect states has
> > led my system to run without some devices, like wireless and sound. So
> > I tried to bisect the sound/usb/line6 path. It turns out that this
> > commit is the point where it breaks for me:
> > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/sound/usb/line6?id=f6a0dd107ad0c8b59d1c9735eea4b8cb9f460949
> > 
> > In fact, when I apply the reverse patch on top of 4.10-rc7, it fixes
> > the problem for me.
> 
> Wonderful, thanks so much for tracking this down!
> 
> > Should I bring some of the people that are mentioned in the commit
> > into this conversation?
> 
> I've done so now.  Andrej and Takashi, the above patch causes a
> regression for Igor, any thoughts?  Should we just revert it?

Yeah, the patch looks wrong, the function line6_get_interval() should
be called unconditionally.

I'm going to queue a revert for 4.10-final.


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: [alsa-devel] Jack sensing in snd_usb_audio ?

2016-10-18 Thread Takashi Iwai
On Tue, 18 Oct 2016 15:33:42 +0200,
Felipe Ferreri Tonello wrote:
> 
> Hi Takashi
> 
> On 18/10/16 13:07, Takashi Iwai wrote:
> > On Wed, 12 Oct 2016 18:15:04 +0200,
> > Bastien Nocera wrote:
> >>
> >> On Wed, 2016-10-12 at 18:06 +0200, Clemens Ladisch wrote:
> >>> Bastien Nocera wrote:
> >>>> On Wed, 2016-10-12 at 14:43 +0200, Clemens Ladisch wrote:
> >>>>> Bastien Nocera wrote:
> >>>>>> "
> >>>>>> A change of state in the audio function is most often caused by
> >>>>>> a
> >>>>>> certain event that takes place. An event can either be user-
> >>>>>> initiated
> >>>>>> or device-initiated. User-initiated jack insertion or removal
> >>>>>> is a
> >>>>>> typical example of a user-initiated event.
> >>>>>> "
> >>>>>
> >>>>>
> >>>>> There are not many USB Audio 2.0 devices, and I'm not aware of
> >>>>> any
> >>>>> that actually implements this.
> >>>>
> >>>>
> >>>> I guess I would see whether there are events if I captured the USB
> >>>> traffic even without special handling/turning on a feature in the
> >>>> drivers, right?
> >>>
> >>>
> >>> Most devices do not even have the status endpoint (see "lsusb -v").
> >>> To check what events arrive, you can add logging to the
> >>> snd_usb_mixer_interrupt() function.
> >>
> >> I'm guessing it doesn't support it then (see attached log)
> > 
> > So this looks like a HID, not from the audio device class.
> > It's an oft-seen implementation.
> > 
> >> I also checked the input device output when plugging in something, with
> >> evtest, and no feedback either.
> > 
> > Then at first you need to hack a HID driver to support this device.
> > It'll create an input device, and then we'll need to find some way to
> > couple the given input device and the audio device.  We can parse the
> > sysfs device path to figure out, but I'm not sure what's the best way
> > to tell it to applications.
> > 
> 
> Why not use similar API as a normal ALSA card? This will enable jack
> detection by default in applications using kcontrol interface.

Are you suggesting to create another sound card object by a HID
driver?  This would be even less useful.  Then you'll have two
individual sound cards in the end that have no connection between
them.


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: [alsa-devel] Jack sensing in snd_usb_audio ?

2016-10-18 Thread Takashi Iwai
On Wed, 12 Oct 2016 18:15:04 +0200,
Bastien Nocera wrote:
> 
> On Wed, 2016-10-12 at 18:06 +0200, Clemens Ladisch wrote:
> > Bastien Nocera wrote:
> > > On Wed, 2016-10-12 at 14:43 +0200, Clemens Ladisch wrote:
> > > > Bastien Nocera wrote:
> > > > > "
> > > > > A change of state in the audio function is most often caused by
> > > > > a
> > > > > certain event that takes place. An event can either be user-
> > > > > initiated
> > > > > or device-initiated. User-initiated jack insertion or removal
> > > > > is a
> > > > > typical example of a user-initiated event.
> > > > > "
> > > > 
> > > > 
> > > > There are not many USB Audio 2.0 devices, and I'm not aware of
> > > > any
> > > > that actually implements this.
> > > 
> > > 
> > > I guess I would see whether there are events if I captured the USB
> > > traffic even without special handling/turning on a feature in the
> > > drivers, right?
> > 
> > 
> > Most devices do not even have the status endpoint (see "lsusb -v").
> > To check what events arrive, you can add logging to the
> > snd_usb_mixer_interrupt() function.
> 
> I'm guessing it doesn't support it then (see attached log)

So this looks like a HID, not from the audio device class.
It's an oft-seen implementation.

> I also checked the input device output when plugging in something, with
> evtest, and no feedback either.

Then at first you need to hack a HID driver to support this device.
It'll create an input device, and then we'll need to find some way to
couple the given input device and the audio device.  We can parse the
sysfs device path to figure out, but I'm not sure what's the best way
to tell it to applications.


Takashi

> Bus 003 Device 035: ID 1b3f:2008 Generalplus Technology Inc. 
> Device Descriptor:
>   bLength18
>   bDescriptorType 1
>   bcdUSB   1.10
>   bDeviceClass0 
>   bDeviceSubClass 0 
>   bDeviceProtocol 0 
>   bMaxPacketSize0 8
>   idVendor   0x1b3f Generalplus Technology Inc.
>   idProduct  0x2008 
>   bcdDevice1.00
>   iManufacturer   1 GeneralPlus
>   iProduct2 USB Audio Device
>   iSerial 0 
>   bNumConfigurations  1
>   Configuration Descriptor:
> bLength 9
> bDescriptorType 2
> wTotalLength  253
> bNumInterfaces  4
> bConfigurationValue 1
> iConfiguration  0 
> bmAttributes 0x80
>   (Bus Powered)
> MaxPower  100mA
> Interface Descriptor:
>   bLength 9
>   bDescriptorType 4
>   bInterfaceNumber0
>   bAlternateSetting   0
>   bNumEndpoints   0
>   bInterfaceClass 1 Audio
>   bInterfaceSubClass  1 Control Device
>   bInterfaceProtocol  0 
>   iInterface  0 
>   AudioControl Interface Descriptor:
> bLength10
> bDescriptorType36
> bDescriptorSubtype  1 (HEADER)
> bcdADC   1.00
> wTotalLength  100
> bInCollection   2
> baInterfaceNr( 0)   1
> baInterfaceNr( 1)   2
>   AudioControl Interface Descriptor:
> bLength12
> bDescriptorType36
> bDescriptorSubtype  2 (INPUT_TERMINAL)
> bTerminalID 1
> wTerminalType  0x0101 USB Streaming
> bAssocTerminal  0
> bNrChannels 2
> wChannelConfig 0x0003
>   Left Front (L)
>   Right Front (R)
> iChannelNames   0 
> iTerminal   0 
>   AudioControl Interface Descriptor:
> bLength12
> bDescriptorType36
> bDescriptorSubtype  2 (INPUT_TERMINAL)
> bTerminalID 4
> wTerminalType  0x0201 Microphone
> bAssocTerminal  0
> bNrChannels 1
> wChannelConfig 0x0001
>   Left Front (L)
> iChannelNames   0 
> iTerminal   0 
>   AudioControl Interface Descriptor:
> bLength 9
> bDescriptorType36
> bDescriptorSubtype  3 (OUTPUT_TERMINAL)
> bTerminalID 3
> wTerminalType  0x0301 Speaker
> bAssocTerminal  0
> bSourceID   6
> iTerminal   0 
>   AudioControl Interface Descriptor:
> bLength 9
> bDescriptorType36
> bDescriptorSubtype  3 (OUTPUT_TERMINAL)
> bTerminalID 2
> wTerminalType  0x0101 USB Streaming
> bAssocTerminal  0
> bSourceID   9
> iTerminal   0 
>   AudioControl Interface Descriptor:
> bLength 7
>  

Re: [PATCH] ALSA: usb: caiaq: audio: don't print error when allocating urb fails

2016-08-11 Thread Takashi Iwai
On Thu, 11 Aug 2016 22:40:11 +0200,
Wolfram Sang wrote:
> 
> kmalloc will print enough information in case of failure.
> 
> Signed-off-by: Wolfram Sang 

Applied, thanks.


Takashi

> ---
>  sound/usb/caiaq/audio.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
> index 327f8642ca80e6..8f66ba730d69d9 100644
> --- a/sound/usb/caiaq/audio.c
> +++ b/sound/usb/caiaq/audio.c
> @@ -739,7 +739,6 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev 
> *cdev, int dir, int *ret)
>   for (i = 0; i < N_URBS; i++) {
>   urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL);
>   if (!urbs[i]) {
> - dev_err(dev, "unable to usb_alloc_urb(), OOM!?\n");
>   *ret = -ENOMEM;
>   return urbs;
>   }
> -- 
> 2.8.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 1/2] usb-audio: correct speed checking

2016-05-08 Thread Takashi Iwai
On Wed, 04 May 2016 14:18:39 +0200,
Oliver Neukum wrote:
> 
> Allow handling SS+ USB devices correctly.
> 
> Signed-off-by: Oliver Neukum 

Thanks, applied both patches now.


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] Documentation: nousb is a module parameter

2015-11-10 Thread Takashi Iwai
On Tue, 10 Nov 2015 14:15:44 +0100,
Oliver Neukum wrote:
> 
> The documentation wrongly implied that it is a core parameter.
> That is not true. If usbcore is compiled as a module, a module
> parameter needs a prefix.

The code drivers/usb/core/usb.c has the following:

/* To disable USB, kernel command line is 'nousb' not 'usbcore.nousb' */
#ifdef MODULE
module_param(nousb, bool, 0444);
#else
core_param(nousb, nousb, bool, 0444);
#endif

... which is quite confusing.

This change was introduced by commit 785895ff1fed
USB: Don't use __module_param_call; use core_param.

IMO, the current setup is a bad mixture to try keeping some
compatibility while breaking others.  We should either keep "nousb"
always working or unify as a module option.


Takashi

> 
> Signed-off-by: Oliver Neukum 
> ---
>  Documentation/kernel-parameters.txt | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/kernel-parameters.txt 
> b/Documentation/kernel-parameters.txt
> index 22a4b68..a805dff 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -2536,8 +2536,6 @@ bytes respectively. Such letter suffixes can also be 
> entirely omitted.
>  
>   notsc   [BUGS=X86-32] Disable Time Stamp Counter
>  
> - nousb   [USB] Disable the USB subsystem
> -
>   nowatchdog  [KNL] Disable both lockup detectors, i.e.
>  soft-lockup and NMI watchdog (hard-lockup).
>  
> @@ -3852,6 +3850,8 @@ bytes respectively. Such letter suffixes can also be 
> entirely omitted.
>  USB_REQ_GET_DESCRIPTOR request in milliseconds
>   (default 5000 = 5.0 seconds).
>  
> + usbcore.nousb   [USB] Disable the USB subsystem
> +
>   usbhid.mousepoll=
>   [USBHID] The interval which mice are to be polled at.
>  
> -- 
> 2.1.4
> 
--
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: [RESEND][PATCH] Bluetooth: Make request workqueue freezable

2015-05-21 Thread Takashi Iwai
At Thu, 21 May 2015 13:37:56 -0400 (EDT),
Alan Stern wrote:
 
 On Thu, 21 May 2015, Takashi Iwai wrote:
 
  At Thu, 21 May 2015 11:26:17 -0400 (EDT),
  Alan Stern wrote:
   
   On Thu, 21 May 2015, Takashi Iwai wrote:
   
At Thu, 21 May 2015 10:18:08 -0400 (EDT),
Alan Stern wrote:
 
 On Thu, 21 May 2015, Takashi Iwai wrote:
 
  Then avoiding the failed firmware is no solution, indeed.
  If it's a new probe, it should be never executed during resume.
 
 Can you expand this comment?  What's wrong with probing during resume?

Well, if the probe requires the access to a user-space file, it can't
be done during resume.  That's the very problem we're seeing now.
The firmware loader can't help much alone if it's a new device
object.
   
   But the same thing happens during early boot, if the driver is built 
   into the kernel.  When the probe occurs, userspace isn't up and running 
   yet, so the firmware loader can't do anything.
   
   Why should probe during resume be any worse than probe during early 
   boot?
  
  The early boot has initrd, so the files can be there.  But the resume
  has no way to fetch the file except for cached data.
 
 I suppose USB could delay re-probing until userspace is running again,
 if we knew when that was.  But it would be awkward and prone to races.  
 It also would leave a user-visible window of time during which the 
 device does not exist, which we want to avoid.  (This may not matter 
 for bluetooth, but it does matter for other kinds of devices.)

Right.

 I would prefer to solve this problem in a different way, if possible.

Well, we're back in square again :)

But, before going further the discussion in loop again, I'd like to
know which firmware file actually hits.  Is it a non-existing
firmware?  Or is it a firmware that should have been cached?  In the
latter case, why it isn't used?


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: [RESEND][PATCH] Bluetooth: Make request workqueue freezable

2015-05-21 Thread Takashi Iwai
At Thu, 21 May 2015 14:07:11 +0200,
Marcel Holtmann wrote:
 
 Hi Takashi,
 
  The data is cached in RAM.  More specifically, the former loaded
  firmware files are reloaded and saved at suspend for each device
  object.  See fw_pm_notify() in firmware_class.c.
  
  OK, this may be a stupid idea, but do we know the firmware
  was successfully loaded in the first place?
  Also btusb is in the habit of falling back to a generic
  firmware in some places. It seems to me that caching
  firmware is conceptually not enough, but we'd also need
  to record the absence of firmware images.
  
  in a lot of cases the firmware is optional. The device will operate fine 
  without the firmware. There are a few devices where the firmware is 
  required, but for many it just contains patches.
  
  It would be nice if we could tell request_firmware() if it is optional 
  or mandatory firmware. Or if it should just cache the status of a 
  missing firmware as well.
  
  OK, below is a quick hack to record the failed f/w files, too.
  Not sure whether this helps, though.  Proper tests are appreciated.
  
  
  
  This doesn't quite work. We end up with the name on fw_names but
  the firmware isn't actually on the firmware cache list.
  
  If request_firmware fails to get the firmware from the filesystem,
  release firmware will be called which is going to free the
  firmware_buf which has been marked as failed anyway. The only
  way to make this work would be to always piggy back and increase
  the ref so it always stays around. But this also marks the firmware
  as a permanent failure. There would need to be a hook somewhere
  to force a cache drop, else there would be no way to add new
  firmware to a running system without a reboot.
  
  Perhaps we split the difference: keep a list of firmware images
  that failed to load in the past and if one is requested during
  a time when usermodehelper isn't available, silently return an
  error? This way, if correct firmware is loaded at a regular time
  the item can be removed from the list.
  
  Well, IMO, it's way too much expectation for the generic f/w loader.
  The driver itself must know already which should be really loaded.
  The fact is that it's the driver who calls the function that might not
  work in the resume path.  So the driver can deal with such exceptions
  at best.
 
 I keep repeating myself here. From the driver point of view it goes
 via probe() callback of the USB driver. So the driver does not
 know. For the driver it looks like a brand new device. There are
 platforms that might decide to just kill the power to the USB bus
 where the Bluetooth controller sits on. It gets the power back on
 resume. However this means it is a brand new device at that
 point. So the driver should not have to remember everything. 

Then avoiding the failed firmware is no solution, indeed.
If it's a new probe, it should be never executed during resume.
That is, either freeze the work like Laura's patch or explicitly allow
the UMH lock wait like my patch.  Laura's patch has a merit that it's
much simpler.  OTOH, if you want to keep the changes only in
request_firmware() call, you can think of changes like my patch; a
revised version is attached below.


Takashi

---
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 171841ad1008..87157f557263 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -97,21 +97,6 @@ static inline long firmware_loading_timeout(void)
return loading_timeout  0 ? loading_timeout * HZ : MAX_JIFFY_OFFSET;
 }
 
-/* firmware behavior options */
-#define FW_OPT_UEVENT  (1U  0)
-#define FW_OPT_NOWAIT  (1U  1)
-#ifdef CONFIG_FW_LOADER_USER_HELPER
-#define FW_OPT_USERHELPER  (1U  2)
-#else
-#define FW_OPT_USERHELPER  0
-#endif
-#ifdef CONFIG_FW_LOADER_USER_HELPER_FALLBACK
-#define FW_OPT_FALLBACKFW_OPT_USERHELPER
-#else
-#define FW_OPT_FALLBACK0
-#endif
-#define FW_OPT_NO_WARN (1U  3)
-
 struct firmware_cache {
/* firmware_buf instance will be added into the below list */
spinlock_t lock;
@@ -1085,8 +1070,7 @@ static int assign_firmware_buf(struct firmware *fw, 
struct device *device,
 }
 
 /* called from request_firmware() and request_firmware_work_func() */
-static int
-_request_firmware(const struct firmware **firmware_p, const char *name,
+int _request_firmware(const struct firmware **firmware_p, const char *name,
  struct device *device, unsigned int opt_flags)
 {
struct firmware *fw;
@@ -1099,13 +1083,15 @@ _request_firmware(const struct firmware **firmware_p, 
const char *name,
if (!name || name[0] == '\0')
return -EINVAL;
 
+   /* Need to pin this module until return */
+   __module_get(THIS_MODULE);
ret = _request_firmware_prepare(fw, name, device);
if (ret = 0) /* error or already assigned */
goto out;
 
ret = 0;
timeout = 

Re: [RESEND][PATCH] Bluetooth: Make request workqueue freezable

2015-05-21 Thread Takashi Iwai
At Thu, 21 May 2015 10:18:08 -0400 (EDT),
Alan Stern wrote:
 
 On Thu, 21 May 2015, Takashi Iwai wrote:
 
  Then avoiding the failed firmware is no solution, indeed.
  If it's a new probe, it should be never executed during resume.
 
 Can you expand this comment?  What's wrong with probing during resume?

Well, if the probe requires the access to a user-space file, it can't
be done during resume.  That's the very problem we're seeing now.
The firmware loader can't help much alone if it's a new device
object.

 The USB stack does carry out probes during resume under certain
 circumstances.  A driver lacking a reset_resume callback is one of
 those circumstances.

So, having a proper reset_resume in btusb would help in the end?


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: [RESEND][PATCH] Bluetooth: Make request workqueue freezable

2015-05-21 Thread Takashi Iwai
At Thu, 21 May 2015 11:26:17 -0400 (EDT),
Alan Stern wrote:
 
 On Thu, 21 May 2015, Takashi Iwai wrote:
 
  At Thu, 21 May 2015 10:18:08 -0400 (EDT),
  Alan Stern wrote:
   
   On Thu, 21 May 2015, Takashi Iwai wrote:
   
Then avoiding the failed firmware is no solution, indeed.
If it's a new probe, it should be never executed during resume.
   
   Can you expand this comment?  What's wrong with probing during resume?
  
  Well, if the probe requires the access to a user-space file, it can't
  be done during resume.  That's the very problem we're seeing now.
  The firmware loader can't help much alone if it's a new device
  object.
 
 But the same thing happens during early boot, if the driver is built 
 into the kernel.  When the probe occurs, userspace isn't up and running 
 yet, so the firmware loader can't do anything.
 
 Why should probe during resume be any worse than probe during early 
 boot?

The early boot has initrd, so the files can be there.  But the resume
has no way to fetch the file except for cached data.


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: [RESEND][PATCH] Bluetooth: Make request workqueue freezable

2015-05-21 Thread Takashi Iwai
At Thu, 21 May 2015 19:27:41 +0200,
Arend van Spriel wrote:
 
 On 05/21/15 17:35, Takashi Iwai wrote:
  At Thu, 21 May 2015 11:26:17 -0400 (EDT),
  Alan Stern wrote:
 
  On Thu, 21 May 2015, Takashi Iwai wrote:
 
  At Thu, 21 May 2015 10:18:08 -0400 (EDT),
  Alan Stern wrote:
 
  On Thu, 21 May 2015, Takashi Iwai wrote:
 
  Then avoiding the failed firmware is no solution, indeed.
  If it's a new probe, it should be never executed during resume.
 
  Can you expand this comment?  What's wrong with probing during resume?
 
  Well, if the probe requires the access to a user-space file, it can't
  be done during resume.  That's the very problem we're seeing now.
  The firmware loader can't help much alone if it's a new device
  object.
 
  But the same thing happens during early boot, if the driver is built
  into the kernel.  When the probe occurs, userspace isn't up and running
  yet, so the firmware loader can't do anything.
 
  Why should probe during resume be any worse than probe during early
  boot?
 
  The early boot has initrd, so the files can be there.  But the resume
  has no way to fetch the file except for cached data.
 
 but initrd is optional so without initrd it is pretty much the same.

User can build the firmware into the kernel.


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: [RESEND][PATCH] Bluetooth: Make request workqueue freezable

2015-05-20 Thread Takashi Iwai
At Tue, 19 May 2015 19:42:55 +0200,
Oliver Neukum wrote:
 
 On Tue, 2015-05-19 at 19:13 +0200, Takashi Iwai wrote:
  At Tue, 19 May 2015 10:26:46 -0400 (EDT),
  Alan Stern wrote:
   
   Of just have request_firmware()
  actually sleep until userspace is ready. Seriously, why is
  request_firmware not just sleeping for us.
   
   It won't work.  The request_firmware call is part of the probe 
   sequence, which in turn is part of the resume sequence.  Userspace 
   doesn't start running again until the resume sequence is finished.  If 
   request_firmware waited for userspace, it would hang.
  
  Note that the recent request_firmware() doesn't need the user-space
  invocation (unless the fallback is explicitly enabled) but loads the
 
 That is a dangerous approach. You cannot be sure you can do file IO.
 It depends on the exact shape of the device tree.
 
It's the reason why firmware loader still takes UMH lock (thus we're
seeing this very problem).

  file directly.  And, request_firmware() for the cached data is valid
  to be called in the resume path.
 
 Well, yes, if your data is cached in RAM, all is well. But that leads
 to the same problem one step further. What must be cached?

The data is cached in RAM.  More specifically, the former loaded
firmware files are reloaded and saved at suspend for each device
object.  See fw_pm_notify() in firmware_class.c.

The question is then why the cached data isn't used.  I have no
concrete answer to it for now, need more investigation, but my wild
guess is that it's because the device itself is being renewed.
Or, something wrong in firmware_class.c.


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: [RESEND][PATCH] Bluetooth: Make request workqueue freezable

2015-05-20 Thread Takashi Iwai
At Wed, 20 May 2015 11:46:31 +0200,
Marcel Holtmann wrote:
 
 Hi Oliver,
 
  The data is cached in RAM.  More specifically, the former loaded
  firmware files are reloaded and saved at suspend for each device
  object.  See fw_pm_notify() in firmware_class.c.
  
  OK, this may be a stupid idea, but do we know the firmware
  was successfully loaded in the first place?
  Also btusb is in the habit of falling back to a generic
  firmware in some places. It seems to me that caching
  firmware is conceptually not enough, but we'd also need
  to record the absence of firmware images.
 
 in a lot of cases the firmware is optional. The device will operate fine 
 without the firmware. There are a few devices where the firmware is required, 
 but for many it just contains patches.
 
 It would be nice if we could tell request_firmware() if it is optional or 
 mandatory firmware. Or if it should just cache the status of a missing 
 firmware as well.

OK, below is a quick hack to record the failed f/w files, too.
Not sure whether this helps, though.  Proper tests are appreciated.


Takashi

---
From: Takashi Iwai ti...@suse.de
Subject: [PATCH] firmware: cache failed firmwares, too

Signed-off-by: Takashi Iwai ti...@suse.de
---
 drivers/base/firmware_class.c | 33 -
 1 file changed, 12 insertions(+), 21 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 171841ad1008..a15af7289c94 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -1035,6 +1035,8 @@ _request_firmware_prepare(struct firmware **firmware_p, 
const char *name,
firmware-priv = buf;
 
if (ret  0) {
+   if (buf-size == -1UL)
+   return -ENOENT; /* already recorded as failure */
ret = sync_cached_firmware_buf(buf);
if (!ret) {
fw_set_page_data(buf, firmware);
@@ -1047,17 +1049,12 @@ _request_firmware_prepare(struct firmware **firmware_p, 
const char *name,
return 1; /* need to load */
 }
 
-static int assign_firmware_buf(struct firmware *fw, struct device *device,
+static void assign_firmware_buf(struct firmware *fw, struct device *device,
   unsigned int opt_flags)
 {
struct firmware_buf *buf = fw-priv;
 
mutex_lock(fw_lock);
-   if (!buf-size || is_fw_load_aborted(buf)) {
-   mutex_unlock(fw_lock);
-   return -ENOENT;
-   }
-
/*
 * add firmware name into devres list so that we can auto cache
 * and uncache firmware for device.
@@ -1079,9 +1076,9 @@ static int assign_firmware_buf(struct firmware *fw, 
struct device *device,
}
 
/* pass the pages buffer to driver at the last minute */
-   fw_set_page_data(buf, fw);
+   if (buf-size != -1UL)
+   fw_set_page_data(buf, fw);
mutex_unlock(fw_lock);
-   return 0;
 }
 
 /* called from request_firmware() and request_firmware_work_func() */
@@ -1124,6 +1121,9 @@ _request_firmware(const struct firmware **firmware_p, 
const char *name,
 
ret = fw_get_filesystem_firmware(device, fw-priv);
if (ret) {
+   struct firmware_buf *buf = fw-priv;
+
+   buf-size = -1UL; /* failed */
if (!(opt_flags  FW_OPT_NO_WARN))
dev_warn(device,
 Direct firmware load for %s failed with error 
%d\n,
@@ -1132,12 +1132,12 @@ _request_firmware(const struct firmware **firmware_p, 
const char *name,
dev_warn(device, Falling back to user helper\n);
ret = fw_load_from_user_helper(fw, name, device,
   opt_flags, timeout);
+   if (ret)
+   buf-size = -1UL; /* failed */
}
}
 
-   if (!ret)
-   ret = assign_firmware_buf(fw, device, opt_flags);
-
+   assign_firmware_buf(fw, device, opt_flags);
usermodehelper_read_unlock();
 
  out:
@@ -1435,17 +1435,8 @@ static void __async_dev_cache_fw_image(void *fw_entry,
   async_cookie_t cookie)
 {
struct fw_cache_entry *fce = fw_entry;
-   struct firmware_cache *fwc = fw_cache;
-   int ret;
-
-   ret = cache_firmware(fce-name);
-   if (ret) {
-   spin_lock(fwc-name_lock);
-   list_del(fce-list);
-   spin_unlock(fwc-name_lock);
 
-   free_fw_cache_entry(fce);
-   }
+   cache_firmware(fce-name);
 }
 
 /* called with dev-devres_lock held */
-- 
2.4.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


  1   2   >