static void __exit citty_exit(void) { struct citty_port *citty = NULL; int i; F_ENTER(); /* unregister devices */ for (i = 0; i < CITTY_TTY_MINORS; ++i) { down(&sem_lock_tty[i]); citty = citty_table[i]; if (citty) { citty_table[i] = NULL; kfree(citty); } up(&sem_lock_tty[i]); tty_port_destroy(&citty_port_table[i]); tty_unregister_device(citty_tty_driver, i); cci_free_buffer(&txCittyBuf[i]); } /* unregister driver */ tty_unregister_driver(citty_tty_driver); put_tty_driver(citty_tty_driver); /* clean up for the cctdev stuff */ cctdev_cleanup_module(); F_LEAVE(); }
static void __exit citty_exit(void) { struct citty_serial *citty; int i; F_ENTER(); for (i = 0; i < CITTY_TTY_MINORS; ++i) tty_unregister_device(citty_tty_driver, i); tty_unregister_driver(citty_tty_driver); put_tty_driver(citty_tty_driver); /* free the memory */ for (i = 0; i < CITTY_TTY_MINORS; ++i) { down(&sem[i]); citty = citty_table[i]; if (citty) { kfree(citty); citty_table[i] = NULL; //cci_free_buffer(&txCittyBuf[i]); } up(&sem[i]); cci_free_buffer(&txCittyBuf[i]); //Modified by Rovin to move here } /* clean up for the cctdev stuff */ cctdev_cleanup_module(); F_LEAVE(); }
int cctdev_init_module(void) { int result, i; dev_t dev = 0; char name[256]; F_ENTER(); /* * Get a range of minor numbers to work with, asking for a dynamic * major unless directed otherwise at load time. */ if (cctdev_major) { dev = MKDEV(cctdev_major, cctdev_minor); result = register_chrdev_region(dev, cctdev_nr_devs, "cctdev"); } else { result = alloc_chrdev_region(&dev, cctdev_minor, cctdev_nr_devs, "cctdev"); cctdev_major = MAJOR(dev); } if (result < 0) { printk(KERN_WARNING "cctdev: can't get major %d\n", cctdev_major); return result; } /* * allocate the devices -- we can't have them static, as the number * can be specified at load time */ cctdev_devices = kmalloc(cctdev_nr_devs * sizeof(struct cctdev_dev), GFP_KERNEL); if (!cctdev_devices) { result = -ENOMEM; goto fail; /* Make this more graceful */ } memset(cctdev_devices, 0, cctdev_nr_devs * sizeof(struct cctdev_dev)); cctdev_class = class_create(THIS_MODULE, "cctdev"); /* Initialize each device. */ for (i = 0; i < cctdev_nr_devs; i++) { sprintf(name, "%s%d", "cctdev", i); sema_init(&cctdev_devices[i].sem, 1); cctdev_setup_cdev(&cctdev_devices[i], i); device_create(cctdev_class, NULL, MKDEV(cctdev_major, cctdev_minor + i), NULL, name); } /* At this point call the init function for any friend device */ dev = MKDEV(cctdev_major, cctdev_minor + cctdev_nr_devs); #ifdef cctdev_DEBUG /* only when debugging */ cctdev_create_proc(); #endif F_LEAVE(); cctdev_ready = 1; return 0; /* succeed */ fail: cctdev_cleanup_module(); return result; }