aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/hvc/hvcs.c74
1 files changed, 43 insertions, 31 deletions
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index bedc6c1b6fa5..7e315b7f8700 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -309,6 +309,7 @@ struct hvcs_struct {
309 309
310static LIST_HEAD(hvcs_structs); 310static LIST_HEAD(hvcs_structs);
311static DEFINE_SPINLOCK(hvcs_structs_lock); 311static DEFINE_SPINLOCK(hvcs_structs_lock);
312static DEFINE_MUTEX(hvcs_init_mutex);
312 313
313static void hvcs_unthrottle(struct tty_struct *tty); 314static void hvcs_unthrottle(struct tty_struct *tty);
314static void hvcs_throttle(struct tty_struct *tty); 315static void hvcs_throttle(struct tty_struct *tty);
@@ -340,6 +341,7 @@ static int __devinit hvcs_probe(struct vio_dev *dev,
340static int __devexit hvcs_remove(struct vio_dev *dev); 341static int __devexit hvcs_remove(struct vio_dev *dev);
341static int __init hvcs_module_init(void); 342static int __init hvcs_module_init(void);
342static void __exit hvcs_module_exit(void); 343static void __exit hvcs_module_exit(void);
344static int __devinit hvcs_initialize(void);
343 345
344#define HVCS_SCHED_READ 0x00000001 346#define HVCS_SCHED_READ 0x00000001
345#define HVCS_QUICK_READ 0x00000002 347#define HVCS_QUICK_READ 0x00000002
@@ -762,7 +764,7 @@ static int __devinit hvcs_probe(
762 const struct vio_device_id *id) 764 const struct vio_device_id *id)
763{ 765{
764 struct hvcs_struct *hvcsd; 766 struct hvcs_struct *hvcsd;
765 int index; 767 int index, rc;
766 int retval; 768 int retval;
767 769
768 if (!dev || !id) { 770 if (!dev || !id) {
@@ -770,6 +772,13 @@ static int __devinit hvcs_probe(
770 return -EPERM; 772 return -EPERM;
771 } 773 }
772 774
775 /* Make sure we are properly initialized */
776 rc = hvcs_initialize();
777 if (rc) {
778 pr_err("HVCS: Failed to initialize core driver.\n");
779 return rc;
780 }
781
773 /* early to avoid cleanup on failure */ 782 /* early to avoid cleanup on failure */
774 index = hvcs_get_index(); 783 index = hvcs_get_index();
775 if (index < 0) { 784 if (index < 0) {
@@ -1464,12 +1473,15 @@ static void hvcs_free_index_list(void)
1464 hvcs_index_count = 0; 1473 hvcs_index_count = 0;
1465} 1474}
1466 1475
1467static int __init hvcs_module_init(void) 1476static int __devinit hvcs_initialize(void)
1468{ 1477{
1469 int rc; 1478 int rc, num_ttys_to_alloc;
1470 int num_ttys_to_alloc;
1471 1479
1472 printk(KERN_INFO "Initializing %s\n", hvcs_driver_string); 1480 mutex_lock(&hvcs_init_mutex);
1481 if (hvcs_task) {
1482 mutex_unlock(&hvcs_init_mutex);
1483 return 0;
1484 }
1473 1485
1474 /* Has the user specified an overload with an insmod param? */ 1486 /* Has the user specified an overload with an insmod param? */
1475 if (hvcs_parm_num_devs <= 0 || 1487 if (hvcs_parm_num_devs <= 0 ||
@@ -1528,35 +1540,13 @@ static int __init hvcs_module_init(void)
1528 1540
1529 hvcs_task = kthread_run(khvcsd, NULL, "khvcsd"); 1541 hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
1530 if (IS_ERR(hvcs_task)) { 1542 if (IS_ERR(hvcs_task)) {
1531 printk(KERN_ERR "HVCS: khvcsd creation failed. Driver not loaded.\n"); 1543 printk(KERN_ERR "HVCS: khvcsd creation failed.\n");
1532 rc = -EIO; 1544 rc = -EIO;
1533 goto kthread_fail; 1545 goto kthread_fail;
1534 } 1546 }
1535 1547 mutex_unlock(&hvcs_init_mutex);
1536 rc = vio_register_driver(&hvcs_vio_driver);
1537 if (rc) {
1538 printk(KERN_ERR "HVCS: can't register vio driver\n");
1539 goto vio_fail;
1540 }
1541
1542 /*
1543 * This needs to be done AFTER the vio_register_driver() call or else
1544 * the kobjects won't be initialized properly.
1545 */
1546 rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
1547 if (rc) {
1548 printk(KERN_ERR "HVCS: sysfs attr create failed\n");
1549 goto attr_fail;
1550 }
1551
1552 printk(KERN_INFO "HVCS: driver module inserted.\n");
1553
1554 return 0; 1548 return 0;
1555 1549
1556attr_fail:
1557 vio_unregister_driver(&hvcs_vio_driver);
1558vio_fail:
1559 kthread_stop(hvcs_task);
1560kthread_fail: 1550kthread_fail:
1561 kfree(hvcs_pi_buff); 1551 kfree(hvcs_pi_buff);
1562buff_alloc_fail: 1552buff_alloc_fail:
@@ -1566,15 +1556,39 @@ register_fail:
1566index_fail: 1556index_fail:
1567 put_tty_driver(hvcs_tty_driver); 1557 put_tty_driver(hvcs_tty_driver);
1568 hvcs_tty_driver = NULL; 1558 hvcs_tty_driver = NULL;
1559 mutex_unlock(&hvcs_init_mutex);
1569 return rc; 1560 return rc;
1570} 1561}
1571 1562
1563static int __init hvcs_module_init(void)
1564{
1565 int rc = vio_register_driver(&hvcs_vio_driver);
1566 if (rc) {
1567 printk(KERN_ERR "HVCS: can't register vio driver\n");
1568 return rc;
1569 }
1570
1571 pr_info("HVCS: Driver registered.\n");
1572
1573 /* This needs to be done AFTER the vio_register_driver() call or else
1574 * the kobjects won't be initialized properly.
1575 */
1576 rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
1577 if (rc)
1578 pr_warning(KERN_ERR "HVCS: Failed to create rescan file (err %d)\n", rc);
1579
1580 return 0;
1581}
1582
1572static void __exit hvcs_module_exit(void) 1583static void __exit hvcs_module_exit(void)
1573{ 1584{
1574 /* 1585 /*
1575 * This driver receives hvcs_remove callbacks for each device upon 1586 * This driver receives hvcs_remove callbacks for each device upon
1576 * module removal. 1587 * module removal.
1577 */ 1588 */
1589 vio_unregister_driver(&hvcs_vio_driver);
1590 if (!hvcs_task)
1591 return;
1578 1592
1579 /* 1593 /*
1580 * This synchronous operation will wake the khvcsd kthread if it is 1594 * This synchronous operation will wake the khvcsd kthread if it is
@@ -1589,8 +1603,6 @@ static void __exit hvcs_module_exit(void)
1589 1603
1590 driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan); 1604 driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan);
1591 1605
1592 vio_unregister_driver(&hvcs_vio_driver);
1593
1594 tty_unregister_driver(hvcs_tty_driver); 1606 tty_unregister_driver(hvcs_tty_driver);
1595 1607
1596 hvcs_free_index_list(); 1608 hvcs_free_index_list();