Skip to content
Advertisement

Where do I store dynamically allocated memory on a platform device (without using globals)?

I want to make the platform driver I’m writing reentrant: where do I store memory dynamically assigned during the probe and/or open calls (int probe(struct platform_device*)/int open(struct inode *inode, struct file *))

The driver can be instantiated on multiple pieces of in-system hardware, with each of them being accessed concurrently from user space.

Can I use the private_data field from struct file and the platform_data from struct device as arbitrary pointers to allocated memory?

Advertisement

Answer

If you are writing a platform driver, you should use dev_set_drvdata() function, which sets the driver_data field in struct device, .

There is an example.

struct blink_local {
    int irq;
    unsigned long mem_start;
    unsigned long mem_end;
    void __iomem *base_addr;
};

static int blink_probe(struct platform_device *pdev)
{
    struct resource *r_irq; /* Interrupt resources */
    struct resource *r_mem; /* IO mem resources */
    struct device *dev = &pdev->dev;
    struct blink_local *lp = NULL;

    int rc = 0;
    dev_info(dev, "Device Tree Probingn");
    /* Get iospace for the device */
    r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!r_mem) {
        dev_err(dev, "invalid addressn");
        return -ENODEV;
    }

    lp = (struct blink_local *) kmalloc(sizeof(struct blink_local), GFP_KERNEL);
    if (!lp) {
        dev_err(dev, "Cound not allocate blink devicen");
        return -ENOMEM;
    }

    dev_set_drvdata(dev, lp);
    lp->mem_start = r_mem->start;
    lp->mem_end = r_mem->end;

    if (!request_mem_region(lp->mem_start,
                lp->mem_end - lp->mem_start + 1,
                DRIVER_NAME)) {
        dev_err(dev, "Couldn't lock memory region at %pn",
            (void *)lp->mem_start);
        rc = -EBUSY;
        goto error1;
    }

    lp->base_addr = ioremap(lp->mem_start, lp->mem_end - lp->mem_start + 1);
    if (!lp->base_addr) {
        dev_err(dev, "blink: Could not allocate iomemn");
        rc = -EIO;
        goto error2;
    }

    /* Get IRQ for the device */
    r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    if (!r_irq) {
        dev_info(dev, "no IRQ foundn");
        dev_info(dev, "blink at 0x%08x mapped to 0x%08xn",
            (unsigned int __force)lp->mem_start,
            (unsigned int __force)lp->base_addr);
        return 0;
    }
    lp->irq = r_irq->start;
    rc = request_irq(lp->irq, &blink_irq, 0, DRIVER_NAME, lp);
    if (rc) {
        dev_err(dev, "testmodule: Could not allocate interrupt %d.n",
            lp->irq);
        goto error3;
    }

    return 0;
error3:
    free_irq(lp->irq, lp);
error2:
    release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
error1:
    kfree(lp);
    dev_set_drvdata(dev, NULL);
    return rc;
}
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement