int rmnet_usb_ctrl_init(int no_rmnet_devs, int no_rmnet_insts_per_dev) { struct rmnet_ctrl_dev *dev; int i, n; int status; num_devs = no_rmnet_devs; insts_per_dev = no_rmnet_insts_per_dev; ctrl_devs = kzalloc(num_devs * sizeof(*ctrl_devs), GFP_KERNEL); if (!ctrl_devs) return -ENOMEM; for (i = 0; i < num_devs; i++) { ctrl_devs[i] = kzalloc(insts_per_dev * sizeof(*ctrl_devs[i]), GFP_KERNEL); if (!ctrl_devs[i]) return -ENOMEM; status = alloc_chrdev_region(&ctrldev_num[i], 0, insts_per_dev, rmnet_dev_names[i]); if (IS_ERR_VALUE(status)) { pr_err("ERROR:%s: alloc_chrdev_region() ret %i.\n", __func__, status); return status; } ctrldev_classp[i] = class_create(THIS_MODULE, rmnet_dev_names[i]); if (IS_ERR(ctrldev_classp[i])) { pr_err("ERROR:%s: class_create() ENOMEM\n", __func__); status = PTR_ERR(ctrldev_classp[i]); return status; } for (n = 0; n < insts_per_dev; n++) { dev = &ctrl_devs[i][n]; /*for debug purpose*/ snprintf(dev->name, CTRL_DEV_MAX_LEN, "%s%d", rmnet_dev_names[i], n); dev->wq = create_singlethread_workqueue(dev->name); if (!dev->wq) { pr_err("unable to allocate workqueue"); kfree(dev); return -ENOMEM; } dev->ch_id = n; mutex_init(&dev->dev_lock); spin_lock_init(&dev->rx_lock); init_waitqueue_head(&dev->read_wait_queue); init_waitqueue_head(&dev->open_wait_queue); INIT_LIST_HEAD(&dev->rx_list); init_usb_anchor(&dev->tx_submitted); init_usb_anchor(&dev->rx_submitted); INIT_WORK(&dev->get_encap_work, get_encap_work); cdev_init(&dev->cdev, &ctrldev_fops); dev->cdev.owner = THIS_MODULE; status = cdev_add(&dev->cdev, (ctrldev_num[i] + n), 1); if (status) { pr_err("%s: cdev_add() ret %i\n", __func__, status); destroy_workqueue(dev->wq); kfree(dev); return status; } dev->devicep = device_create(ctrldev_classp[i], NULL, (ctrldev_num[i] + n), NULL, "%s%d", rmnet_dev_names[i], n); if (IS_ERR(dev->devicep)) { pr_err("%s: device_create() returned %ld\n", __func__, PTR_ERR(dev->devicep)); cdev_del(&dev->cdev); destroy_workqueue(dev->wq); kfree(dev); return PTR_ERR(dev->devicep); } /*create /sys/class/hsicctl/hsicctlx/modem_wait*/ status = device_create_file(dev->devicep, &dev_attr_modem_wait); if (status) { device_destroy(dev->devicep->class, dev->devicep->devt); cdev_del(&dev->cdev); destroy_workqueue(dev->wq); kfree(dev); return status; } dev_set_drvdata(dev->devicep, dev); status = rmnet_usb_ctrl_alloc_rx(dev); if (status) { device_remove_file(dev->devicep, &dev_attr_modem_wait); device_destroy(dev->devicep->class, dev->devicep->devt); cdev_del(&dev->cdev); destroy_workqueue(dev->wq); kfree(dev); return status; } } } rmnet_usb_ctrl_debugfs_init(); pr_info("rmnet usb ctrl Initialized.\n"); return 0; }
int rmnet_usb_ctrl_init(void) { struct rmnet_ctrl_dev *dev; int n; int status; for (n = 0; n < NUM_CTRL_CHANNELS; ++n) { dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { status = -ENOMEM; goto error0; } /*for debug purpose*/ snprintf(dev->name, CTRL_DEV_MAX_LEN, "hsicctl%d", n); dev->wq = create_singlethread_workqueue(dev->name); if (!dev->wq) { pr_err("unable to allocate workqueue"); kfree(dev); goto error0; } mutex_init(&dev->dev_lock); spin_lock_init(&dev->rx_lock); init_waitqueue_head(&dev->read_wait_queue); init_waitqueue_head(&dev->open_wait_queue); INIT_LIST_HEAD(&dev->rx_list); init_usb_anchor(&dev->tx_submitted); init_usb_anchor(&dev->rx_submitted); INIT_WORK(&dev->get_encap_work, get_encap_work); status = rmnet_usb_ctrl_alloc_rx(dev); if (status < 0) { kfree(dev); goto error0; } ctrl_dev[n] = dev; } status = alloc_chrdev_region(&ctrldev_num, 0, NUM_CTRL_CHANNELS, DEVICE_NAME); if (IS_ERR_VALUE(status)) { pr_err("ERROR:%s: alloc_chrdev_region() ret %i.\n", __func__, status); goto error0; } ctrldev_classp = class_create(THIS_MODULE, DEVICE_NAME); if (IS_ERR(ctrldev_classp)) { pr_err("ERROR:%s: class_create() ENOMEM\n", __func__); status = -ENOMEM; goto error1; } for (n = 0; n < NUM_CTRL_CHANNELS; ++n) { cdev_init(&ctrl_dev[n]->cdev, &ctrldev_fops); ctrl_dev[n]->cdev.owner = THIS_MODULE; status = cdev_add(&ctrl_dev[n]->cdev, (ctrldev_num + n), 1); if (IS_ERR_VALUE(status)) { pr_err("%s: cdev_add() ret %i\n", __func__, status); kfree(ctrl_dev[n]); goto error2; } ctrl_dev[n]->devicep = device_create(ctrldev_classp, NULL, (ctrldev_num + n), NULL, DEVICE_NAME "%d", n); if (IS_ERR(ctrl_dev[n]->devicep)) { pr_err("%s: device_create() ENOMEM\n", __func__); status = -ENOMEM; cdev_del(&ctrl_dev[n]->cdev); kfree(ctrl_dev[n]); goto error2; } /*create /sys/class/hsicctl/hsicctlx/modem_wait*/ status = device_create_file(ctrl_dev[n]->devicep, &dev_attr_modem_wait); if (status) { device_destroy(ctrldev_classp, MKDEV(MAJOR(ctrldev_num), n)); cdev_del(&ctrl_dev[n]->cdev); kfree(ctrl_dev[n]); goto error2; } dev_set_drvdata(ctrl_dev[n]->devicep, ctrl_dev[n]); } rmnet_usb_ctrl_debugfs_init(); pr_info("rmnet usb ctrl Initialized.\n"); return 0; error2: while (--n >= 0) { cdev_del(&ctrl_dev[n]->cdev); device_destroy(ctrldev_classp, MKDEV(MAJOR(ctrldev_num), n)); } class_destroy(ctrldev_classp); n = NUM_CTRL_CHANNELS; error1: unregister_chrdev_region(MAJOR(ctrldev_num), NUM_CTRL_CHANNELS); error0: while (--n >= 0) kfree(ctrl_dev[n]); return status; }
int rmnet_usb_ctrl_init(void) { struct rmnet_ctrl_dev *dev; int n; int status; int ret = 0; if (get_radio_flag() & 0x0001) usb_pm_debug_enabled = true; if (get_radio_flag() & 0x0002) enable_ctl_msg_debug = true; #ifdef HTC_LOG_RMNET_USB_CTRL if (get_radio_flag() & 0x0008) enable_dbg_rmnet_usb_ctrl = true; #endif for (n = 0; n < NUM_CTRL_CHANNELS; ++n) { dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { status = -ENOMEM; goto error0; } snprintf(dev->name, CTRL_DEV_MAX_LEN, "hsicctl%d", n); dev->wq = create_singlethread_workqueue(dev->name); if (!dev->wq) { pr_err("unable to allocate workqueue"); kfree(dev); goto error0; } mutex_init(&dev->dev_lock); spin_lock_init(&dev->rx_lock); init_waitqueue_head(&dev->read_wait_queue); init_waitqueue_head(&dev->open_wait_queue); INIT_LIST_HEAD(&dev->rx_list); init_usb_anchor(&dev->tx_submitted); init_usb_anchor(&dev->rx_submitted); INIT_WORK(&dev->get_encap_work, get_encap_work); status = rmnet_usb_ctrl_alloc_rx(dev); if (status < 0) { kfree(dev); goto error0; } ctrl_dev[n] = dev; } status = alloc_chrdev_region(&ctrldev_num, 0, NUM_CTRL_CHANNELS, DEVICE_NAME); if (IS_ERR_VALUE(status)) { pr_err("ERROR:%s: alloc_chrdev_region() ret %i.\n", __func__, status); goto error0; } ctrldev_classp = class_create(THIS_MODULE, DEVICE_NAME); if (IS_ERR(ctrldev_classp)) { pr_err("ERROR:%s: class_create() ENOMEM\n", __func__); status = -ENOMEM; goto error1; } for (n = 0; n < NUM_CTRL_CHANNELS; ++n) { cdev_init(&ctrl_dev[n]->cdev, &ctrldev_fops); ctrl_dev[n]->cdev.owner = THIS_MODULE; status = cdev_add(&ctrl_dev[n]->cdev, (ctrldev_num + n), 1); if (IS_ERR_VALUE(status)) { pr_err("%s: cdev_add() ret %i\n", __func__, status); kfree(ctrl_dev[n]); goto error2; } ctrl_dev[n]->devicep = device_create(ctrldev_classp, NULL, (ctrldev_num + n), NULL, DEVICE_NAME "%d", n); if (IS_ERR(ctrl_dev[n]->devicep)) { pr_err("%s: device_create() ENOMEM\n", __func__); status = -ENOMEM; cdev_del(&ctrl_dev[n]->cdev); kfree(ctrl_dev[n]); goto error2; } status = device_create_file(ctrl_dev[n]->devicep, &dev_attr_modem_wait); if (status) { device_destroy(ctrldev_classp, MKDEV(MAJOR(ctrldev_num), n)); cdev_del(&ctrl_dev[n]->cdev); kfree(ctrl_dev[n]); goto error2; } dev_set_drvdata(ctrl_dev[n]->devicep, ctrl_dev[n]); } rmnet_usb_ctrl_debugfs_init(); do { pr_info("%s: register_chrdev\n", __func__); ret = register_chrdev(0, HTC_HSIC_DEVICE_NAME, &hsicctrldev_fops); if ( ret < 0 ) { pr_err("%s: register_chrdev, ret=[%d]\n", __func__, ret); break; } pr_info("%s: register_chrdev, ret=[%d]\n", __func__, ret); htc_hsicctrldev_major = ret; pr_info("%s: class_create\n", __func__); hsicctrldev_classp = class_create(THIS_MODULE, HTC_HSIC_DEVICE_NAME); if (IS_ERR(hsicctrldev_classp)) { pr_err("%s: class_create() ENOMEM\n", __func__); unregister_chrdev( htc_hsicctrldev_major, HTC_HSIC_DEVICE_NAME ); break; } pr_info("%s: device_create\n", __func__); hsicdevicep = device_create(hsicctrldev_classp, NULL, MKDEV(htc_hsicctrldev_major, 0), NULL, HTC_HSIC_DEVICE_NAME); if (IS_ERR(hsicdevicep)) { pr_err("%s: device_create() ENOMEM\n", __func__); class_destroy(hsicctrldev_classp); hsicctrldev_classp = NULL; hsicdevicep = NULL; break; } } while ( 0 ); pr_info("rmnet usb ctrl Initialized.\n"); return 0; error2: while (--n >= 0) { cdev_del(&ctrl_dev[n]->cdev); device_destroy(ctrldev_classp, MKDEV(MAJOR(ctrldev_num), n)); } class_destroy(ctrldev_classp); n = NUM_CTRL_CHANNELS; error1: unregister_chrdev_region(MAJOR(ctrldev_num), NUM_CTRL_CHANNELS); error0: while (--n >= 0) kfree(ctrl_dev[n]); return status; }