How to request_mem_region() in Linux Drivers: Reserving I/O Memory the Right Way-Free Linux Device Drivers Course

request_mem_region() in Linux Drivers: Reserving I/O Memory the Right Way

Free Linux Kernel Programming Course • Hardware I/O Memory • Lecture 2

← Previous Lecture    Next Lecture →

What You Will Learn

  • Why a driver must reserve its I/O memory region before touching it
  • How request_mem_region() and release_mem_region() work in Linux drivers
  • The managed, modern alternative: devm_request_mem_region()
  • How to read the reserved regions of a running system from /proc/iomem
  • Common ownership conflicts and how the kernel protects against them

Prerequisites

  • Completion of Lecture 1 on MMIO vs PMIO (or equivalent background)
  • Basic understanding of Linux kernel modules and platform drivers

Why Reserve I/O Memory Before Using It

Before a Linux driver maps or touches any hardware register range, it is expected to formally reserve that range with the kernel’s resource tree. This step, request_mem_region() in Linux driver code, exists for one simple reason: multiple drivers must never be allowed to silently claim the same physical register range at the same time. Without this bookkeeping step, two competing drivers — or a buggy driver loaded twice — could both try to program the same hardware block, leading to unpredictable and hard-to-debug failures.

How the Kernel Resource Tree Works

Internally, the kernel keeps a tree of struct resource objects representing every physical address range in the system — RAM, ROM, and every peripheral’s register block. When a driver calls request_mem_region(), it is asking the kernel to insert a new leaf into this tree under the “iomem” root. If the requested range overlaps an already-reserved leaf, the request fails, and the driver knows immediately that something else already owns that hardware.

Conceptual View: The I/O Memory Resource Tree
iomem (root resource)
System RAM
UART registers
GPIO registers

You can inspect this exact tree yourself on any running Linux system:

cat /proc/iomem

Every line in that output is one reserved struct resource, together with the driver name that owns it — this is the same “name” string a driver passes to request_mem_region().

The Classic API

The traditional pair of functions has been part of the kernel for decades and still appears throughout the source tree:

struct resource *request_mem_region(resource_size_t start,
                                     resource_size_t n,
                                     const char *name);

void release_mem_region(resource_size_t start, resource_size_t n);

start is the physical address where the region begins, n is its length in bytes, and name is a human-readable label (usually the driver name) that shows up in /proc/iomem. A successful call returns a non-NULL struct resource *; a NULL return means the region is already owned by someone else, and the driver should back off cleanly, typically returning -EBUSY from its probe function.

The Modern, Managed Approach: devm_request_mem_region()

Writing correct cleanup paths by hand is a common source of bugs — it’s easy to forget to call release_mem_region() on every error path. Since the introduction of the “devm_” (device-managed) family of APIs, this has become the recommended approach in current kernels. A devm_-prefixed resource is automatically released by the kernel when the device is detached or the probe fails, with no manual cleanup required.

static int mychip_probe(struct platform_device *pdev)
{
    struct resource *res;
    struct device *dev = &pdev->dev;

    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!res)
        return -ENODEV;

    if (!devm_request_mem_region(dev, res->start,
                                  resource_size(res), pdev->name)) {
        dev_err(dev, "failed to reserve MMIO region\n");
        return -EBUSY;
    }

    /* No manual release_mem_region() needed on cleanup —
       devm_ handles it automatically. */
    return 0;
}

Classic vs Managed API: Comparison

Aspect request_mem_region() devm_request_mem_region()
Cleanup Manual — must call release_mem_region() Automatic, tied to device lifetime
Risk of leaks on error paths Higher Much lower
Recommended for new drivers No, legacy pattern Yes, current best practice

Real-World Use Cases

  • A platform driver reserving its register block before calling ioremap()
  • Preventing two instances of the same driver from double-claiming shared hardware
  • Diagnosing hardware conflicts by inspecting /proc/iomem during bring-up on new boards

Common Mistakes and Troubleshooting

  • Skipping the reservation entirely — mapping a resource without requesting it first can mask real conflicts between drivers.
  • Forgetting release_mem_region() on an error path when using the classic (non-devm) API, causing the region to stay “leaked” until reboot.
  • Requesting the wrong length — always use resource_size(res) rather than a manually typed constant.
  • -EBUSY at probe time — check /proc/iomem to find out which other driver already owns the range.

Best Practices

  • Prefer devm_request_mem_region() in all new driver code targeting current kernels
  • Always check the return value and fail the probe cleanly with a descriptive dev_err()
  • Use a meaningful, unique name string so /proc/iomem is useful for debugging
  • Never assume a region is free — always request it, even during early bring-up experiments

Performance and Security Considerations

Reserving a resource has negligible runtime cost — it is a one-time bookkeeping operation at probe time, not a per-access cost. From a security and stability standpoint, this reservation step is what prevents a poorly written or malicious module from silently taking over hardware that another driver already depends on, which could otherwise be used to destabilize the system.

Summary / Key Takeaways

  • request_mem_region() in a Linux driver reserves a hardware register range in the kernel’s resource tree
  • A NULL return means the region is already owned by another driver
  • devm_request_mem_region() is the current best practice, with automatic cleanup
  • /proc/iomem lets you inspect every reserved I/O memory region on a running system

Conclusion

Reserving I/O memory correctly is a small but essential step that protects your driver — and every other driver on the system — from silent hardware conflicts. With the region safely reserved, the next lecture in this free Linux device drivers course shows you how to actually map it into kernel virtual address space using ioremap(), so your driver can start reading and writing real hardware registers.

Frequently Asked Questions

Q1. What does request_mem_region() actually do?

It inserts a new entry into the kernel’s I/O memory resource tree, formally marking a physical address range as owned by your driver, and fails if the range is already claimed.

Q2. Do I still need to call ioremap() after request_mem_region()?

Yes. Requesting the region only reserves ownership; it does not make the registers accessible. You still need to map the physical range into kernel virtual address space, covered in the next lecture.

Q3. What is the difference between request_mem_region() and devm_request_mem_region()?

The devm_ variant ties the reservation to the device’s lifetime, so the kernel releases it automatically, removing the need for manual cleanup on every error and removal path.

Q4. What does it mean if request_mem_region() returns NULL?

It means the requested address range is already reserved by another driver; your probe function should fail cleanly, typically returning -EBUSY.

Q5. How can I see which driver owns a given I/O memory range?

Run cat /proc/iomem on the target system; each reserved range is listed together with the name string passed to request_mem_region() or devm_request_mem_region().

Q6. Is request_mem_region() used for PCI devices too?

PCI drivers typically use the related pci_request_region() family instead, which understands PCI BARs, but the underlying resource-tree concept is the same.

Continue Your Free Linux Kernel Programming Course

This lecture is part of EmbeddedPathashala’s free Linux device drivers and kernel programming course.

Explore More Free Lectures

← Previous Lecture    Next Lecture →

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *