diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 06:31:43 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 06:31:43 -0700 |
commit | 0a95d92c0054e74fb79607ac2df958b7bf295706 (patch) | |
tree | e2c5f836e799dcfd72904949be47595af91432e7 /drivers/tty/hvc | |
parent | 08351fc6a75731226e1112fc7254542bd3a2912e (diff) | |
parent | 831532035b12a5f7b600515a6f4da0b207b82d6e (diff) | |
download | linux-3.10-0a95d92c0054e74fb79607ac2df958b7bf295706.tar.gz linux-3.10-0a95d92c0054e74fb79607ac2df958b7bf295706.tar.bz2 linux-3.10-0a95d92c0054e74fb79607ac2df958b7bf295706.zip |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (62 commits)
powerpc/85xx: Fix signedness bug in cache-sram
powerpc/fsl: 85xx: document cache sram bindings
powerpc/fsl: define binding for fsl mpic interrupt controllers
powerpc/fsl_msi: Handle msi-available-ranges better
drivers/serial/ucc_uart.c: Add of_node_put to avoid memory leak
powerpc/85xx: Fix SPE float to integer conversion failure
powerpc/85xx: Update sata controller compatible for p1022ds board
ATA: Add FSL sata v2 controller support
powerpc/mpc8xxx_gpio: simplify searching for 'fsl, qoriq-gpio' compatiable
powerpc/8xx: remove obsolete mgsuvd board
powerpc/82xx: rename and update mgcoge board support
powerpc/83xx: rename and update kmeter1
powerpc/85xx: Workaroudn e500 CPU erratum A005
powerpc/fsl_pci: Add support for FSL PCIe controllers v2.x
powerpc/85xx: Fix writing to spin table 'cpu-release-addr' on ppc64e
powerpc/pseries: Disable MSI using new interface if possible
powerpc: Enable GENERIC_HARDIRQS_NO_DEPRECATED.
powerpc: core irq_data conversion.
powerpc: sysdev/xilinx_intc irq_data conversion.
powerpc: sysdev/uic irq_data conversion.
...
Fix up conflicts in arch/powerpc/sysdev/fsl_msi.c (due to getting rid of
of_platform_driver in arch/powerpc)
Diffstat (limited to 'drivers/tty/hvc')
-rw-r--r-- | drivers/tty/hvc/hvcs.c | 74 |
1 files changed, 43 insertions, 31 deletions
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index bedc6c1b6fa..7e315b7f870 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -309,6 +309,7 @@ struct hvcs_struct { static LIST_HEAD(hvcs_structs); static DEFINE_SPINLOCK(hvcs_structs_lock); +static DEFINE_MUTEX(hvcs_init_mutex); static void hvcs_unthrottle(struct tty_struct *tty); static void hvcs_throttle(struct tty_struct *tty); @@ -340,6 +341,7 @@ static int __devinit hvcs_probe(struct vio_dev *dev, static int __devexit hvcs_remove(struct vio_dev *dev); static int __init hvcs_module_init(void); static void __exit hvcs_module_exit(void); +static int __devinit hvcs_initialize(void); #define HVCS_SCHED_READ 0x00000001 #define HVCS_QUICK_READ 0x00000002 @@ -762,7 +764,7 @@ static int __devinit hvcs_probe( const struct vio_device_id *id) { struct hvcs_struct *hvcsd; - int index; + int index, rc; int retval; if (!dev || !id) { @@ -770,6 +772,13 @@ static int __devinit hvcs_probe( return -EPERM; } + /* Make sure we are properly initialized */ + rc = hvcs_initialize(); + if (rc) { + pr_err("HVCS: Failed to initialize core driver.\n"); + return rc; + } + /* early to avoid cleanup on failure */ index = hvcs_get_index(); if (index < 0) { @@ -1464,12 +1473,15 @@ static void hvcs_free_index_list(void) hvcs_index_count = 0; } -static int __init hvcs_module_init(void) +static int __devinit hvcs_initialize(void) { - int rc; - int num_ttys_to_alloc; + int rc, num_ttys_to_alloc; - printk(KERN_INFO "Initializing %s\n", hvcs_driver_string); + mutex_lock(&hvcs_init_mutex); + if (hvcs_task) { + mutex_unlock(&hvcs_init_mutex); + return 0; + } /* Has the user specified an overload with an insmod param? */ if (hvcs_parm_num_devs <= 0 || @@ -1528,35 +1540,13 @@ static int __init hvcs_module_init(void) hvcs_task = kthread_run(khvcsd, NULL, "khvcsd"); if (IS_ERR(hvcs_task)) { - printk(KERN_ERR "HVCS: khvcsd creation failed. Driver not loaded.\n"); + printk(KERN_ERR "HVCS: khvcsd creation failed.\n"); rc = -EIO; goto kthread_fail; } - - rc = vio_register_driver(&hvcs_vio_driver); - if (rc) { - printk(KERN_ERR "HVCS: can't register vio driver\n"); - goto vio_fail; - } - - /* - * This needs to be done AFTER the vio_register_driver() call or else - * the kobjects won't be initialized properly. - */ - rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan); - if (rc) { - printk(KERN_ERR "HVCS: sysfs attr create failed\n"); - goto attr_fail; - } - - printk(KERN_INFO "HVCS: driver module inserted.\n"); - + mutex_unlock(&hvcs_init_mutex); return 0; -attr_fail: - vio_unregister_driver(&hvcs_vio_driver); -vio_fail: - kthread_stop(hvcs_task); kthread_fail: kfree(hvcs_pi_buff); buff_alloc_fail: @@ -1566,15 +1556,39 @@ register_fail: index_fail: put_tty_driver(hvcs_tty_driver); hvcs_tty_driver = NULL; + mutex_unlock(&hvcs_init_mutex); return rc; } +static int __init hvcs_module_init(void) +{ + int rc = vio_register_driver(&hvcs_vio_driver); + if (rc) { + printk(KERN_ERR "HVCS: can't register vio driver\n"); + return rc; + } + + pr_info("HVCS: Driver registered.\n"); + + /* This needs to be done AFTER the vio_register_driver() call or else + * the kobjects won't be initialized properly. + */ + rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan); + if (rc) + pr_warning(KERN_ERR "HVCS: Failed to create rescan file (err %d)\n", rc); + + return 0; +} + static void __exit hvcs_module_exit(void) { /* * This driver receives hvcs_remove callbacks for each device upon * module removal. */ + vio_unregister_driver(&hvcs_vio_driver); + if (!hvcs_task) + return; /* * This synchronous operation will wake the khvcsd kthread if it is @@ -1589,8 +1603,6 @@ static void __exit hvcs_module_exit(void) driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan); - vio_unregister_driver(&hvcs_vio_driver); - tty_unregister_driver(hvcs_tty_driver); hvcs_free_index_list(); |