3

I'm currently working on porting a kernel module for a VME bridge from 2.6 to 3.16.

The device is capable of mapping a VME address space to PCI, where the address range that is mapped into can be set by the driver. So the kernel module first tries to find an available region in address space by doing a loop like this

for (pciAddr=MEM_START; pciAddr<MEM_STOP; pciAddr+=STEP) {
  if (check_mem_region(pci_Addr, size)==0)
    break;
}
request_mem_region(pciAddr, size, modulename);

which should be changed to

for (pciAddr=MEM_START; pciAddr<MEM_STOP; pciAddr+=STEP) {
  if (request_mem_region(pciAddr, size, modulename)!=0)
    break;
}

for newer Kernels. This works fine for the 2.6 Kernel, but for the newer 3.16 both variants return the first region (starting at MEM_START) as available, but subsequent reads in this address range fail, returning always 0xff.

MEM_START is defined as 0x40000000, and /proc/iomem shows

40000000-401fffff : PCI Bus 0000:01

in one of the lines. When changing MEM_START to another address which is free according to /proc/iomem, everything works.

So it seems that request_mem_region() returns success for a region which is not available, and does this only for newer Kernels. What could be the reason for this behavior?

Karsten Koop
  • 2,475
  • 1
  • 18
  • 23
  • Are you calling ioremap() after requesting the region and prior to accessing it? – user5071535 Aug 14 '15 at 16:16
  • I think it's not forbidden to request and even map the region as many times you want to. The actual PCI device has BARs which should provide the window which is operates with the device. This is my understanding. Moreover, there is a patchset targeting v4.3 to introduce memmap() wrapper instead of ioremap() if you need to access to the region as to regular memory (implies cache usage). – 0andriy Aug 14 '15 at 18:37
  • I wonder if you have another module that's not playing nice and mapping the memory. This link has a good discussion of request_mem_region() and ioremap(): http://www.makelinux.net/ldd3/chp-9-sect-4 – user5071535 Aug 14 '15 at 19:17
  • I did some further tests with other Kernels (3.2 from Debian 7, 2.6.18 and 2.6.24 from Debian 4 and 3.16 and 4.1 from Debian 8) on the same hardware. For all kernels, requesting an address region that is listed in /proc/iomem does not fail in most cases. The kernel module works for kernels 2.6 because for those kernels there is no device mapped at 0x4000000, for later kernels the PCI Bus 0000:01 is mapped there. I was under the impression that /proc/iomem lists all reserved addresses, which I read at makelinux.net and which seems to be not true. So this whole approach might have been wrong. – Karsten Koop Aug 17 '15 at 15:21
  • The question would then be: What is the correct approach in this case? The device can map a certain range of VME addresses to PCI address space, and the PCI base address can be chosen. The range of VME addresses (base address and size) is requested from user space and not known beforehand. One only needs to find a free physical address range. – Karsten Koop Aug 17 '15 at 15:25
  • @KarstenKoop How are you choosing the PCI base address? Generally the system populates the PCI device's BAR(s), are you trying to assign them manually via software? – user5071535 Aug 17 '15 at 22:11
  • @user5071535 Yes, the module is trying to do this manually, but not for the base address of the device itself, but the base address of the bridged VME address space. As the base address, size and number of mapped VME regions is given from user space, this cannot be done during boot, I guess. – Karsten Koop Aug 19 '15 at 08:02

0 Answers0