int pps_register_source(struct pps_source_info *info, int default_params) { struct pps_device *pps; int id; int err; /* Sanity checks */ if ((info->mode & default_params) != default_params) { printk(KERN_ERR "pps: %s: unsupported default parameters\n", info->name); err = -EINVAL; goto pps_register_source_exit; } if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 && info->echo == NULL) { printk(KERN_ERR "pps: %s: echo function is not defined\n", info->name); err = -EINVAL; goto pps_register_source_exit; } if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) { printk(KERN_ERR "pps: %s: unspecified time format\n", info->name); err = -EINVAL; goto pps_register_source_exit; } /* Allocate memory for the new PPS source struct */ pps = kzalloc(sizeof(struct pps_device), GFP_KERNEL); if (pps == NULL) { err = -ENOMEM; goto pps_register_source_exit; } /* These initializations must be done before calling idr_get_new() * in order to avoid reces into pps_event(). */ pps->params.api_version = PPS_API_VERS; pps->params.mode = default_params; pps->info = *info; init_waitqueue_head(&pps->queue); spin_lock_init(&pps->lock); atomic_set(&pps->usage, 1); /* Get new ID for the new PPS source */ if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) { err = -ENOMEM; goto kfree_pps; } spin_lock_irq(&pps_idr_lock); /* Now really allocate the PPS source. * After idr_get_new() calling the new source will be freely available * into the kernel. */ err = idr_get_new(&pps_idr, pps, &id); if (err < 0) { spin_unlock_irq(&pps_idr_lock); goto kfree_pps; } id = id & MAX_ID_MASK; if (id >= PPS_MAX_SOURCES) { spin_unlock_irq(&pps_idr_lock); printk(KERN_ERR "pps: %s: too many PPS sources in the system\n", info->name); err = -EBUSY; goto free_idr; } pps->id = id; spin_unlock_irq(&pps_idr_lock); /* Create the char device */ err = pps_register_cdev(pps); if (err < 0) { printk(KERN_ERR "pps: %s: unable to create char device\n", info->name); goto free_idr; } pr_info("new PPS source %s at ID %d\n", info->name, id); return id; free_idr: spin_lock_irq(&pps_idr_lock); idr_remove(&pps_idr, id); spin_unlock_irq(&pps_idr_lock); kfree_pps: kfree(pps); pps_register_source_exit: printk(KERN_ERR "pps: %s: unable to register source\n", info->name); return err; }
struct pps_device *pps_register_source(struct pps_source_info *info, int default_params) { struct pps_device *pps; int err; /* Sanity checks */ if ((info->mode & default_params) != default_params) { pr_err("%s: unsupported default parameters\n", info->name); err = -EINVAL; goto pps_register_source_exit; } if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 && info->echo == NULL) { pr_err("%s: echo function is not defined\n", info->name); err = -EINVAL; goto pps_register_source_exit; } if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) { pr_err("%s: unspecified time format\n", info->name); err = -EINVAL; goto pps_register_source_exit; } /* Allocate memory for the new PPS source struct */ pps = kzalloc(sizeof(struct pps_device), GFP_KERNEL); if (pps == NULL) { err = -ENOMEM; goto pps_register_source_exit; } /* These initializations must be done before calling idr_get_new() * in order to avoid reces into pps_event(). */ pps->params.api_version = PPS_API_VERS; pps->params.mode = default_params; pps->info = *info; init_waitqueue_head(&pps->queue); spin_lock_init(&pps->lock); /* Create the char device */ err = pps_register_cdev(pps); if (err < 0) { pr_err("%s: unable to create char device\n", info->name); goto kfree_pps; } dev_info(pps->dev, "new PPS source %s\n", info->name); return pps; kfree_pps: kfree(pps); pps_register_source_exit: pr_err("%s: unable to register source\n", info->name); return NULL; }