int pps_register_cdev()

in pps.c [347:404]


int pps_register_cdev(struct pps_device *pps)
{
	int err;
	dev_t devt;

	mutex_lock(&pps_idr_lock);
	/*
	 * Get new ID for the new PPS source.  After idr_alloc() calling
	 * the new source will be freely available into the kernel.
	 */
	err = idr_alloc(&pps_idr, pps, 0, PPS_MAX_SOURCES, GFP_KERNEL);
	if (err < 0) {
		if (err == -ENOSPC) {
			pr_err("%s: too many PPS sources in the system\n",
			       pps->info.name);
			err = -EBUSY;
		}
		goto out_unlock;
	}
	pps->id = err;
	mutex_unlock(&pps_idr_lock);

	devt = MKDEV(MAJOR(pps_devt), pps->id);

	cdev_init(&pps->cdev, &pps_cdev_fops);
	pps->cdev.owner = pps->info.owner;

	err = cdev_add(&pps->cdev, devt, 1);
	if (err) {
		pr_err("%s: failed to add char device %d:%d\n",
				pps->info.name, MAJOR(pps_devt), pps->id);
		goto free_idr;
	}
	pps->dev = device_create(pps_class, pps->info.dev, devt, pps,
							"pps%d", pps->id);
	if (IS_ERR(pps->dev)) {
		err = PTR_ERR(pps->dev);
		goto del_cdev;
	}

	/* Override the release function with our own */
	pps->dev->release = pps_device_destruct;

	pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
			MAJOR(pps_devt), pps->id);

	return 0;

del_cdev:
	cdev_del(&pps->cdev);

free_idr:
	mutex_lock(&pps_idr_lock);
	idr_remove(&pps_idr, pps->id);
out_unlock:
	mutex_unlock(&pps_idr_lock);
	return err;
}