Jamie
Jamie

Reputation: 7431

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?

Upvotes: 0

Views: 457

Answers (2)

zhangfeng
zhangfeng

Reputation: 36

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 Probing\n");
    /* Get iospace for the device */
    r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!r_mem) {
        dev_err(dev, "invalid address\n");
        return -ENODEV;
    }

    lp = (struct blink_local *) kmalloc(sizeof(struct blink_local), GFP_KERNEL);
    if (!lp) {
        dev_err(dev, "Cound not allocate blink device\n");
        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 %p\n",
            (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 iomem\n");
        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 found\n");
        dev_info(dev, "blink at 0x%08x mapped to 0x%08x\n",
            (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;
}

Upvotes: 2

chrk
chrk

Reputation: 4215

For memory allocated dynamically by the driver, the private_data field of struct file is the one to use.

The way this field is used is up to the driver, the kernel doesn't touch it. It's there just for the drivers to use.

You can also have a look at this previous question.

Upvotes: 0

Related Questions