diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2008-06-20 09:24:08 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-07-24 22:06:06 -0400 |
commit | 611e097d7707741a336a0677d9d69bec40f29f3d (patch) | |
tree | 0b0059544914bf027ada51a1ba90f694c54df835 | |
parent | 066f4d82a67f621ddd547bfa4b9c94631d8457b0 (diff) |
hvc_console: rework setup to replace irq functions with callbacks
This patch tries to change hvc_console to not use request_irq/free_irq if
the backend does not use irqs. This allows virtio_console to use hvc_console
without having a linker reference to request_irq/free_irq.
In addition, together with patch 2/3 it improves the performance for virtio
console input. (an earlier version of this patch was tested by Yajin on lguest)
The irq specific code is moved to hvc_irq.c and selected by the drivers that
use irqs (System p, System i, XEN).
I replaced "int irq" with the opaque "int data". The request_irq and
free_irq calls are replaced with notifier_add and notifier_del. I have also
changed the code a bit to call the notifier_add and notifier_del inside the
spinlock area as the callbacks are found via hp->ops.
Changes since last version:
o remove ifdef
o reintroduce "irq_requested" as "notified"
o cleanups, sparse..
I did not move the timer based polling into a separate polling scheme. I
played with several variants, but it seems we need to sleep/schedule in
a thread even for irq based consoles, as there are throttleing and buffer
size constraints.
I also kept hvc_struct defined in hvc_console.h so that hvc_irq.c can access
the irq_requested element.
Feedback is appreciated. virtio_console is currently the only available console
for kvm on s390. I plan to push this change as soon as all affected parties
agree on it. I would love to get test results from System p, Xen etc.
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | drivers/char/Kconfig | 5 | ||||
-rw-r--r-- | drivers/char/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/hvc_console.c | 81 | ||||
-rw-r--r-- | drivers/char/hvc_console.h | 35 | ||||
-rw-r--r-- | drivers/char/hvc_irq.c | 44 | ||||
-rw-r--r-- | drivers/char/hvc_iseries.c | 2 | ||||
-rw-r--r-- | drivers/char/hvc_vio.c | 2 | ||||
-rw-r--r-- | drivers/char/hvc_xen.c | 2 |
8 files changed, 105 insertions, 67 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 67b07576f8bf..d825361a6baf 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -578,11 +578,14 @@ config HVC_DRIVER | |||
578 | It will automatically be selected if one of the back-end console drivers | 578 | It will automatically be selected if one of the back-end console drivers |
579 | is selected. | 579 | is selected. |
580 | 580 | ||
581 | config HVC_IRQ | ||
582 | bool | ||
581 | 583 | ||
582 | config HVC_CONSOLE | 584 | config HVC_CONSOLE |
583 | bool "pSeries Hypervisor Virtual Console support" | 585 | bool "pSeries Hypervisor Virtual Console support" |
584 | depends on PPC_PSERIES | 586 | depends on PPC_PSERIES |
585 | select HVC_DRIVER | 587 | select HVC_DRIVER |
588 | select HVC_IRQ | ||
586 | help | 589 | help |
587 | pSeries machines when partitioned support a hypervisor virtual | 590 | pSeries machines when partitioned support a hypervisor virtual |
588 | console. This driver allows each pSeries partition to have a console | 591 | console. This driver allows each pSeries partition to have a console |
@@ -593,6 +596,7 @@ config HVC_ISERIES | |||
593 | depends on PPC_ISERIES | 596 | depends on PPC_ISERIES |
594 | default y | 597 | default y |
595 | select HVC_DRIVER | 598 | select HVC_DRIVER |
599 | select HVC_IRQ | ||
596 | help | 600 | help |
597 | iSeries machines support a hypervisor virtual console. | 601 | iSeries machines support a hypervisor virtual console. |
598 | 602 | ||
@@ -614,6 +618,7 @@ config HVC_XEN | |||
614 | bool "Xen Hypervisor Console support" | 618 | bool "Xen Hypervisor Console support" |
615 | depends on XEN | 619 | depends on XEN |
616 | select HVC_DRIVER | 620 | select HVC_DRIVER |
621 | select HVC_IRQ | ||
617 | default y | 622 | default y |
618 | help | 623 | help |
619 | Xen virtual console device driver | 624 | Xen virtual console device driver |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 4b6e736cfa02..eb02c3506800 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -48,6 +48,7 @@ obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o | |||
48 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o | 48 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o |
49 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o | 49 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o |
50 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o | 50 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o |
51 | obj-$(CONFIG_HVC_IRQ) += hvc_irq.o | ||
51 | obj-$(CONFIG_HVC_XEN) += hvc_xen.o | 52 | obj-$(CONFIG_HVC_XEN) += hvc_xen.o |
52 | obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o | 53 | obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o |
53 | obj-$(CONFIG_RAW_DRIVER) += raw.o | 54 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 2f9759d625cc..2f5b7fb67045 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -27,7 +27,6 @@ | |||
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/kref.h> | ||
31 | #include <linux/kthread.h> | 30 | #include <linux/kthread.h> |
32 | #include <linux/list.h> | 31 | #include <linux/list.h> |
33 | #include <linux/module.h> | 32 | #include <linux/module.h> |
@@ -75,23 +74,6 @@ static int hvc_init(void); | |||
75 | static int sysrq_pressed; | 74 | static int sysrq_pressed; |
76 | #endif | 75 | #endif |
77 | 76 | ||
78 | struct hvc_struct { | ||
79 | spinlock_t lock; | ||
80 | int index; | ||
81 | struct tty_struct *tty; | ||
82 | unsigned int count; | ||
83 | int do_wakeup; | ||
84 | char *outbuf; | ||
85 | int outbuf_size; | ||
86 | int n_outbuf; | ||
87 | uint32_t vtermno; | ||
88 | struct hv_ops *ops; | ||
89 | int irq_requested; | ||
90 | int irq; | ||
91 | struct list_head next; | ||
92 | struct kref kref; /* ref count & hvc_struct lifetime */ | ||
93 | }; | ||
94 | |||
95 | /* dynamic list of hvc_struct instances */ | 77 | /* dynamic list of hvc_struct instances */ |
96 | static LIST_HEAD(hvc_structs); | 78 | static LIST_HEAD(hvc_structs); |
97 | 79 | ||
@@ -300,26 +282,12 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) | |||
300 | } | 282 | } |
301 | 283 | ||
302 | /* Wake the sleeping khvcd */ | 284 | /* Wake the sleeping khvcd */ |
303 | static void hvc_kick(void) | 285 | void hvc_kick(void) |
304 | { | 286 | { |
305 | hvc_kicked = 1; | 287 | hvc_kicked = 1; |
306 | wake_up_process(hvc_task); | 288 | wake_up_process(hvc_task); |
307 | } | 289 | } |
308 | 290 | ||
309 | static int hvc_poll(struct hvc_struct *hp); | ||
310 | |||
311 | /* | ||
312 | * NOTE: This API isn't used if the console adapter doesn't support interrupts. | ||
313 | * In this case the console is poll driven. | ||
314 | */ | ||
315 | static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance) | ||
316 | { | ||
317 | /* if hvc_poll request a repoll, then kick the hvcd thread */ | ||
318 | if (hvc_poll(dev_instance)) | ||
319 | hvc_kick(); | ||
320 | return IRQ_HANDLED; | ||
321 | } | ||
322 | |||
323 | static void hvc_unthrottle(struct tty_struct *tty) | 291 | static void hvc_unthrottle(struct tty_struct *tty) |
324 | { | 292 | { |
325 | hvc_kick(); | 293 | hvc_kick(); |
@@ -333,7 +301,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
333 | { | 301 | { |
334 | struct hvc_struct *hp; | 302 | struct hvc_struct *hp; |
335 | unsigned long flags; | 303 | unsigned long flags; |
336 | int irq = 0; | ||
337 | int rc = 0; | 304 | int rc = 0; |
338 | 305 | ||
339 | /* Auto increments kref reference if found. */ | 306 | /* Auto increments kref reference if found. */ |
@@ -352,18 +319,15 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
352 | tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ | 319 | tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ |
353 | 320 | ||
354 | hp->tty = tty; | 321 | hp->tty = tty; |
355 | /* Save for request_irq outside of spin_lock. */ | 322 | |
356 | irq = hp->irq; | 323 | if (hp->ops->notifier_add) |
357 | if (irq) | 324 | rc = hp->ops->notifier_add(hp, hp->data); |
358 | hp->irq_requested = 1; | ||
359 | 325 | ||
360 | spin_unlock_irqrestore(&hp->lock, flags); | 326 | spin_unlock_irqrestore(&hp->lock, flags); |
361 | /* check error, fallback to non-irq */ | 327 | |
362 | if (irq) | ||
363 | rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, "hvc_console", hp); | ||
364 | 328 | ||
365 | /* | 329 | /* |
366 | * If the request_irq() fails and we return an error. The tty layer | 330 | * If the notifier fails we return an error. The tty layer |
367 | * will call hvc_close() after a failed open but we don't want to clean | 331 | * will call hvc_close() after a failed open but we don't want to clean |
368 | * up there so we'll clean up here and clear out the previously set | 332 | * up there so we'll clean up here and clear out the previously set |
369 | * tty fields and return the kref reference. | 333 | * tty fields and return the kref reference. |
@@ -371,7 +335,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
371 | if (rc) { | 335 | if (rc) { |
372 | spin_lock_irqsave(&hp->lock, flags); | 336 | spin_lock_irqsave(&hp->lock, flags); |
373 | hp->tty = NULL; | 337 | hp->tty = NULL; |
374 | hp->irq_requested = 0; | ||
375 | spin_unlock_irqrestore(&hp->lock, flags); | 338 | spin_unlock_irqrestore(&hp->lock, flags); |
376 | tty->driver_data = NULL; | 339 | tty->driver_data = NULL; |
377 | kref_put(&hp->kref, destroy_hvc_struct); | 340 | kref_put(&hp->kref, destroy_hvc_struct); |
@@ -386,7 +349,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
386 | static void hvc_close(struct tty_struct *tty, struct file * filp) | 349 | static void hvc_close(struct tty_struct *tty, struct file * filp) |
387 | { | 350 | { |
388 | struct hvc_struct *hp; | 351 | struct hvc_struct *hp; |
389 | int irq = 0; | ||
390 | unsigned long flags; | 352 | unsigned long flags; |
391 | 353 | ||
392 | if (tty_hung_up_p(filp)) | 354 | if (tty_hung_up_p(filp)) |
@@ -404,9 +366,8 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
404 | spin_lock_irqsave(&hp->lock, flags); | 366 | spin_lock_irqsave(&hp->lock, flags); |
405 | 367 | ||
406 | if (--hp->count == 0) { | 368 | if (--hp->count == 0) { |
407 | if (hp->irq_requested) | 369 | if (hp->ops->notifier_del) |
408 | irq = hp->irq; | 370 | hp->ops->notifier_del(hp, hp->data); |
409 | hp->irq_requested = 0; | ||
410 | 371 | ||
411 | /* We are done with the tty pointer now. */ | 372 | /* We are done with the tty pointer now. */ |
412 | hp->tty = NULL; | 373 | hp->tty = NULL; |
@@ -418,10 +379,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
418 | * waking periodically to check chars_in_buffer(). | 379 | * waking periodically to check chars_in_buffer(). |
419 | */ | 380 | */ |
420 | tty_wait_until_sent(tty, HVC_CLOSE_WAIT); | 381 | tty_wait_until_sent(tty, HVC_CLOSE_WAIT); |
421 | |||
422 | if (irq) | ||
423 | free_irq(irq, hp); | ||
424 | |||
425 | } else { | 382 | } else { |
426 | if (hp->count < 0) | 383 | if (hp->count < 0) |
427 | printk(KERN_ERR "hvc_close %X: oops, count is %d\n", | 384 | printk(KERN_ERR "hvc_close %X: oops, count is %d\n", |
@@ -436,7 +393,6 @@ static void hvc_hangup(struct tty_struct *tty) | |||
436 | { | 393 | { |
437 | struct hvc_struct *hp = tty->driver_data; | 394 | struct hvc_struct *hp = tty->driver_data; |
438 | unsigned long flags; | 395 | unsigned long flags; |
439 | int irq = 0; | ||
440 | int temp_open_count; | 396 | int temp_open_count; |
441 | 397 | ||
442 | if (!hp) | 398 | if (!hp) |
@@ -458,13 +414,12 @@ static void hvc_hangup(struct tty_struct *tty) | |||
458 | hp->count = 0; | 414 | hp->count = 0; |
459 | hp->n_outbuf = 0; | 415 | hp->n_outbuf = 0; |
460 | hp->tty = NULL; | 416 | hp->tty = NULL; |
461 | if (hp->irq_requested) | 417 | |
462 | /* Saved for use outside of spin_lock. */ | 418 | if (hp->ops->notifier_del) |
463 | irq = hp->irq; | 419 | hp->ops->notifier_del(hp, hp->data); |
464 | hp->irq_requested = 0; | 420 | |
465 | spin_unlock_irqrestore(&hp->lock, flags); | 421 | spin_unlock_irqrestore(&hp->lock, flags); |
466 | if (irq) | 422 | |
467 | free_irq(irq, hp); | ||
468 | while(temp_open_count) { | 423 | while(temp_open_count) { |
469 | --temp_open_count; | 424 | --temp_open_count; |
470 | kref_put(&hp->kref, destroy_hvc_struct); | 425 | kref_put(&hp->kref, destroy_hvc_struct); |
@@ -575,7 +530,7 @@ static u32 timeout = MIN_TIMEOUT; | |||
575 | #define HVC_POLL_READ 0x00000001 | 530 | #define HVC_POLL_READ 0x00000001 |
576 | #define HVC_POLL_WRITE 0x00000002 | 531 | #define HVC_POLL_WRITE 0x00000002 |
577 | 532 | ||
578 | static int hvc_poll(struct hvc_struct *hp) | 533 | int hvc_poll(struct hvc_struct *hp) |
579 | { | 534 | { |
580 | struct tty_struct *tty; | 535 | struct tty_struct *tty; |
581 | int i, n, poll_mask = 0; | 536 | int i, n, poll_mask = 0; |
@@ -602,10 +557,10 @@ static int hvc_poll(struct hvc_struct *hp) | |||
602 | if (test_bit(TTY_THROTTLED, &tty->flags)) | 557 | if (test_bit(TTY_THROTTLED, &tty->flags)) |
603 | goto throttled; | 558 | goto throttled; |
604 | 559 | ||
605 | /* If we aren't interrupt driven and aren't throttled, we always | 560 | /* If we aren't notifier driven and aren't throttled, we always |
606 | * request a reschedule | 561 | * request a reschedule |
607 | */ | 562 | */ |
608 | if (hp->irq == 0) | 563 | if (!hp->irq_requested) |
609 | poll_mask |= HVC_POLL_READ; | 564 | poll_mask |= HVC_POLL_READ; |
610 | 565 | ||
611 | /* Read data if any */ | 566 | /* Read data if any */ |
@@ -733,7 +688,7 @@ static const struct tty_operations hvc_ops = { | |||
733 | .chars_in_buffer = hvc_chars_in_buffer, | 688 | .chars_in_buffer = hvc_chars_in_buffer, |
734 | }; | 689 | }; |
735 | 690 | ||
736 | struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | 691 | struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, |
737 | struct hv_ops *ops, int outbuf_size) | 692 | struct hv_ops *ops, int outbuf_size) |
738 | { | 693 | { |
739 | struct hvc_struct *hp; | 694 | struct hvc_struct *hp; |
@@ -754,7 +709,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | |||
754 | memset(hp, 0x00, sizeof(*hp)); | 709 | memset(hp, 0x00, sizeof(*hp)); |
755 | 710 | ||
756 | hp->vtermno = vtermno; | 711 | hp->vtermno = vtermno; |
757 | hp->irq = irq; | 712 | hp->data = data; |
758 | hp->ops = ops; | 713 | hp->ops = ops; |
759 | hp->outbuf_size = outbuf_size; | 714 | hp->outbuf_size = outbuf_size; |
760 | hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; | 715 | hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; |
diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h index 42ffb17e15df..d9ce10915625 100644 --- a/drivers/char/hvc_console.h +++ b/drivers/char/hvc_console.h | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #ifndef HVC_CONSOLE_H | 27 | #ifndef HVC_CONSOLE_H |
28 | #define HVC_CONSOLE_H | 28 | #define HVC_CONSOLE_H |
29 | #include <linux/kref.h> | ||
29 | 30 | ||
30 | /* | 31 | /* |
31 | * This is the max number of console adapters that can/will be found as | 32 | * This is the max number of console adapters that can/will be found as |
@@ -42,24 +43,50 @@ | |||
42 | */ | 43 | */ |
43 | #define HVC_ALLOC_TTY_ADAPTERS 8 | 44 | #define HVC_ALLOC_TTY_ADAPTERS 8 |
44 | 45 | ||
46 | struct hvc_struct { | ||
47 | spinlock_t lock; | ||
48 | int index; | ||
49 | struct tty_struct *tty; | ||
50 | unsigned int count; | ||
51 | int do_wakeup; | ||
52 | char *outbuf; | ||
53 | int outbuf_size; | ||
54 | int n_outbuf; | ||
55 | uint32_t vtermno; | ||
56 | struct hv_ops *ops; | ||
57 | int irq_requested; | ||
58 | int data; | ||
59 | struct list_head next; | ||
60 | struct kref kref; /* ref count & hvc_struct lifetime */ | ||
61 | }; | ||
45 | 62 | ||
46 | /* implemented by a low level driver */ | 63 | /* implemented by a low level driver */ |
47 | struct hv_ops { | 64 | struct hv_ops { |
48 | int (*get_chars)(uint32_t vtermno, char *buf, int count); | 65 | int (*get_chars)(uint32_t vtermno, char *buf, int count); |
49 | int (*put_chars)(uint32_t vtermno, const char *buf, int count); | 66 | int (*put_chars)(uint32_t vtermno, const char *buf, int count); |
50 | }; | ||
51 | 67 | ||
52 | struct hvc_struct; | 68 | /* Callbacks for notification. Called in open and close */ |
69 | int (*notifier_add)(struct hvc_struct *hp, int irq); | ||
70 | void (*notifier_del)(struct hvc_struct *hp, int irq); | ||
71 | }; | ||
53 | 72 | ||
54 | /* Register a vterm and a slot index for use as a console (console_init) */ | 73 | /* Register a vterm and a slot index for use as a console (console_init) */ |
55 | extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); | 74 | extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); |
56 | 75 | ||
57 | /* register a vterm for hvc tty operation (module_init or hotplug add) */ | 76 | /* register a vterm for hvc tty operation (module_init or hotplug add) */ |
58 | extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq, | 77 | extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int data, |
59 | struct hv_ops *ops, int outbuf_size); | 78 | struct hv_ops *ops, int outbuf_size); |
60 | /* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ | 79 | /* remove a vterm from hvc tty operation (module_exit or hotplug remove) */ |
61 | extern int __devexit hvc_remove(struct hvc_struct *hp); | 80 | extern int __devexit hvc_remove(struct hvc_struct *hp); |
62 | 81 | ||
82 | /* data available */ | ||
83 | int hvc_poll(struct hvc_struct *hp); | ||
84 | void hvc_kick(void); | ||
85 | |||
86 | /* default notifier for irq based notification */ | ||
87 | extern int notifier_add_irq(struct hvc_struct *hp, int data); | ||
88 | extern void notifier_del_irq(struct hvc_struct *hp, int data); | ||
89 | |||
63 | 90 | ||
64 | #if defined(CONFIG_XMON) && defined(CONFIG_SMP) | 91 | #if defined(CONFIG_XMON) && defined(CONFIG_SMP) |
65 | #include <asm/xmon.h> | 92 | #include <asm/xmon.h> |
diff --git a/drivers/char/hvc_irq.c b/drivers/char/hvc_irq.c new file mode 100644 index 000000000000..73a59cdb8947 --- /dev/null +++ b/drivers/char/hvc_irq.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corp. 2001,2008 | ||
3 | * | ||
4 | * This file contains the IRQ specific code for hvc_console | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/interrupt.h> | ||
9 | |||
10 | #include "hvc_console.h" | ||
11 | |||
12 | static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance) | ||
13 | { | ||
14 | /* if hvc_poll request a repoll, then kick the hvcd thread */ | ||
15 | if (hvc_poll(dev_instance)) | ||
16 | hvc_kick(); | ||
17 | return IRQ_HANDLED; | ||
18 | } | ||
19 | |||
20 | /* | ||
21 | * For IRQ based systems these callbacks can be used | ||
22 | */ | ||
23 | int notifier_add_irq(struct hvc_struct *hp, int irq) | ||
24 | { | ||
25 | int rc; | ||
26 | |||
27 | if (!irq) { | ||
28 | hp->irq_requested = 0; | ||
29 | return 0; | ||
30 | } | ||
31 | rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, | ||
32 | "hvc_console", hp); | ||
33 | if (!rc) | ||
34 | hp->irq_requested = 1; | ||
35 | return rc; | ||
36 | } | ||
37 | |||
38 | void notifier_del_irq(struct hvc_struct *hp, int irq) | ||
39 | { | ||
40 | if (!irq) | ||
41 | return; | ||
42 | free_irq(irq, hp); | ||
43 | hp->irq_requested = 0; | ||
44 | } | ||
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index a08f8f981c11..b71c610fe5ae 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c | |||
@@ -200,6 +200,8 @@ done: | |||
200 | static struct hv_ops hvc_get_put_ops = { | 200 | static struct hv_ops hvc_get_put_ops = { |
201 | .get_chars = get_chars, | 201 | .get_chars = get_chars, |
202 | .put_chars = put_chars, | 202 | .put_chars = put_chars, |
203 | .notifier_add = notifier_add_irq, | ||
204 | .notifier_del = notifier_del_irq, | ||
203 | }; | 205 | }; |
204 | 206 | ||
205 | static int __devinit hvc_vio_probe(struct vio_dev *vdev, | 207 | static int __devinit hvc_vio_probe(struct vio_dev *vdev, |
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index 79711aa4b41d..93f3840c1682 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c | |||
@@ -80,6 +80,8 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count) | |||
80 | static struct hv_ops hvc_get_put_ops = { | 80 | static struct hv_ops hvc_get_put_ops = { |
81 | .get_chars = filtered_get_chars, | 81 | .get_chars = filtered_get_chars, |
82 | .put_chars = hvc_put_chars, | 82 | .put_chars = hvc_put_chars, |
83 | .notifier_add = notifier_add_irq, | ||
84 | .notifier_del = notifier_del_irq, | ||
83 | }; | 85 | }; |
84 | 86 | ||
85 | static int __devinit hvc_vio_probe(struct vio_dev *vdev, | 87 | static int __devinit hvc_vio_probe(struct vio_dev *vdev, |
diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c index db2ae4216279..6b70aa66a587 100644 --- a/drivers/char/hvc_xen.c +++ b/drivers/char/hvc_xen.c | |||
@@ -100,6 +100,8 @@ static int read_console(uint32_t vtermno, char *buf, int len) | |||
100 | static struct hv_ops hvc_ops = { | 100 | static struct hv_ops hvc_ops = { |
101 | .get_chars = read_console, | 101 | .get_chars = read_console, |
102 | .put_chars = write_console, | 102 | .put_chars = write_console, |
103 | .notifier_add = notifier_add_irq, | ||
104 | .notifier_del = notifier_del_irq, | ||
103 | }; | 105 | }; |
104 | 106 | ||
105 | static int __init xen_init(void) | 107 | static int __init xen_init(void) |