mmap not working in device driver

s.achterop at rug.nl s.achterop at rug.nl
Mon Apr 6 14:30:27 EDT 2020


   Hello list,

I created a simple misc-device platform device driver, including a test program, see
     https://github.com/SietseAchterop/Batradio/blob/master/batradio_module/testfiqtimer.c
     https://github.com/SietseAchterop/Batradio/blob/master/batradio_module/batradio_client.c

This on an raspberry zero with the latest kernel from  https://github.com/raspberrypi/linux,
compiled from source using arm-linux-gnueabihf-gcc (GCC) 8.3.0.

The driver only implements the mmap and ioctl functions.
An area in the driver (fiq_buf) is made available to the user program via mmap.
The problem is that changing data (status value) in the driver via ioctl, is NOT reflected in the user program.

Here a few snippets from the driver:

 From the init function:

   batradio_data = devm_kzalloc(&pdev->dev,
			       sizeof(*batradio_data),
			       GFP_KERNEL);
   if (!batradio_data)
     return -ENOMEM;

   batradio_data->fiq_base = devm_kzalloc(&pdev->dev,
					 FIQ_BUFFER_SIZE,   // 256*1024
					 GFP_KERNEL);
   if (!batradio_data->fiq_base) {
     dev_err(&pdev->dev, "Couldn't allocate memory!\n");
     return -ENOMEM;
   }

   fiq_buf = (struct fiq_buffer *)batradio_data->fiq_base;
   fiq_buf->status = 55;

And from the mmap function:

   size_t size = vma->vm_end - vma->vm_start;
   unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;

   if (offset + size > FIQ_BUFFER_SIZE)
     return -EINVAL;

   offset += virt_to_phys(batradio_data->fiq_base);

   vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);

   if (remap_pfn_range(vma,
		      vma->vm_start,
		      offset >> PAGE_SHIFT,
		      size,
		      vma->vm_page_prot)) {
     return -EAGAIN;
   }

And finally from the client program:

   fiq_fd = open(FIQ_PATH, O_RDWR);
   if (!fiq_fd) {
     ret = errno;
     perror("Couldn't open batradio device, error %d", errno);
     exit(-1);
   }

   fiq_addr = mmap(NULL, FIQ_BUFFER_SIZE, PROT_READ | PROT_WRITE,
		  MAP_SHARED, fiq_fd, 0);
   if (fiq_addr == MAP_FAILED) {
     ret = errno;
     perror("Couldn't map the fiq buffer");
     exit(-2);
   }
   fiq_buf = (struct fiq_buffer*)fiq_addr;

   printf("status %d\n", fiq_buf->status);


All very standard I think.
Why are changes in fiq_buf->status in the driver not shown in the client program?

   Thanks in advance,
       Sietse



More information about the Kernelnewbies mailing list