On Mon, 24 Nov 2014, Sebastian Andrzej Siewior wrote:
> the following error pops up during "testusb -a -t 10"
> | musb-hdrc musb-hdrc.1.auto: dma_pool_free buffer-128,
> f134e000/be842000 (bad dma)
> hcd_buffer_create() creates a few buffers, the smallest has 32 bytes of
> size. ARCH_KMALLOC_MINALIGN is set to 64 bytes. This combo results in
> hcd_buffer_alloc() returning memory which is 32bytes aligned and it
> might by identified by buffer_offset() as another buffer. This means the
> buffer which is on a 32byte boundary will not get freed, instead it
> tries to free another buffer with the error message.
>
> This patch fixes the issue by creating the smallest DMA buffer with the
> size of ARCH_KMALLOC_MINALIGN. This will be either 32 or 64 bytes. If the
> ARCH_KMALLOC_MINALIGN is 128 (currently powerpc64, mips ip32, x86 pentium
> 4) then it will create the first buffer with 128 bytes and will have only 3
> buffers in total. There is a BUILD_BUG_ON() now in case someone has a
> ARCH_KMALLOC_MINALIGN greater than 256 bytes.
Okay, this is a little awkward but not too bad. And I prefer it over
the earlier proposal, even though the source code ends up a little
bigger.
> diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
> index 684ef70dc09d..a80d1ec8b1b0 100644
> --- a/drivers/usb/core/buffer.c
> +++ b/drivers/usb/core/buffer.c
> @@ -26,7 +26,11 @@ static const size_t pool_max[HCD_BUFFER_POOLS] = {
> /* platforms without dma-friendly caches might need to
> * prevent cacheline sharing...
> */
> +#if ARCH_KMALLOC_MINALIGN <= 32
> 32,
> +#elif ARCH_KMALLOC_MINALIGN <= 64
> + 64,
> +#endif
> 128,
> 512,
> PAGE_SIZE / 2
> @@ -58,6 +62,7 @@ int hcd_buffer_create(struct usb_hcd *hcd)
> !(hcd->driver->flags & HCD_LOCAL_MEM))
> return 0;
>
> + BUILD_BUG_ON(ARCH_KMALLOC_MINALIGN > 128);
> for (i = 0; i < HCD_BUFFER_POOLS; i++) {
> size = pool_max[i];
> if (!size)
> diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
> index cd96a2bc3388..1e2234ca448d 100644
> --- a/include/linux/usb/hcd.h
> +++ b/include/linux/usb/hcd.h
> @@ -23,6 +23,7 @@
>
> #include <linux/rwsem.h>
> #include <linux/interrupt.h>
> +#include <linux/slab.h>
>
> #define MAX_TOPO_LEVEL 6
>
> @@ -171,8 +172,11 @@ struct usb_hcd {
> struct usb_hcd *shared_hcd;
> struct usb_hcd *primary_hcd;
>
> -
> -#define HCD_BUFFER_POOLS 4
> +#if ARCH_KMALLOC_MINALIGN <= 64
> + #define HCD_BUFFER_POOLS 4
> +#else
> + #define HCD_BUFFER_POOLS 3
> +#endif
> struct dma_pool *pool[HCD_BUFFER_POOLS];
What about the ARCH_KMALLOC_MINALIGN <= 32 case?
Alan Stern
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html