struct dax_region *dax_region = dev_dax->region;
struct dax_device *dax_dev = dev_dax->dax_dev;
- ida_simple_remove(&dax_region->ida, dev_dax->id);
+ if (dev_dax->id >= 0)
+ ida_simple_remove(&dax_region->ida, dev_dax->id);
dax_region_put(dax_region);
put_dax(dax_dev);
kfree(dev_dax);
}
struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
- struct resource *res, int count)
+ int id, struct resource *res, int count)
{
struct device *parent = dax_region->dev;
struct dax_device *dax_dev;
struct inode *inode;
struct device *dev;
struct cdev *cdev;
- int rc = 0, i;
+ int rc, i;
+
+ if (!count)
+ return ERR_PTR(-EINVAL);
dev_dax = kzalloc(sizeof(*dev_dax) + sizeof(*res) * count, GFP_KERNEL);
if (!dev_dax)
if (i < count)
goto err_id;
- dev_dax->id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL);
- if (dev_dax->id < 0) {
- rc = dev_dax->id;
- goto err_id;
+ if (id < 0) {
+ id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL);
+ dev_dax->id = id;
+ if (id < 0) {
+ rc = id;
+ goto err_id;
+ }
+ } else {
+ /* region provider owns @id lifetime */
+ dev_dax->id = -1;
}
/*
* device outside of mmap of the resulting character device.
*/
dax_dev = alloc_dax(dev_dax, NULL, NULL);
- if (!dax_dev)
+ if (!dax_dev) {
+ rc = -ENOMEM;
goto err_dax;
+ }
/* from here on we're committed to teardown via dax_dev_release() */
dev = &dev_dax->dev;
dev->parent = parent;
dev->groups = dax_attribute_groups;
dev->release = dev_dax_release;
- dev_set_name(dev, "dax%d.%d", dax_region->id, dev_dax->id);
+ dev_set_name(dev, "dax%d.%d", dax_region->id, id);
rc = cdev_device_add(cdev, dev);
if (rc) {
return dev_dax;
err_dax:
- ida_simple_remove(&dax_region->ida, dev_dax->id);
+ if (dev_dax->id >= 0)
+ ida_simple_remove(&dax_region->ida, dev_dax->id);
err_id:
kfree(dev_dax);