[alsa-devel] [PATCH] 6fire: fix DMA issues with URB transfer_buffer usage
Takashi Iwai
tiwai at suse.de
Wed Aug 7 16:05:37 CEST 2013
At Wed, 7 Aug 2013 15:59:07 +0200,
Torsten Schenk wrote:
>
> On Wed, 07 Aug 2013 14:43:43 +0200
> Takashi Iwai <tiwai at suse.de> wrote:
>
> > At Tue, 06 Aug 2013 14:53:24 +0300,
> > Jussi Kivilinna wrote:
> > >
> > > Patch fixes 6fire not to use stack as URB transfer_buffer. URB
> > > buffers need to be DMA-able, which stack is not. Furthermore,
> > > transfer_buffer should not be allocated as part of larger device
> > > structure because DMA coherency issues and patch fixes this issue
> > > too.
>
> Thanks for the information. There is another section where this applies
> in midi.c/midi.h. I can post a patch later.
Yes, please.
> > > Patch is only compile tested.
> >
> > The changes look OK, but I'd like to let it checked with a real
> > hardware before putting to stable kernel.
> >
> > Torsten, could you check this?
>
> The patch works nicely.
OK, I queued the patch to sound git tree now.
> I'm just wondering if instead of calling kmalloc() every time it'd be
> better to put a global sender_buffer and a mutex into the comm_runtime
> struct and lock it every time a writeX is performed. This also would
> have the advantage that message blocks would never overlap which
> currently is possible.
>
> I can prepare a patch on top of this one and send it later, if you
> agree.
Yes, it'd be much better.
thanks,
Takashi
>
> Thanks,
> Torsten
>
> >
> >
> > thanks,
> >
> > Takashi
> >
> > >
> > > Cc: stable at vger.kernel.org
> > > Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
> > > ---
> > > sound/usb/6fire/comm.c | 38 ++++++++++++++++++++++++++++++++
> > > +----- sound/usb/6fire/comm.h | 2 +-
> > > 2 files changed, 34 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c
> > > index 9e6e3ff..23452ee 100644
> > > --- a/sound/usb/6fire/comm.c
> > > +++ b/sound/usb/6fire/comm.c
> > > @@ -110,19 +110,37 @@ static int usb6fire_comm_send_buffer(u8
> > > *buffer, struct usb_device *dev) static int usb6fire_comm_write8
> > > (struct comm_runtime *rt, u8 request, u8 reg, u8 value)
> > > {
> > > - u8 buffer[13]; /* 13: maximum length of message */
> > > + u8 *buffer;
> > > + int ret;
> > > +
> > > + /* 13: maximum length of message */
> > > + buffer = kmalloc(13, GFP_KERNEL);
> > > + if (!buffer)
> > > + return -ENOMEM;
> > >
> > > usb6fire_comm_init_buffer(buffer, 0x00, request, reg,
> > > value, 0x00);
> > > - return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
> > > + ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
> > > +
> > > + kfree(buffer);
> > > + return ret;
> > > }
> > >
> > > static int usb6fire_comm_write16(struct comm_runtime *rt, u8
> > > request, u8 reg, u8 vl, u8 vh)
> > > {
> > > - u8 buffer[13]; /* 13: maximum length of message */
> > > + u8 *buffer;
> > > + int ret;
> > > +
> > > + /* 13: maximum length of message */
> > > + buffer = kmalloc(13, GFP_KERNEL);
> > > + if (!buffer)
> > > + return -ENOMEM;
> > >
> > > usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl,
> > > vh);
> > > - return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
> > > + ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
> > > +
> > > + kfree(buffer);
> > > + return ret;
> > > }
> > >
> > > int usb6fire_comm_init(struct sfire_chip *chip)
> > > @@ -135,6 +153,12 @@ int usb6fire_comm_init(struct sfire_chip *chip)
> > > if (!rt)
> > > return -ENOMEM;
> > >
> > > + rt->receiver_buffer = kzalloc(COMM_RECEIVER_BUFSIZE,
> > > GFP_KERNEL);
> > > + if (!rt->receiver_buffer) {
> > > + kfree(rt);
> > > + return -ENOMEM;
> > > + }
> > > +
> > > urb = &rt->receiver;
> > > rt->serial = 1;
> > > rt->chip = chip;
> > > @@ -153,6 +177,7 @@ int usb6fire_comm_init(struct sfire_chip *chip)
> > > urb->interval = 1;
> > > ret = usb_submit_urb(urb, GFP_KERNEL);
> > > if (ret < 0) {
> > > + kfree(rt->receiver_buffer);
> > > kfree(rt);
> > > snd_printk(KERN_ERR PREFIX "cannot create comm
> > > data receiver."); return ret;
> > > @@ -171,6 +196,9 @@ void usb6fire_comm_abort(struct sfire_chip
> > > *chip)
> > > void usb6fire_comm_destroy(struct sfire_chip *chip)
> > > {
> > > - kfree(chip->comm);
> > > + struct comm_runtime *rt = chip->comm;
> > > +
> > > + kfree(rt->receiver_buffer);
> > > + kfree(rt);
> > > chip->comm = NULL;
> > > }
> > > diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h
> > > index 6a0840b..780d5ed 100644
> > > --- a/sound/usb/6fire/comm.h
> > > +++ b/sound/usb/6fire/comm.h
> > > @@ -24,7 +24,7 @@ struct comm_runtime {
> > > struct sfire_chip *chip;
> > >
> > > struct urb receiver;
> > > - u8 receiver_buffer[COMM_RECEIVER_BUFSIZE];
> > > + u8 *receiver_buffer;
> > >
> > > u8 serial; /* urb serial */
> > >
> > >
> > > _______________________________________________
> > > Alsa-devel mailing list
> > > Alsa-devel at alsa-project.org
> > > http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> > >
> >
>
More information about the Alsa-devel
mailing list