Re: ehci_hcd map_single: unable to map unsafe buffer on a standard NSLU2
- To: debian-arm@lists.debian.org
- Cc: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
- Subject: Re: ehci_hcd map_single: unable to map unsafe buffer on a standard NSLU2
- From: Thierry Merle <thierry.merle@free.fr>
- Date: Sat, 20 Oct 2007 14:19:02 +0200
- Message-id: <[🔎] 4719F236.3070106@free.fr>
- In-reply-to: <46FF404C.5050209@free.fr>
- References: <46E56C30.8070600@free.fr> <20070910165527.GA8784@kos.to> <46E57955.4040105@free.fr> <20070910174242.GR5384@csclub.uwaterloo.ca> <46E59187.7090307@free.fr> <20070910190449.GU5384@csclub.uwaterloo.ca> <46E5A3AB.9080202@free.fr> <20070910204719.GV5384@csclub.uwaterloo.ca> <12613111.post@talk.nabble.com> <20070911130655.GY5384@csclub.uwaterloo.ca> <46FF404C.5050209@free.fr>
Thierry Merle a écrit :
> Lennart Sorensen a écrit :
>> On Tue, Sep 11, 2007 at 04:53:41AM -0700, Thierry Merle wrote:
>>
>>> I am using a Terratec Cinergy T2 USB tuner on my 266MHz NSLU2.
>>> When I am recording a DVB-T stream, it takes around 33% CPU (zapdvb
>>> process,
>>> the tool I use to record) but surprisingly, my NSLU2 is much less
>>> responsive
>>> for other tasks (big latencies for ssh, fetchmail, imap and other
>>> things
>>> that run on my box).
>>> Nevertheless, the recorded file contains the entire stream (video is
>>> fluid).
>>> Do you think this is a CPU related problem?
>>>
>>
>> Isn't DVB-T mpeg? That would be a lot less work than a raw captured tv
>> signal (the driver in question mentioned needing 170MBit per second on
>> the USB port per tuner, which sounds like an awful lot more data than an
>> mpeg stream would generate). That would need much more bandwidth from
>> the cpu, and if the cpu now has to compress the video it would take
>> quite a lot of cpu. Even the disk access to write 170MBit/s starts to
>> add up, especially since the disk is almost certainly on another USB
>> port. I am assuming your tuner has hardware encoding to mpeg or that it
>> is receiving an existing mpeg stream from some other DVB device.
>>
>> So yes I could see it being simply a CPU issue.
>>
>> --
>> Len Sorensen
>>
>>
>>
> Right, DVB-T mpeg-2 TS for both cinergyT2 and em28xx based tuners.
> To inform you the current state of the investigation:
> - I wired a serial-to-usb cable to get the serial console (I used a
> DKU-5 data cable containing a ark3116 chip, works perfectly for this
> usage, and very cheap).
> - by lowering the number of URB allocated in em28xx, I succeeded in
> going further... to another bug :)
> I have now the following error on console, so frequently that the NSLU2
> cannot respond to any sollicitation (need to hard-shutdown it) :
> BUG: warning at arch/arm/mm/consistent.c:363/dma_free_coherent()
> BUG: warning at arch/arm/mm/consistent.c:363/dma_free_coherent()
> BUG: warning at arch/arm/mm/consistent.c:363/dma_free_coherent()
> [...]
> This warning is caused by: WARN_ON(irqs_disabled()); in
> dma_free_coherent.
> The function comment says: * Must not be called with IRQs disabled.
> I suggested that a dma_free_coherent has been indirectly called in a
> critical section...
> So we need to analyze that with the em28xx maintainer that does his best
> to help me with the poor information I can give to him.
>
> Thierry
>
>
>
Hello,
I proposed a patch on the linux-arm ML (you will find at the end of this
message) to correct the dma_free_coherent calls when IRQ are disabled.
This allows the tuner to tune frequencies without kernel freezes, but
the streaming is corrupted, I need to investigate on this now.
This patches the kernel, the dmabounce part; this corrects a very rare
bug I think, so nobody commented it yet.
Do someone encountered a kernel freeze on the NSLU2 using a USB device?
Cheers,
Thierry
--- linux-source-2.6.22.orig/arch/arm/common/dmabounce.c 2007-10-12 21:51:54.000000000 +0200
+++ linux-source-2.6.22/arch/arm/common/dmabounce.c 2007-10-10 19:16:36.000000000 +0200
@@ -29,7 +29,7 @@
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/list.h>
-
+#include <linux/interrupt.h>
#include <asm/cacheflush.h>
#undef STATS
@@ -51,6 +51,7 @@ struct safe_buffer {
int direction;
/* safe buffer info */
+ struct device *dev;
struct dmabounce_pool *pool;
void *safe;
dma_addr_t safe_dma_addr;
@@ -125,6 +126,7 @@ alloc_safe_buffer(struct dmabounce_devic
return NULL;
}
+ buf->dev = device_info->dev;
buf->ptr = ptr;
buf->size = size;
buf->direction = dir;
@@ -180,6 +182,39 @@ find_safe_buffer(struct dmabounce_device
return rb;
}
+/* The free safe buffer part. dma_free_coherent cannot be called irq disabled.
+ To cope with that, a tasklet (do_free) does the job upon request */
+static DEFINE_SPINLOCK(buflock);
+static LIST_HEAD(buffers);
+
+static void do_free(unsigned long ignored)
+{
+ spin_lock_irq(&buflock);
+ while (!list_empty(&buffers)) {
+ struct safe_buffer *buf;
+
+ buf = list_entry(buffers.next,
+ struct safe_buffer,
+ node);
+ list_del(&buf->node);
+ spin_unlock_irq(&buflock);
+
+ if (buf->pool)
+ dma_pool_free(buf->pool->pool, buf->safe, buf->safe_dma_addr);
+ else
+ dma_free_coherent(buf->dev, buf->size, buf->safe,
+ buf->safe_dma_addr);
+
+ kfree(buf);
+
+ spin_lock_irq(&buflock);
+
+ }
+ spin_unlock_irq(&buflock);
+}
+
+static DECLARE_TASKLET(deferred_free, do_free, 0);
+
static inline void
free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *buf)
{
@@ -193,13 +228,12 @@ free_safe_buffer(struct dmabounce_device
write_unlock_irqrestore(&device_info->lock, flags);
- if (buf->pool)
- dma_pool_free(buf->pool->pool, buf->safe, buf->safe_dma_addr);
- else
- dma_free_coherent(device_info->dev, buf->size, buf->safe,
- buf->safe_dma_addr);
+ /* pass the safe buffer to the tasklet */
+ spin_lock_irqsave(&buflock, flags);
+ list_add_tail(&buf->node, &buffers);
+ tasklet_schedule(&deferred_free);
+ spin_unlock_irqrestore(&buflock, flags);
- kfree(buf);
}
/* ************************************************** */
Reply to: