static void __exit mic_exit(void) { /* Close endpoints related to reverse registration */ acptboot_exit(); #ifdef USE_VCONSOLE micvcons_destroy(mic_data.dd_numdevs); #endif pci_unregister_driver(&mic_lindata.dd_pcidriver); micpm_uninit(); /* Uninit data structures for PM disconnect */ micpm_disconn_uninit(mic_data.dd_numdevs + 1); #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34)) pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "mic"); #endif micscif_kmem_cache_destroy(); vmcore_exit(); micveth_exit(); micscif_destroy(); ramoops_exit(); device_destroy(mic_lindata.dd_class, mic_lindata.dd_dev + 1); device_destroy(mic_lindata.dd_class, mic_lindata.dd_dev); class_destroy(mic_lindata.dd_class); cdev_del(&mic_lindata.dd_cdev); unregister_chrdev_region(mic_lindata.dd_dev, MAX_DLDR_MINORS); unregister_pm_notifier(&mic_pm_notifer); return; }
int micvcons_create(int num_bds) { micvcons_port_t *port; bd_info_t *bd_info; int bd, ret = 0; char wq_name[14]; struct device *dev; INIT_LIST_HEAD(&timer_list_head); if (micvcons_tty) goto exit; micvcons_tty = alloc_tty_driver(num_bds); if (!micvcons_tty) { ret = -ENOMEM; goto exit; } micvcons_tty->owner = THIS_MODULE; micvcons_tty->driver_name = MICVCONS_DEVICE_NAME; micvcons_tty->name = MICVCONS_DEVICE_NAME; micvcons_tty->major = 0; #if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) micvcons_tty->minor_num = num_bds; #endif micvcons_tty->minor_start = 0; micvcons_tty->type = TTY_DRIVER_TYPE_SERIAL; micvcons_tty->subtype = SERIAL_TYPE_NORMAL; micvcons_tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; micvcons_tty->init_termios = tty_std_termios; micvcons_tty->init_termios.c_iflag = IGNCR; micvcons_tty->init_termios.c_oflag = 0; micvcons_tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; micvcons_tty->init_termios.c_lflag = 0; tty_set_operations(micvcons_tty, &micvcons_tty_ops); if ((ret = tty_register_driver(micvcons_tty)) != 0) { printk("Failed to register vcons tty driver\n"); put_tty_driver(micvcons_tty); micvcons_tty = NULL; goto exit; } for (bd = 0; bd < num_bds; bd++) { port = &mic_data.dd_ports[bd]; port->dp_bdinfo = mic_data.dd_bi[bd]; spin_lock_init(&port->dp_lock); mutex_init (&port->dp_mutex); bd_info = (bd_info_t *)port->dp_bdinfo; bd_info->bi_port = port; dev = tty_register_device(micvcons_tty, bd, NULL); if (IS_ERR(dev)) { printk("Failed to register vcons tty device\n"); micvcons_destroy(bd); ret = PTR_ERR(dev); goto exit; } snprintf(wq_name, sizeof(wq_name), "VCONS MIC %d", bd); port->dp_wq = create_singlethread_workqueue(wq_name); if (!port->dp_wq) { printk(KERN_ERR "%s: create_singlethread_workqueue\n", __func__); tty_unregister_device(micvcons_tty, bd); micvcons_destroy(bd); ret = -ENOMEM; goto exit; } INIT_WORK(&port->dp_wakeup_read_buf, micvcons_wakeup_readbuf); } vcons_timer.function = micvcons_timeout; vcons_timer.data = (unsigned long)(&timer_list_head); init_timer(&vcons_timer); exit: return ret; }