diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/hvc_console.c | 80 |
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 | */ |
116 | static struct hvc_struct *hvc_get_by_index(int index) | 116 | static 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 | } |
243 | console_initcall(hvc_console_init); | 243 | console_initcall(hvc_console_init); |
244 | 244 | ||
245 | /* callback when the kboject ref count reaches zero. */ | ||
246 | static 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) | |||
372 | static void hvc_close(struct tty_struct *tty, struct file * filp) | 386 | static 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 | ||
423 | static void hvc_hangup(struct tty_struct *tty) | 435 | static 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. */ | ||
733 | static 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 | |||
749 | static struct kobj_type hvc_kobj_type = { | ||
750 | .release = destroy_hvc_struct, | ||
751 | }; | ||
752 | |||
753 | struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | 742 | struct 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, | |||
806 | int __devexit hvc_remove(struct hvc_struct *hp) | 794 | int __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 |