static int rmidev_init_device(struct rmidev_data *data) { dev_t dev_no; int retval; struct device *device_ptr; if (rmidev_major_num) { dev_no = MKDEV(rmidev_major_num, 0); retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME); } else { retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME); /* let kernel allocate a major for us */ rmidev_major_num = MAJOR(dev_no); dev_info(&data->pdev->dev, "Major number of rmidev: %d\n", rmidev_major_num); } if (retval < 0) { dev_err(&data->pdev->dev, "Failed to register or allocate char dev, code %d.\n", retval); goto exit; } else { dev_info(&data->pdev->dev, "Allocated rmidev %d %d.\n", MAJOR(dev_no), MINOR(dev_no)); } mutex_init(&data->file_mutex); cdev_init(&data->main_dev, &rmidev_fops); retval = cdev_add(&data->main_dev, dev_no, 1); if (retval) { dev_err(&data->pdev->dev, "Error %d adding rmi_char_dev.\n", retval); rmidev_device_cleanup(data); goto exit; } dev_set_name(&data->pdev->dev, "rmidev%d", MINOR(dev_no)); data->device_class = rmidev_device_class; device_ptr = device_create( data->device_class, NULL, dev_no, NULL, CHAR_DEVICE_NAME"%d", MINOR(dev_no)); if (IS_ERR(device_ptr)) { dev_err(&data->pdev->dev, "Failed to create rmi device.\n"); rmidev_device_cleanup(data); retval = -ENODEV; } exit: return retval; }
static void rmidev_remove_device(struct synaptics_rmi4_data *rmi4_data) { struct rmidev_handle *rmidev = rmi4_data->rmidev; struct rmidev_data *dev_data = NULL; if (!rmidev) goto exit; sysfs_remove_group(rmidev->attr_dir, &attr_group); sysfs_remove_bin_file(rmidev->attr_dir, &attr_data); kobject_put(rmidev->attr_dir); dev_data = &rmidev->dev_data; if (dev_data) { rmidev_device_cleanup(dev_data); mutex_destroy(&dev_data->file_mutex); } unregister_chrdev_region(rmidev->dev_no, 1); class_destroy(rmidev_device_class); kfree(rmidev); rmi4_data->rmidev = NULL; exit: return; }
static void rmidev_remove_device(struct rmi_char_device *cd) { struct rmidev_data *data; dev_dbg(&cd->dev, "%s: removing an rmidev device.\n", __func__); if (!cd) return; data = cd->data; if (data) rmidev_device_cleanup(data); }
static int rmidev_init_device(struct rmi_char_device *cd) { struct rmi_device *rmi_dev = cd->rmi_dev; struct rmidev_data *data; dev_t dev_no; int retval; struct device *device_ptr; if (rmidev_major_num) { dev_no = MKDEV(rmidev_major_num, cd->rmi_dev->number); retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME); } else { retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME); /* let kernel allocate a major for us */ rmidev_major_num = MAJOR(dev_no); dev_info(&rmi_dev->dev, "Major number of rmidev: %d\n", rmidev_major_num); } if (retval < 0) { dev_err(&rmi_dev->dev, "Failed to get minor dev number %d, code %d.\n", cd->rmi_dev->number, retval); return retval; } else dev_info(&rmi_dev->dev, "Allocated rmidev %d %d.\n", MAJOR(dev_no), MINOR(dev_no)); data = kzalloc(sizeof(struct rmidev_data), GFP_KERNEL); if (!data) { dev_err(&rmi_dev->dev, "Failed to allocate rmidev_data.\n"); /* unregister the char device region */ __unregister_chrdev(rmidev_major_num, MINOR(dev_no), 1, CHAR_DEVICE_NAME); return -ENOMEM; } mutex_init(&data->file_mutex); data->rmi_dev = cd->rmi_dev; cd->data = data; cdev_init(&data->main_dev, &rmidev_fops); retval = cdev_add(&data->main_dev, dev_no, 1); if (retval) { dev_err(&cd->rmi_dev->dev, "Error %d adding rmi_char_dev.\n", retval); rmidev_device_cleanup(data); return retval; } dev_set_name(&cd->dev, "rmidev%d", MINOR(dev_no)); data->device_class = rmidev_device_class; device_ptr = device_create( data->device_class, NULL, dev_no, NULL, CHAR_DEVICE_NAME"%d", MINOR(dev_no)); if (IS_ERR(device_ptr)) { dev_err(&cd->rmi_dev->dev, "Failed to create rmi device.\n"); rmidev_device_cleanup(data); return -ENODEV; } return 0; }
static int rmidev_init_device(struct synaptics_rmi4_data *rmi4_data) { int retval; dev_t dev_no; struct device *device_ptr; struct rmidev_handle *rmidev = NULL; rmidev = kzalloc(sizeof(struct rmidev_handle), GFP_KERNEL); if (!rmidev) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to alloc mem for rmidev\n", __func__); retval = -ENOMEM; goto err_rmidev; } rmi4_data->rmidev = rmidev; rmidev->rmi4_data = rmi4_data; retval = rmidev_create_device_class(rmi4_data); if (retval < 0) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to create device class\n", __func__); goto err_device_class; } if (rmidev_major_num) { dev_no = MKDEV(rmidev_major_num, DEV_NUMBER); retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME); } else { retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME); if (retval < 0) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to allocate char device region\n", __func__); goto err_device_region; } rmidev_major_num = MAJOR(dev_no); dev_dbg(&rmi4_data->i2c_client->dev, "%s: Major number of rmidev = %d\n", __func__, rmidev_major_num); } mutex_init(&rmidev->dev_data.file_mutex); cdev_init(&rmidev->dev_data.main_dev, &rmidev_fops); retval = cdev_add(&rmidev->dev_data.main_dev, dev_no, 1); if (retval < 0) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to add rmi char device\n", __func__); goto err_char_device; } dev_set_name(&rmidev->dev, "rmidev%d", MINOR(dev_no)); rmidev->dev_data.device_class = rmidev_device_class; device_ptr = device_create(rmidev->dev_data.device_class, NULL, dev_no, NULL, CHAR_DEVICE_NAME"%d", MINOR(dev_no)); if (IS_ERR(device_ptr)) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to create rmi char device\n", __func__); retval = -ENODEV; goto err_char_device; } retval = gpio_export(rmi4_data->board->gpio, false); if (retval < 0) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to export attention gpio\n", __func__); } else { retval = gpio_export_link(&(rmi4_data->input_dev->dev), "attn", rmi4_data->board->gpio); if (retval < 0) { dev_err(&rmi4_data->input_dev->dev, "%s Failed to create gpio symlink\n", __func__); } else { dev_dbg(&rmi4_data->input_dev->dev, "%s: Exported attention gpio %d\n", __func__, rmi4_data->board->gpio); } } rmidev->attr_dir = kobject_create_and_add(ATTRIBUTE_FOLDER_NAME, &rmi4_data->input_dev->dev.kobj); if (!rmidev->attr_dir) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to create sysfs directory\n", __func__); retval = -ENODEV; goto err_attr_dir; } retval = sysfs_create_bin_file(rmidev->attr_dir, &attr_data); if (retval < 0) { dev_err(&rmi4_data->i2c_client->dev, "%s: Failed to create sysfs bin file\n", __func__); goto err_sysfs_bin; } retval = sysfs_create_group(rmidev->attr_dir, &attr_group); if (retval < 0) { dev_err(&rmi4_data->input_dev->dev, "%s: Failed to create sysfs attributes\n", __func__); retval = -ENODEV; goto err_sysfs_attrs; } return 0; err_sysfs_attrs: sysfs_remove_group(rmidev->attr_dir, &attr_group); sysfs_remove_bin_file(rmidev->attr_dir, &attr_data); err_sysfs_bin: kobject_put(rmidev->attr_dir); err_attr_dir: err_char_device: rmidev_device_cleanup(&rmidev->dev_data); mutex_destroy(&rmidev->dev_data.file_mutex); unregister_chrdev_region(dev_no, 1); err_device_region: class_destroy(rmidev_device_class); err_device_class: kfree(rmidev); rmi4_data->rmidev = NULL; err_rmidev: return retval; }