3

I'm investigating some memory corruption issues in an ethernet driver for an embedded system.

I suspect a problem between a bus mastering DMA controller and slow SDRAM. So I want to use a bounce buffer in fast SRAM. To do this I need two things: I must place the SRAM's physical address (from the bus master's perspective) into the DMA controller buffer descriptor, and I must memcpy the data from the bounce buffer into the sk_buff in SDRAM once the DMA controller reports an incoming packet.

What I haven't been able to determine, from reading

is whether skb->data is a physical or virtual address. i.e. should I call

memcpy(skb->data, phys_to_virt(bounce_addr), len);

or

memcpy(phys_to_virt(skb->data), phys_to_virt(bounce_addr), len);

to get the packet into an sk_buff so the rest of the linux networking stack can process it?

EDIT: This is the driver in question. I'd say that it's passing virtual addresses into the DMA controller registers and therefore can't work, but I have a devkit on which this code works. However my SDRAM doesn't have as good timings as the devkit DDR SDRAM, hence I'm thinking of implementing bounce buffers.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Hmm, it *must* be virtual since it points into the same buffer, right? – Nikolai Fetissov Feb 03 '11 at 21:04
  • @Nikolai: same buffer as what? – Ben Voigt Feb 03 '11 at 21:11
  • @Ben, same as the `*head`, `*tail`, and `*end`. Take a look at e100 code, for example, where it always does `pci_map_single` on `skb->data` when talking to hardware: http://lxr.linux.no/#linux+v2.6.37/drivers/net/e100.c#L1883 – Nikolai Fetissov Feb 03 '11 at 21:41
  • @Nikolai: That would help if I knew what the arguments to `pci_map_single` were supposed to be. I guess it's like `virt_to_bus` for PCI devices? I'm getting concerned because the existing driver code appears to put `skb->data` directly into the DMA buffer descriptor, and if `skb->data` is a virtual address, there's no way the DMA controller could use it directly. – Ben Voigt Feb 03 '11 at 21:49
  • It's basically `dma_map_single`. take a look into http://lxr.linux.no/#linux+v2.6.37/Documentation/DMA-API.txt . Hope this helps. BTW, what's the arch? – Nikolai Fetissov Feb 03 '11 at 21:58
  • @Nikolai: Yeah, that makes it clear it takes a virtual address. arch is `nios2mmu`. – Ben Voigt Feb 03 '11 at 22:07

1 Answers1

4

It's virtual. Basically anything of type foo * in the kernel is going to be a virtual address, and in fact, you'll very, very, rarely deal with physical addresses outside of low-level memory management -- you'll either have virtual addresses, or struct page that you need to kmap to get a virtual address.

nelhage
  • 2,734
  • 19
  • 14
  • I assume you meant "rarely deal with *physical* addresses outside of low-level memory management". But that clearly isn't true, drivers for devices with DMA capability have to tell the device the physical address of the DMA buffer, and that's the topic of my question. I should think that physical addresses should be kept in some pointer-sized integral type rather than pointers, because they can't be dereferenced, but looking at the existing source code that isn't the case. Maybe this particular driver just isn't written well. – Ben Voigt Feb 04 '11 at 03:42
  • Thanks, fixed the typo. And I guess my experience is mostly with core kernel code, instead of device drivers, so I can't actually speak for what random drivers do. I expect well-written ones make the distinction, but there are a lot of crappy ones out there. – nelhage Feb 04 '11 at 03:43