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; }