diff options
| -rw-r--r-- | drivers/tty/serial/kgdb_nmi.c | 30 |
1 files changed, 9 insertions, 21 deletions
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c index d51b2a1ba909..20d21d09ee86 100644 --- a/drivers/tty/serial/kgdb_nmi.c +++ b/drivers/tty/serial/kgdb_nmi.c | |||
| @@ -80,24 +80,10 @@ static struct console kgdb_nmi_console = { | |||
| 80 | 80 | ||
| 81 | struct kgdb_nmi_tty_priv { | 81 | struct kgdb_nmi_tty_priv { |
| 82 | struct tty_port port; | 82 | struct tty_port port; |
| 83 | struct tasklet_struct tlet; | 83 | struct timer_list timer; |
| 84 | STRUCT_KFIFO(char, KGDB_NMI_FIFO_SIZE) fifo; | 84 | STRUCT_KFIFO(char, KGDB_NMI_FIFO_SIZE) fifo; |
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | /* | ||
| 88 | * Our debugging console is polled in a tasklet, so we'll check for input | ||
| 89 | * every tick. In HZ-less mode, we should program the next tick. We have | ||
| 90 | * to use the lowlevel stuff as no locks should be grabbed. | ||
| 91 | */ | ||
| 92 | #ifdef CONFIG_HIGH_RES_TIMERS | ||
| 93 | static void kgdb_tty_poke(void) | ||
| 94 | { | ||
| 95 | tick_program_event(ktime_get(), 0); | ||
| 96 | } | ||
| 97 | #else | ||
| 98 | static inline void kgdb_tty_poke(void) {} | ||
| 99 | #endif | ||
| 100 | |||
| 101 | static struct tty_port *kgdb_nmi_port; | 87 | static struct tty_port *kgdb_nmi_port; |
| 102 | 88 | ||
| 103 | static void kgdb_tty_recv(int ch) | 89 | static void kgdb_tty_recv(int ch) |
| @@ -108,14 +94,13 @@ static void kgdb_tty_recv(int ch) | |||
| 108 | if (!kgdb_nmi_port || ch < 0) | 94 | if (!kgdb_nmi_port || ch < 0) |
| 109 | return; | 95 | return; |
| 110 | /* | 96 | /* |
| 111 | * Can't use port->tty->driver_data as tty might be not there. Tasklet | 97 | * Can't use port->tty->driver_data as tty might be not there. Timer |
| 112 | * will check for tty and will get the ref, but here we don't have to | 98 | * will check for tty and will get the ref, but here we don't have to |
| 113 | * do that, and actually, we can't: we're in NMI context, no locks are | 99 | * do that, and actually, we can't: we're in NMI context, no locks are |
| 114 | * possible. | 100 | * possible. |
| 115 | */ | 101 | */ |
| 116 | priv = container_of(kgdb_nmi_port, struct kgdb_nmi_tty_priv, port); | 102 | priv = container_of(kgdb_nmi_port, struct kgdb_nmi_tty_priv, port); |
| 117 | kfifo_in(&priv->fifo, &c, 1); | 103 | kfifo_in(&priv->fifo, &c, 1); |
| 118 | kgdb_tty_poke(); | ||
| 119 | } | 104 | } |
| 120 | 105 | ||
| 121 | static int kgdb_nmi_poll_one_knock(void) | 106 | static int kgdb_nmi_poll_one_knock(void) |
| @@ -199,7 +184,8 @@ static void kgdb_nmi_tty_receiver(unsigned long data) | |||
| 199 | struct kgdb_nmi_tty_priv *priv = (void *)data; | 184 | struct kgdb_nmi_tty_priv *priv = (void *)data; |
| 200 | char ch; | 185 | char ch; |
| 201 | 186 | ||
| 202 | tasklet_schedule(&priv->tlet); | 187 | priv->timer.expires = jiffies + (HZ/100); |
| 188 | add_timer(&priv->timer); | ||
| 203 | 189 | ||
| 204 | if (likely(!kgdb_nmi_tty_enabled || !kfifo_len(&priv->fifo))) | 190 | if (likely(!kgdb_nmi_tty_enabled || !kfifo_len(&priv->fifo))) |
| 205 | return; | 191 | return; |
| @@ -215,7 +201,9 @@ static int kgdb_nmi_tty_activate(struct tty_port *port, struct tty_struct *tty) | |||
| 215 | container_of(port, struct kgdb_nmi_tty_priv, port); | 201 | container_of(port, struct kgdb_nmi_tty_priv, port); |
| 216 | 202 | ||
| 217 | kgdb_nmi_port = port; | 203 | kgdb_nmi_port = port; |
| 218 | tasklet_schedule(&priv->tlet); | 204 | priv->timer.expires = jiffies + (HZ/100); |
| 205 | add_timer(&priv->timer); | ||
| 206 | |||
| 219 | return 0; | 207 | return 0; |
| 220 | } | 208 | } |
| 221 | 209 | ||
| @@ -224,7 +212,7 @@ static void kgdb_nmi_tty_shutdown(struct tty_port *port) | |||
| 224 | struct kgdb_nmi_tty_priv *priv = | 212 | struct kgdb_nmi_tty_priv *priv = |
| 225 | container_of(port, struct kgdb_nmi_tty_priv, port); | 213 | container_of(port, struct kgdb_nmi_tty_priv, port); |
| 226 | 214 | ||
| 227 | tasklet_kill(&priv->tlet); | 215 | del_timer(&priv->timer); |
| 228 | kgdb_nmi_port = NULL; | 216 | kgdb_nmi_port = NULL; |
| 229 | } | 217 | } |
| 230 | 218 | ||
| @@ -243,7 +231,7 @@ static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty) | |||
| 243 | return -ENOMEM; | 231 | return -ENOMEM; |
| 244 | 232 | ||
| 245 | INIT_KFIFO(priv->fifo); | 233 | INIT_KFIFO(priv->fifo); |
| 246 | tasklet_init(&priv->tlet, kgdb_nmi_tty_receiver, (unsigned long)priv); | 234 | setup_timer(&priv->timer, kgdb_nmi_tty_receiver, (unsigned long)priv); |
| 247 | tty_port_init(&priv->port); | 235 | tty_port_init(&priv->port); |
| 248 | priv->port.ops = &kgdb_nmi_tty_port_ops; | 236 | priv->port.ops = &kgdb_nmi_tty_port_ops; |
| 249 | tty->driver_data = priv; | 237 | tty->driver_data = priv; |
