aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/hvc_console.c80
1 files changed, 33 insertions, 47 deletions
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 8252f8668538..480fae29c9b2 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -27,7 +27,7 @@
27#include <linux/init.h> 27#include <linux/init.h>
28#include <linux/kbd_kern.h> 28#include <linux/kbd_kern.h>
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/kobject.h> 30#include <linux/kref.h>
31#include <linux/kthread.h> 31#include <linux/kthread.h>
32#include <linux/list.h> 32#include <linux/list.h>
33#include <linux/module.h> 33#include <linux/module.h>
@@ -89,7 +89,7 @@ struct hvc_struct {
89 int irq_requested; 89 int irq_requested;
90 int irq; 90 int irq;
91 struct list_head next; 91 struct list_head next;
92 struct kobject kobj; /* ref count & hvc_struct lifetime */ 92 struct kref kref; /* ref count & hvc_struct lifetime */
93}; 93};
94 94
95/* dynamic list of hvc_struct instances */ 95/* dynamic list of hvc_struct instances */
@@ -110,7 +110,7 @@ static int last_hvc = -1;
110 110
111/* 111/*
112 * Do not call this function with either the hvc_structs_lock or the hvc_struct 112 * Do not call this function with either the hvc_structs_lock or the hvc_struct
113 * lock held. If successful, this function increments the kobject reference 113 * lock held. If successful, this function increments the kref reference
114 * count against the target hvc_struct so it should be released when finished. 114 * count against the target hvc_struct so it should be released when finished.
115 */ 115 */
116static struct hvc_struct *hvc_get_by_index(int index) 116static struct hvc_struct *hvc_get_by_index(int index)
@@ -123,7 +123,7 @@ static struct hvc_struct *hvc_get_by_index(int index)
123 list_for_each_entry(hp, &hvc_structs, next) { 123 list_for_each_entry(hp, &hvc_structs, next) {
124 spin_lock_irqsave(&hp->lock, flags); 124 spin_lock_irqsave(&hp->lock, flags);
125 if (hp->index == index) { 125 if (hp->index == index) {
126 kobject_get(&hp->kobj); 126 kref_get(&hp->kref);
127 spin_unlock_irqrestore(&hp->lock, flags); 127 spin_unlock_irqrestore(&hp->lock, flags);
128 spin_unlock(&hvc_structs_lock); 128 spin_unlock(&hvc_structs_lock);
129 return hp; 129 return hp;
@@ -242,6 +242,23 @@ static int __init hvc_console_init(void)
242} 242}
243console_initcall(hvc_console_init); 243console_initcall(hvc_console_init);
244 244
245/* callback when the kboject ref count reaches zero. */
246static void destroy_hvc_struct(struct kref *kref)
247{
248 struct hvc_struct *hp = container_of(kref, struct hvc_struct, kref);
249 unsigned long flags;
250
251 spin_lock(&hvc_structs_lock);
252
253 spin_lock_irqsave(&hp->lock, flags);
254 list_del(&(hp->next));
255 spin_unlock_irqrestore(&hp->lock, flags);
256
257 spin_unlock(&hvc_structs_lock);
258
259 kfree(hp);
260}
261
245/* 262/*
246 * hvc_instantiate() is an early console discovery method which locates 263 * hvc_instantiate() is an early console discovery method which locates
247 * consoles * prior to the vio subsystem discovering them. Hotplugged 264 * consoles * prior to the vio subsystem discovering them. Hotplugged
@@ -261,7 +278,7 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
261 /* make sure no no tty has been registered in this index */ 278 /* make sure no no tty has been registered in this index */
262 hp = hvc_get_by_index(index); 279 hp = hvc_get_by_index(index);
263 if (hp) { 280 if (hp) {
264 kobject_put(&hp->kobj); 281 kref_put(&hp->kref, destroy_hvc_struct);
265 return -1; 282 return -1;
266 } 283 }
267 284
@@ -318,9 +335,8 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
318 unsigned long flags; 335 unsigned long flags;
319 int irq = 0; 336 int irq = 0;
320 int rc = 0; 337 int rc = 0;
321 struct kobject *kobjp;
322 338
323 /* Auto increments kobject reference if found. */ 339 /* Auto increments kref reference if found. */
324 if (!(hp = hvc_get_by_index(tty->index))) 340 if (!(hp = hvc_get_by_index(tty->index)))
325 return -ENODEV; 341 return -ENODEV;
326 342
@@ -341,8 +357,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
341 if (irq) 357 if (irq)
342 hp->irq_requested = 1; 358 hp->irq_requested = 1;
343 359
344 kobjp = &hp->kobj;
345
346 spin_unlock_irqrestore(&hp->lock, flags); 360 spin_unlock_irqrestore(&hp->lock, flags);
347 /* check error, fallback to non-irq */ 361 /* check error, fallback to non-irq */
348 if (irq) 362 if (irq)
@@ -352,7 +366,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
352 * If the request_irq() fails and we return an error. The tty layer 366 * If the request_irq() fails and we return an error. The tty layer
353 * will call hvc_close() after a failed open but we don't want to clean 367 * will call hvc_close() after a failed open but we don't want to clean
354 * up there so we'll clean up here and clear out the previously set 368 * up there so we'll clean up here and clear out the previously set
355 * tty fields and return the kobject reference. 369 * tty fields and return the kref reference.
356 */ 370 */
357 if (rc) { 371 if (rc) {
358 spin_lock_irqsave(&hp->lock, flags); 372 spin_lock_irqsave(&hp->lock, flags);
@@ -360,7 +374,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
360 hp->irq_requested = 0; 374 hp->irq_requested = 0;
361 spin_unlock_irqrestore(&hp->lock, flags); 375 spin_unlock_irqrestore(&hp->lock, flags);
362 tty->driver_data = NULL; 376 tty->driver_data = NULL;
363 kobject_put(kobjp); 377 kref_put(&hp->kref, destroy_hvc_struct);
364 printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc); 378 printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
365 } 379 }
366 /* Force wakeup of the polling thread */ 380 /* Force wakeup of the polling thread */
@@ -372,7 +386,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
372static void hvc_close(struct tty_struct *tty, struct file * filp) 386static void hvc_close(struct tty_struct *tty, struct file * filp)
373{ 387{
374 struct hvc_struct *hp; 388 struct hvc_struct *hp;
375 struct kobject *kobjp;
376 int irq = 0; 389 int irq = 0;
377 unsigned long flags; 390 unsigned long flags;
378 391
@@ -382,7 +395,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
382 /* 395 /*
383 * No driver_data means that this close was issued after a failed 396 * No driver_data means that this close was issued after a failed
384 * hvc_open by the tty layer's release_dev() function and we can just 397 * hvc_open by the tty layer's release_dev() function and we can just
385 * exit cleanly because the kobject reference wasn't made. 398 * exit cleanly because the kref reference wasn't made.
386 */ 399 */
387 if (!tty->driver_data) 400 if (!tty->driver_data)
388 return; 401 return;
@@ -390,7 +403,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
390 hp = tty->driver_data; 403 hp = tty->driver_data;
391 spin_lock_irqsave(&hp->lock, flags); 404 spin_lock_irqsave(&hp->lock, flags);
392 405
393 kobjp = &hp->kobj;
394 if (--hp->count == 0) { 406 if (--hp->count == 0) {
395 if (hp->irq_requested) 407 if (hp->irq_requested)
396 irq = hp->irq; 408 irq = hp->irq;
@@ -417,7 +429,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
417 spin_unlock_irqrestore(&hp->lock, flags); 429 spin_unlock_irqrestore(&hp->lock, flags);
418 } 430 }
419 431
420 kobject_put(kobjp); 432 kref_put(&hp->kref, destroy_hvc_struct);
421} 433}
422 434
423static void hvc_hangup(struct tty_struct *tty) 435static void hvc_hangup(struct tty_struct *tty)
@@ -426,7 +438,6 @@ static void hvc_hangup(struct tty_struct *tty)
426 unsigned long flags; 438 unsigned long flags;
427 int irq = 0; 439 int irq = 0;
428 int temp_open_count; 440 int temp_open_count;
429 struct kobject *kobjp;
430 441
431 if (!hp) 442 if (!hp)
432 return; 443 return;
@@ -443,7 +454,6 @@ static void hvc_hangup(struct tty_struct *tty)
443 return; 454 return;
444 } 455 }
445 456
446 kobjp = &hp->kobj;
447 temp_open_count = hp->count; 457 temp_open_count = hp->count;
448 hp->count = 0; 458 hp->count = 0;
449 hp->n_outbuf = 0; 459 hp->n_outbuf = 0;
@@ -457,7 +467,7 @@ static void hvc_hangup(struct tty_struct *tty)
457 free_irq(irq, hp); 467 free_irq(irq, hp);
458 while(temp_open_count) { 468 while(temp_open_count) {
459 --temp_open_count; 469 --temp_open_count;
460 kobject_put(kobjp); 470 kref_put(&hp->kref, destroy_hvc_struct);
461 } 471 }
462} 472}
463 473
@@ -729,27 +739,6 @@ static const struct tty_operations hvc_ops = {
729 .chars_in_buffer = hvc_chars_in_buffer, 739 .chars_in_buffer = hvc_chars_in_buffer,
730}; 740};
731 741
732/* callback when the kboject ref count reaches zero. */
733static void destroy_hvc_struct(struct kobject *kobj)
734{
735 struct hvc_struct *hp = container_of(kobj, struct hvc_struct, kobj);
736 unsigned long flags;
737
738 spin_lock(&hvc_structs_lock);
739
740 spin_lock_irqsave(&hp->lock, flags);
741 list_del(&(hp->next));
742 spin_unlock_irqrestore(&hp->lock, flags);
743
744 spin_unlock(&hvc_structs_lock);
745
746 kfree(hp);
747}
748
749static struct kobj_type hvc_kobj_type = {
750 .release = destroy_hvc_struct,
751};
752
753struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, 742struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
754 struct hv_ops *ops, int outbuf_size) 743 struct hv_ops *ops, int outbuf_size)
755{ 744{
@@ -776,8 +765,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
776 hp->outbuf_size = outbuf_size; 765 hp->outbuf_size = outbuf_size;
777 hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; 766 hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];
778 767
779 kobject_init(&hp->kobj); 768 kref_init(&hp->kref);
780 hp->kobj.ktype = &hvc_kobj_type;
781 769
782 spin_lock_init(&hp->lock); 770 spin_lock_init(&hp->lock);
783 spin_lock(&hvc_structs_lock); 771 spin_lock(&hvc_structs_lock);
@@ -806,12 +794,10 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
806int __devexit hvc_remove(struct hvc_struct *hp) 794int __devexit hvc_remove(struct hvc_struct *hp)
807{ 795{
808 unsigned long flags; 796 unsigned long flags;
809 struct kobject *kobjp;
810 struct tty_struct *tty; 797 struct tty_struct *tty;
811 798
812 spin_lock_irqsave(&hp->lock, flags); 799 spin_lock_irqsave(&hp->lock, flags);
813 tty = hp->tty; 800 tty = hp->tty;
814 kobjp = &hp->kobj;
815 801
816 if (hp->index < MAX_NR_HVC_CONSOLES) 802 if (hp->index < MAX_NR_HVC_CONSOLES)
817 vtermnos[hp->index] = -1; 803 vtermnos[hp->index] = -1;
@@ -821,12 +807,12 @@ int __devexit hvc_remove(struct hvc_struct *hp)
821 spin_unlock_irqrestore(&hp->lock, flags); 807 spin_unlock_irqrestore(&hp->lock, flags);
822 808
823 /* 809 /*
824 * We 'put' the instance that was grabbed when the kobject instance 810 * We 'put' the instance that was grabbed when the kref instance
825 * was initialized using kobject_init(). Let the last holder of this 811 * was initialized using kref_init(). Let the last holder of this
826 * kobject cause it to be removed, which will probably be the tty_hangup 812 * kref cause it to be removed, which will probably be the tty_hangup
827 * below. 813 * below.
828 */ 814 */
829 kobject_put(kobjp); 815 kref_put(&hp->kref, destroy_hvc_struct);
830 816
831 /* 817 /*
832 * This function call will auto chain call hvc_hangup. The tty should 818 * This function call will auto chain call hvc_hangup. The tty should