diff options
Diffstat (limited to 'net/irda')
-rw-r--r-- | net/irda/ircomm/ircomm_param.c | 5 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_tty.c | 281 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_tty_attach.c | 40 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_tty_ioctl.c | 33 |
4 files changed, 176 insertions, 183 deletions
diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c index 8b915f3ac3b9..308939128359 100644 --- a/net/irda/ircomm/ircomm_param.c +++ b/net/irda/ircomm/ircomm_param.c | |||
@@ -99,7 +99,6 @@ pi_param_info_t ircomm_param_info = { pi_major_call_table, 3, 0x0f, 4 }; | |||
99 | */ | 99 | */ |
100 | int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) | 100 | int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) |
101 | { | 101 | { |
102 | struct tty_struct *tty; | ||
103 | unsigned long flags; | 102 | unsigned long flags; |
104 | struct sk_buff *skb; | 103 | struct sk_buff *skb; |
105 | int count; | 104 | int count; |
@@ -109,10 +108,6 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) | |||
109 | IRDA_ASSERT(self != NULL, return -1;); | 108 | IRDA_ASSERT(self != NULL, return -1;); |
110 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); | 109 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); |
111 | 110 | ||
112 | tty = self->tty; | ||
113 | if (!tty) | ||
114 | return 0; | ||
115 | |||
116 | /* Make sure we don't send parameters for raw mode */ | 111 | /* Make sure we don't send parameters for raw mode */ |
117 | if (self->service_type == IRCOMM_3_WIRE_RAW) | 112 | if (self->service_type == IRCOMM_3_WIRE_RAW) |
118 | return 0; | 113 | return 0; |
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 6b9d5a0e42f9..7a0d6115d06f 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c | |||
@@ -104,6 +104,35 @@ static const struct tty_operations ops = { | |||
104 | #endif /* CONFIG_PROC_FS */ | 104 | #endif /* CONFIG_PROC_FS */ |
105 | }; | 105 | }; |
106 | 106 | ||
107 | static void ircomm_port_raise_dtr_rts(struct tty_port *port, int raise) | ||
108 | { | ||
109 | struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb, | ||
110 | port); | ||
111 | /* | ||
112 | * Here, we use to lock those two guys, but as ircomm_param_request() | ||
113 | * does it itself, I don't see the point (and I see the deadlock). | ||
114 | * Jean II | ||
115 | */ | ||
116 | if (raise) | ||
117 | self->settings.dte |= IRCOMM_RTS | IRCOMM_DTR; | ||
118 | else | ||
119 | self->settings.dte &= ~(IRCOMM_RTS | IRCOMM_DTR); | ||
120 | |||
121 | ircomm_param_request(self, IRCOMM_DTE, TRUE); | ||
122 | } | ||
123 | |||
124 | static int ircomm_port_carrier_raised(struct tty_port *port) | ||
125 | { | ||
126 | struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb, | ||
127 | port); | ||
128 | return self->settings.dce & IRCOMM_CD; | ||
129 | } | ||
130 | |||
131 | static const struct tty_port_operations ircomm_port_ops = { | ||
132 | .dtr_rts = ircomm_port_raise_dtr_rts, | ||
133 | .carrier_raised = ircomm_port_carrier_raised, | ||
134 | }; | ||
135 | |||
107 | /* | 136 | /* |
108 | * Function ircomm_tty_init() | 137 | * Function ircomm_tty_init() |
109 | * | 138 | * |
@@ -194,7 +223,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self) | |||
194 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); | 223 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); |
195 | 224 | ||
196 | /* Check if already open */ | 225 | /* Check if already open */ |
197 | if (test_and_set_bit(ASYNC_B_INITIALIZED, &self->flags)) { | 226 | if (test_and_set_bit(ASYNCB_INITIALIZED, &self->port.flags)) { |
198 | IRDA_DEBUG(2, "%s(), already open so break out!\n", __func__ ); | 227 | IRDA_DEBUG(2, "%s(), already open so break out!\n", __func__ ); |
199 | return 0; | 228 | return 0; |
200 | } | 229 | } |
@@ -231,7 +260,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self) | |||
231 | 260 | ||
232 | return 0; | 261 | return 0; |
233 | err: | 262 | err: |
234 | clear_bit(ASYNC_B_INITIALIZED, &self->flags); | 263 | clear_bit(ASYNCB_INITIALIZED, &self->port.flags); |
235 | return ret; | 264 | return ret; |
236 | } | 265 | } |
237 | 266 | ||
@@ -242,72 +271,62 @@ err: | |||
242 | * | 271 | * |
243 | */ | 272 | */ |
244 | static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, | 273 | static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, |
245 | struct file *filp) | 274 | struct tty_struct *tty, struct file *filp) |
246 | { | 275 | { |
276 | struct tty_port *port = &self->port; | ||
247 | DECLARE_WAITQUEUE(wait, current); | 277 | DECLARE_WAITQUEUE(wait, current); |
248 | int retval; | 278 | int retval; |
249 | int do_clocal = 0, extra_count = 0; | 279 | int do_clocal = 0, extra_count = 0; |
250 | unsigned long flags; | 280 | unsigned long flags; |
251 | struct tty_struct *tty; | ||
252 | 281 | ||
253 | IRDA_DEBUG(2, "%s()\n", __func__ ); | 282 | IRDA_DEBUG(2, "%s()\n", __func__ ); |
254 | 283 | ||
255 | tty = self->tty; | ||
256 | |||
257 | /* | 284 | /* |
258 | * If non-blocking mode is set, or the port is not enabled, | 285 | * If non-blocking mode is set, or the port is not enabled, |
259 | * then make the check up front and then exit. | 286 | * then make the check up front and then exit. |
260 | */ | 287 | */ |
261 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ | 288 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ |
262 | /* nonblock mode is set or port is not enabled */ | 289 | /* nonblock mode is set or port is not enabled */ |
263 | self->flags |= ASYNC_NORMAL_ACTIVE; | 290 | port->flags |= ASYNC_NORMAL_ACTIVE; |
264 | IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ ); | 291 | IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ ); |
265 | return 0; | 292 | return 0; |
266 | } | 293 | } |
267 | 294 | ||
268 | if (tty->termios->c_cflag & CLOCAL) { | 295 | if (tty->termios.c_cflag & CLOCAL) { |
269 | IRDA_DEBUG(1, "%s(), doing CLOCAL!\n", __func__ ); | 296 | IRDA_DEBUG(1, "%s(), doing CLOCAL!\n", __func__ ); |
270 | do_clocal = 1; | 297 | do_clocal = 1; |
271 | } | 298 | } |
272 | 299 | ||
273 | /* Wait for carrier detect and the line to become | 300 | /* Wait for carrier detect and the line to become |
274 | * free (i.e., not in use by the callout). While we are in | 301 | * free (i.e., not in use by the callout). While we are in |
275 | * this loop, self->open_count is dropped by one, so that | 302 | * this loop, port->count is dropped by one, so that |
276 | * mgsl_close() knows when to free things. We restore it upon | 303 | * mgsl_close() knows when to free things. We restore it upon |
277 | * exit, either normal or abnormal. | 304 | * exit, either normal or abnormal. |
278 | */ | 305 | */ |
279 | 306 | ||
280 | retval = 0; | 307 | retval = 0; |
281 | add_wait_queue(&self->open_wait, &wait); | 308 | add_wait_queue(&port->open_wait, &wait); |
282 | 309 | ||
283 | IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n", | 310 | IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n", |
284 | __FILE__,__LINE__, tty->driver->name, self->open_count ); | 311 | __FILE__, __LINE__, tty->driver->name, port->count); |
285 | 312 | ||
286 | /* As far as I can see, we protect open_count - Jean II */ | 313 | spin_lock_irqsave(&port->lock, flags); |
287 | spin_lock_irqsave(&self->spinlock, flags); | ||
288 | if (!tty_hung_up_p(filp)) { | 314 | if (!tty_hung_up_p(filp)) { |
289 | extra_count = 1; | 315 | extra_count = 1; |
290 | self->open_count--; | 316 | port->count--; |
291 | } | 317 | } |
292 | spin_unlock_irqrestore(&self->spinlock, flags); | 318 | spin_unlock_irqrestore(&port->lock, flags); |
293 | self->blocked_open++; | 319 | port->blocked_open++; |
294 | 320 | ||
295 | while (1) { | 321 | while (1) { |
296 | if (tty->termios->c_cflag & CBAUD) { | 322 | if (tty->termios.c_cflag & CBAUD) |
297 | /* Here, we use to lock those two guys, but | 323 | tty_port_raise_dtr_rts(port); |
298 | * as ircomm_param_request() does it itself, | ||
299 | * I don't see the point (and I see the deadlock). | ||
300 | * Jean II */ | ||
301 | self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR; | ||
302 | |||
303 | ircomm_param_request(self, IRCOMM_DTE, TRUE); | ||
304 | } | ||
305 | 324 | ||
306 | current->state = TASK_INTERRUPTIBLE; | 325 | current->state = TASK_INTERRUPTIBLE; |
307 | 326 | ||
308 | if (tty_hung_up_p(filp) || | 327 | if (tty_hung_up_p(filp) || |
309 | !test_bit(ASYNC_B_INITIALIZED, &self->flags)) { | 328 | !test_bit(ASYNCB_INITIALIZED, &port->flags)) { |
310 | retval = (self->flags & ASYNC_HUP_NOTIFY) ? | 329 | retval = (port->flags & ASYNC_HUP_NOTIFY) ? |
311 | -EAGAIN : -ERESTARTSYS; | 330 | -EAGAIN : -ERESTARTSYS; |
312 | break; | 331 | break; |
313 | } | 332 | } |
@@ -317,8 +336,8 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, | |||
317 | * specified, we cannot return before the IrCOMM link is | 336 | * specified, we cannot return before the IrCOMM link is |
318 | * ready | 337 | * ready |
319 | */ | 338 | */ |
320 | if (!test_bit(ASYNC_B_CLOSING, &self->flags) && | 339 | if (!test_bit(ASYNCB_CLOSING, &port->flags) && |
321 | (do_clocal || (self->settings.dce & IRCOMM_CD)) && | 340 | (do_clocal || tty_port_carrier_raised(port)) && |
322 | self->state == IRCOMM_TTY_READY) | 341 | self->state == IRCOMM_TTY_READY) |
323 | { | 342 | { |
324 | break; | 343 | break; |
@@ -330,27 +349,27 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, | |||
330 | } | 349 | } |
331 | 350 | ||
332 | IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n", | 351 | IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n", |
333 | __FILE__,__LINE__, tty->driver->name, self->open_count ); | 352 | __FILE__, __LINE__, tty->driver->name, port->count); |
334 | 353 | ||
335 | schedule(); | 354 | schedule(); |
336 | } | 355 | } |
337 | 356 | ||
338 | __set_current_state(TASK_RUNNING); | 357 | __set_current_state(TASK_RUNNING); |
339 | remove_wait_queue(&self->open_wait, &wait); | 358 | remove_wait_queue(&port->open_wait, &wait); |
340 | 359 | ||
341 | if (extra_count) { | 360 | if (extra_count) { |
342 | /* ++ is not atomic, so this should be protected - Jean II */ | 361 | /* ++ is not atomic, so this should be protected - Jean II */ |
343 | spin_lock_irqsave(&self->spinlock, flags); | 362 | spin_lock_irqsave(&port->lock, flags); |
344 | self->open_count++; | 363 | port->count++; |
345 | spin_unlock_irqrestore(&self->spinlock, flags); | 364 | spin_unlock_irqrestore(&port->lock, flags); |
346 | } | 365 | } |
347 | self->blocked_open--; | 366 | port->blocked_open--; |
348 | 367 | ||
349 | IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n", | 368 | IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n", |
350 | __FILE__,__LINE__, tty->driver->name, self->open_count); | 369 | __FILE__, __LINE__, tty->driver->name, port->count); |
351 | 370 | ||
352 | if (!retval) | 371 | if (!retval) |
353 | self->flags |= ASYNC_NORMAL_ACTIVE; | 372 | port->flags |= ASYNC_NORMAL_ACTIVE; |
354 | 373 | ||
355 | return retval; | 374 | return retval; |
356 | } | 375 | } |
@@ -381,6 +400,8 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
381 | return -ENOMEM; | 400 | return -ENOMEM; |
382 | } | 401 | } |
383 | 402 | ||
403 | tty_port_init(&self->port); | ||
404 | self->port.ops = &ircomm_port_ops; | ||
384 | self->magic = IRCOMM_TTY_MAGIC; | 405 | self->magic = IRCOMM_TTY_MAGIC; |
385 | self->flow = FLOW_STOP; | 406 | self->flow = FLOW_STOP; |
386 | 407 | ||
@@ -388,13 +409,9 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
388 | INIT_WORK(&self->tqueue, ircomm_tty_do_softint); | 409 | INIT_WORK(&self->tqueue, ircomm_tty_do_softint); |
389 | self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED; | 410 | self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED; |
390 | self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED; | 411 | self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED; |
391 | self->close_delay = 5*HZ/10; | ||
392 | self->closing_wait = 30*HZ; | ||
393 | 412 | ||
394 | /* Init some important stuff */ | 413 | /* Init some important stuff */ |
395 | init_timer(&self->watchdog_timer); | 414 | init_timer(&self->watchdog_timer); |
396 | init_waitqueue_head(&self->open_wait); | ||
397 | init_waitqueue_head(&self->close_wait); | ||
398 | spin_lock_init(&self->spinlock); | 415 | spin_lock_init(&self->spinlock); |
399 | 416 | ||
400 | /* | 417 | /* |
@@ -404,31 +421,32 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
404 | * | 421 | * |
405 | * Note this is completely usafe and doesn't work properly | 422 | * Note this is completely usafe and doesn't work properly |
406 | */ | 423 | */ |
407 | tty->termios->c_iflag = 0; | 424 | tty->termios.c_iflag = 0; |
408 | tty->termios->c_oflag = 0; | 425 | tty->termios.c_oflag = 0; |
409 | 426 | ||
410 | /* Insert into hash */ | 427 | /* Insert into hash */ |
428 | /* FIXME there is a window from find to here */ | ||
411 | hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL); | 429 | hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL); |
412 | } | 430 | } |
413 | /* ++ is not atomic, so this should be protected - Jean II */ | 431 | /* ++ is not atomic, so this should be protected - Jean II */ |
414 | spin_lock_irqsave(&self->spinlock, flags); | 432 | spin_lock_irqsave(&self->port.lock, flags); |
415 | self->open_count++; | 433 | self->port.count++; |
416 | 434 | ||
417 | tty->driver_data = self; | 435 | tty->driver_data = self; |
418 | self->tty = tty; | 436 | spin_unlock_irqrestore(&self->port.lock, flags); |
419 | spin_unlock_irqrestore(&self->spinlock, flags); | 437 | tty_port_tty_set(&self->port, tty); |
420 | 438 | ||
421 | IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name, | 439 | IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name, |
422 | self->line, self->open_count); | 440 | self->line, self->port.count); |
423 | 441 | ||
424 | /* Not really used by us, but lets do it anyway */ | 442 | /* Not really used by us, but lets do it anyway */ |
425 | self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 443 | tty->low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
426 | 444 | ||
427 | /* | 445 | /* |
428 | * If the port is the middle of closing, bail out now | 446 | * If the port is the middle of closing, bail out now |
429 | */ | 447 | */ |
430 | if (tty_hung_up_p(filp) || | 448 | if (tty_hung_up_p(filp) || |
431 | test_bit(ASYNC_B_CLOSING, &self->flags)) { | 449 | test_bit(ASYNCB_CLOSING, &self->port.flags)) { |
432 | 450 | ||
433 | /* Hm, why are we blocking on ASYNC_CLOSING if we | 451 | /* Hm, why are we blocking on ASYNC_CLOSING if we |
434 | * do return -EAGAIN/-ERESTARTSYS below anyway? | 452 | * do return -EAGAIN/-ERESTARTSYS below anyway? |
@@ -438,14 +456,15 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
438 | * probably better sleep uninterruptible? | 456 | * probably better sleep uninterruptible? |
439 | */ | 457 | */ |
440 | 458 | ||
441 | if (wait_event_interruptible(self->close_wait, !test_bit(ASYNC_B_CLOSING, &self->flags))) { | 459 | if (wait_event_interruptible(self->port.close_wait, |
460 | !test_bit(ASYNCB_CLOSING, &self->port.flags))) { | ||
442 | IRDA_WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n", | 461 | IRDA_WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n", |
443 | __func__); | 462 | __func__); |
444 | return -ERESTARTSYS; | 463 | return -ERESTARTSYS; |
445 | } | 464 | } |
446 | 465 | ||
447 | #ifdef SERIAL_DO_RESTART | 466 | #ifdef SERIAL_DO_RESTART |
448 | return (self->flags & ASYNC_HUP_NOTIFY) ? | 467 | return (self->port.flags & ASYNC_HUP_NOTIFY) ? |
449 | -EAGAIN : -ERESTARTSYS; | 468 | -EAGAIN : -ERESTARTSYS; |
450 | #else | 469 | #else |
451 | return -EAGAIN; | 470 | return -EAGAIN; |
@@ -469,7 +488,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
469 | if (ret) | 488 | if (ret) |
470 | return ret; | 489 | return ret; |
471 | 490 | ||
472 | ret = ircomm_tty_block_til_ready(self, filp); | 491 | ret = ircomm_tty_block_til_ready(self, tty, filp); |
473 | if (ret) { | 492 | if (ret) { |
474 | IRDA_DEBUG(2, | 493 | IRDA_DEBUG(2, |
475 | "%s(), returning after block_til_ready with %d\n", __func__ , | 494 | "%s(), returning after block_til_ready with %d\n", __func__ , |
@@ -489,81 +508,22 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
489 | static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) | 508 | static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) |
490 | { | 509 | { |
491 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; | 510 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; |
492 | unsigned long flags; | 511 | struct tty_port *port = &self->port; |
493 | 512 | ||
494 | IRDA_DEBUG(0, "%s()\n", __func__ ); | 513 | IRDA_DEBUG(0, "%s()\n", __func__ ); |
495 | 514 | ||
496 | IRDA_ASSERT(self != NULL, return;); | 515 | IRDA_ASSERT(self != NULL, return;); |
497 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); | 516 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); |
498 | 517 | ||
499 | spin_lock_irqsave(&self->spinlock, flags); | 518 | if (tty_port_close_start(port, tty, filp) == 0) |
500 | |||
501 | if (tty_hung_up_p(filp)) { | ||
502 | spin_unlock_irqrestore(&self->spinlock, flags); | ||
503 | |||
504 | IRDA_DEBUG(0, "%s(), returning 1\n", __func__ ); | ||
505 | return; | ||
506 | } | ||
507 | |||
508 | if ((tty->count == 1) && (self->open_count != 1)) { | ||
509 | /* | ||
510 | * Uh, oh. tty->count is 1, which means that the tty | ||
511 | * structure will be freed. state->count should always | ||
512 | * be one in these conditions. If it's greater than | ||
513 | * one, we've got real problems, since it means the | ||
514 | * serial port won't be shutdown. | ||
515 | */ | ||
516 | IRDA_DEBUG(0, "%s(), bad serial port count; " | ||
517 | "tty->count is 1, state->count is %d\n", __func__ , | ||
518 | self->open_count); | ||
519 | self->open_count = 1; | ||
520 | } | ||
521 | |||
522 | if (--self->open_count < 0) { | ||
523 | IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n", | ||
524 | __func__, self->line, self->open_count); | ||
525 | self->open_count = 0; | ||
526 | } | ||
527 | if (self->open_count) { | ||
528 | spin_unlock_irqrestore(&self->spinlock, flags); | ||
529 | |||
530 | IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ ); | ||
531 | return; | 519 | return; |
532 | } | ||
533 | |||
534 | /* Hum... Should be test_and_set_bit ??? - Jean II */ | ||
535 | set_bit(ASYNC_B_CLOSING, &self->flags); | ||
536 | |||
537 | /* We need to unlock here (we were unlocking at the end of this | ||
538 | * function), because tty_wait_until_sent() may schedule. | ||
539 | * I don't know if the rest should be protected somehow, | ||
540 | * so someone should check. - Jean II */ | ||
541 | spin_unlock_irqrestore(&self->spinlock, flags); | ||
542 | |||
543 | /* | ||
544 | * Now we wait for the transmit buffer to clear; and we notify | ||
545 | * the line discipline to only process XON/XOFF characters. | ||
546 | */ | ||
547 | tty->closing = 1; | ||
548 | if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
549 | tty_wait_until_sent_from_close(tty, self->closing_wait); | ||
550 | 520 | ||
551 | ircomm_tty_shutdown(self); | 521 | ircomm_tty_shutdown(self); |
552 | 522 | ||
553 | tty_driver_flush_buffer(tty); | 523 | tty_driver_flush_buffer(tty); |
554 | tty_ldisc_flush(tty); | ||
555 | 524 | ||
556 | tty->closing = 0; | 525 | tty_port_close_end(port, tty); |
557 | self->tty = NULL; | 526 | tty_port_tty_set(port, NULL); |
558 | |||
559 | if (self->blocked_open) { | ||
560 | if (self->close_delay) | ||
561 | schedule_timeout_interruptible(self->close_delay); | ||
562 | wake_up_interruptible(&self->open_wait); | ||
563 | } | ||
564 | |||
565 | self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
566 | wake_up_interruptible(&self->close_wait); | ||
567 | } | 527 | } |
568 | 528 | ||
569 | /* | 529 | /* |
@@ -606,7 +566,7 @@ static void ircomm_tty_do_softint(struct work_struct *work) | |||
606 | if (!self || self->magic != IRCOMM_TTY_MAGIC) | 566 | if (!self || self->magic != IRCOMM_TTY_MAGIC) |
607 | return; | 567 | return; |
608 | 568 | ||
609 | tty = self->tty; | 569 | tty = tty_port_tty_get(&self->port); |
610 | if (!tty) | 570 | if (!tty) |
611 | return; | 571 | return; |
612 | 572 | ||
@@ -627,7 +587,7 @@ static void ircomm_tty_do_softint(struct work_struct *work) | |||
627 | } | 587 | } |
628 | 588 | ||
629 | if (tty->hw_stopped) | 589 | if (tty->hw_stopped) |
630 | return; | 590 | goto put; |
631 | 591 | ||
632 | /* Unlink transmit buffer */ | 592 | /* Unlink transmit buffer */ |
633 | spin_lock_irqsave(&self->spinlock, flags); | 593 | spin_lock_irqsave(&self->spinlock, flags); |
@@ -646,6 +606,8 @@ static void ircomm_tty_do_softint(struct work_struct *work) | |||
646 | 606 | ||
647 | /* Check if user (still) wants to be waken up */ | 607 | /* Check if user (still) wants to be waken up */ |
648 | tty_wakeup(tty); | 608 | tty_wakeup(tty); |
609 | put: | ||
610 | tty_kref_put(tty); | ||
649 | } | 611 | } |
650 | 612 | ||
651 | /* | 613 | /* |
@@ -880,7 +842,7 @@ static void ircomm_tty_throttle(struct tty_struct *tty) | |||
880 | ircomm_tty_send_xchar(tty, STOP_CHAR(tty)); | 842 | ircomm_tty_send_xchar(tty, STOP_CHAR(tty)); |
881 | 843 | ||
882 | /* Hardware flow control? */ | 844 | /* Hardware flow control? */ |
883 | if (tty->termios->c_cflag & CRTSCTS) { | 845 | if (tty->termios.c_cflag & CRTSCTS) { |
884 | self->settings.dte &= ~IRCOMM_RTS; | 846 | self->settings.dte &= ~IRCOMM_RTS; |
885 | self->settings.dte |= IRCOMM_DELTA_RTS; | 847 | self->settings.dte |= IRCOMM_DELTA_RTS; |
886 | 848 | ||
@@ -912,7 +874,7 @@ static void ircomm_tty_unthrottle(struct tty_struct *tty) | |||
912 | } | 874 | } |
913 | 875 | ||
914 | /* Using hardware flow control? */ | 876 | /* Using hardware flow control? */ |
915 | if (tty->termios->c_cflag & CRTSCTS) { | 877 | if (tty->termios.c_cflag & CRTSCTS) { |
916 | self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS); | 878 | self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS); |
917 | 879 | ||
918 | ircomm_param_request(self, IRCOMM_DTE, TRUE); | 880 | ircomm_param_request(self, IRCOMM_DTE, TRUE); |
@@ -955,7 +917,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self) | |||
955 | 917 | ||
956 | IRDA_DEBUG(0, "%s()\n", __func__ ); | 918 | IRDA_DEBUG(0, "%s()\n", __func__ ); |
957 | 919 | ||
958 | if (!test_and_clear_bit(ASYNC_B_INITIALIZED, &self->flags)) | 920 | if (!test_and_clear_bit(ASYNCB_INITIALIZED, &self->port.flags)) |
959 | return; | 921 | return; |
960 | 922 | ||
961 | ircomm_tty_detach_cable(self); | 923 | ircomm_tty_detach_cable(self); |
@@ -994,6 +956,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self) | |||
994 | static void ircomm_tty_hangup(struct tty_struct *tty) | 956 | static void ircomm_tty_hangup(struct tty_struct *tty) |
995 | { | 957 | { |
996 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; | 958 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; |
959 | struct tty_port *port = &self->port; | ||
997 | unsigned long flags; | 960 | unsigned long flags; |
998 | 961 | ||
999 | IRDA_DEBUG(0, "%s()\n", __func__ ); | 962 | IRDA_DEBUG(0, "%s()\n", __func__ ); |
@@ -1004,14 +967,17 @@ static void ircomm_tty_hangup(struct tty_struct *tty) | |||
1004 | /* ircomm_tty_flush_buffer(tty); */ | 967 | /* ircomm_tty_flush_buffer(tty); */ |
1005 | ircomm_tty_shutdown(self); | 968 | ircomm_tty_shutdown(self); |
1006 | 969 | ||
1007 | /* I guess we need to lock here - Jean II */ | 970 | spin_lock_irqsave(&port->lock, flags); |
1008 | spin_lock_irqsave(&self->spinlock, flags); | 971 | port->flags &= ~ASYNC_NORMAL_ACTIVE; |
1009 | self->flags &= ~ASYNC_NORMAL_ACTIVE; | 972 | if (port->tty) { |
1010 | self->tty = NULL; | 973 | set_bit(TTY_IO_ERROR, &port->tty->flags); |
1011 | self->open_count = 0; | 974 | tty_kref_put(port->tty); |
1012 | spin_unlock_irqrestore(&self->spinlock, flags); | 975 | } |
976 | port->tty = NULL; | ||
977 | port->count = 0; | ||
978 | spin_unlock_irqrestore(&port->lock, flags); | ||
1013 | 979 | ||
1014 | wake_up_interruptible(&self->open_wait); | 980 | wake_up_interruptible(&port->open_wait); |
1015 | } | 981 | } |
1016 | 982 | ||
1017 | /* | 983 | /* |
@@ -1071,20 +1037,20 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) | |||
1071 | IRDA_ASSERT(self != NULL, return;); | 1037 | IRDA_ASSERT(self != NULL, return;); |
1072 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); | 1038 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); |
1073 | 1039 | ||
1074 | tty = self->tty; | 1040 | tty = tty_port_tty_get(&self->port); |
1075 | 1041 | ||
1076 | status = self->settings.dce; | 1042 | status = self->settings.dce; |
1077 | 1043 | ||
1078 | if (status & IRCOMM_DCE_DELTA_ANY) { | 1044 | if (status & IRCOMM_DCE_DELTA_ANY) { |
1079 | /*wake_up_interruptible(&self->delta_msr_wait);*/ | 1045 | /*wake_up_interruptible(&self->delta_msr_wait);*/ |
1080 | } | 1046 | } |
1081 | if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) { | 1047 | if ((self->port.flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) { |
1082 | IRDA_DEBUG(2, | 1048 | IRDA_DEBUG(2, |
1083 | "%s(), ircomm%d CD now %s...\n", __func__ , self->line, | 1049 | "%s(), ircomm%d CD now %s...\n", __func__ , self->line, |
1084 | (status & IRCOMM_CD) ? "on" : "off"); | 1050 | (status & IRCOMM_CD) ? "on" : "off"); |
1085 | 1051 | ||
1086 | if (status & IRCOMM_CD) { | 1052 | if (status & IRCOMM_CD) { |
1087 | wake_up_interruptible(&self->open_wait); | 1053 | wake_up_interruptible(&self->port.open_wait); |
1088 | } else { | 1054 | } else { |
1089 | IRDA_DEBUG(2, | 1055 | IRDA_DEBUG(2, |
1090 | "%s(), Doing serial hangup..\n", __func__ ); | 1056 | "%s(), Doing serial hangup..\n", __func__ ); |
@@ -1092,10 +1058,10 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) | |||
1092 | tty_hangup(tty); | 1058 | tty_hangup(tty); |
1093 | 1059 | ||
1094 | /* Hangup will remote the tty, so better break out */ | 1060 | /* Hangup will remote the tty, so better break out */ |
1095 | return; | 1061 | goto put; |
1096 | } | 1062 | } |
1097 | } | 1063 | } |
1098 | if (self->flags & ASYNC_CTS_FLOW) { | 1064 | if (tty && self->port.flags & ASYNC_CTS_FLOW) { |
1099 | if (tty->hw_stopped) { | 1065 | if (tty->hw_stopped) { |
1100 | if (status & IRCOMM_CTS) { | 1066 | if (status & IRCOMM_CTS) { |
1101 | IRDA_DEBUG(2, | 1067 | IRDA_DEBUG(2, |
@@ -1103,10 +1069,10 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) | |||
1103 | tty->hw_stopped = 0; | 1069 | tty->hw_stopped = 0; |
1104 | 1070 | ||
1105 | /* Wake up processes blocked on open */ | 1071 | /* Wake up processes blocked on open */ |
1106 | wake_up_interruptible(&self->open_wait); | 1072 | wake_up_interruptible(&self->port.open_wait); |
1107 | 1073 | ||
1108 | schedule_work(&self->tqueue); | 1074 | schedule_work(&self->tqueue); |
1109 | return; | 1075 | goto put; |
1110 | } | 1076 | } |
1111 | } else { | 1077 | } else { |
1112 | if (!(status & IRCOMM_CTS)) { | 1078 | if (!(status & IRCOMM_CTS)) { |
@@ -1116,6 +1082,8 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) | |||
1116 | } | 1082 | } |
1117 | } | 1083 | } |
1118 | } | 1084 | } |
1085 | put: | ||
1086 | tty_kref_put(tty); | ||
1119 | } | 1087 | } |
1120 | 1088 | ||
1121 | /* | 1089 | /* |
@@ -1128,6 +1096,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap, | |||
1128 | struct sk_buff *skb) | 1096 | struct sk_buff *skb) |
1129 | { | 1097 | { |
1130 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; | 1098 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; |
1099 | struct tty_struct *tty; | ||
1131 | 1100 | ||
1132 | IRDA_DEBUG(2, "%s()\n", __func__ ); | 1101 | IRDA_DEBUG(2, "%s()\n", __func__ ); |
1133 | 1102 | ||
@@ -1135,7 +1104,8 @@ static int ircomm_tty_data_indication(void *instance, void *sap, | |||
1135 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); | 1104 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); |
1136 | IRDA_ASSERT(skb != NULL, return -1;); | 1105 | IRDA_ASSERT(skb != NULL, return -1;); |
1137 | 1106 | ||
1138 | if (!self->tty) { | 1107 | tty = tty_port_tty_get(&self->port); |
1108 | if (!tty) { | ||
1139 | IRDA_DEBUG(0, "%s(), no tty!\n", __func__ ); | 1109 | IRDA_DEBUG(0, "%s(), no tty!\n", __func__ ); |
1140 | return 0; | 1110 | return 0; |
1141 | } | 1111 | } |
@@ -1146,7 +1116,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap, | |||
1146 | * Devices like WinCE can do this, and since they don't send any | 1116 | * Devices like WinCE can do this, and since they don't send any |
1147 | * params, we can just as well declare the hardware for running. | 1117 | * params, we can just as well declare the hardware for running. |
1148 | */ | 1118 | */ |
1149 | if (self->tty->hw_stopped && (self->flow == FLOW_START)) { | 1119 | if (tty->hw_stopped && (self->flow == FLOW_START)) { |
1150 | IRDA_DEBUG(0, "%s(), polling for line settings!\n", __func__ ); | 1120 | IRDA_DEBUG(0, "%s(), polling for line settings!\n", __func__ ); |
1151 | ircomm_param_request(self, IRCOMM_POLL, TRUE); | 1121 | ircomm_param_request(self, IRCOMM_POLL, TRUE); |
1152 | 1122 | ||
@@ -1159,8 +1129,9 @@ static int ircomm_tty_data_indication(void *instance, void *sap, | |||
1159 | * Use flip buffer functions since the code may be called from interrupt | 1129 | * Use flip buffer functions since the code may be called from interrupt |
1160 | * context | 1130 | * context |
1161 | */ | 1131 | */ |
1162 | tty_insert_flip_string(self->tty, skb->data, skb->len); | 1132 | tty_insert_flip_string(tty, skb->data, skb->len); |
1163 | tty_flip_buffer_push(self->tty); | 1133 | tty_flip_buffer_push(tty); |
1134 | tty_kref_put(tty); | ||
1164 | 1135 | ||
1165 | /* No need to kfree_skb - see ircomm_ttp_data_indication() */ | 1136 | /* No need to kfree_skb - see ircomm_ttp_data_indication() */ |
1166 | 1137 | ||
@@ -1211,12 +1182,13 @@ static void ircomm_tty_flow_indication(void *instance, void *sap, | |||
1211 | IRDA_ASSERT(self != NULL, return;); | 1182 | IRDA_ASSERT(self != NULL, return;); |
1212 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); | 1183 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); |
1213 | 1184 | ||
1214 | tty = self->tty; | 1185 | tty = tty_port_tty_get(&self->port); |
1215 | 1186 | ||
1216 | switch (cmd) { | 1187 | switch (cmd) { |
1217 | case FLOW_START: | 1188 | case FLOW_START: |
1218 | IRDA_DEBUG(2, "%s(), hw start!\n", __func__ ); | 1189 | IRDA_DEBUG(2, "%s(), hw start!\n", __func__ ); |
1219 | tty->hw_stopped = 0; | 1190 | if (tty) |
1191 | tty->hw_stopped = 0; | ||
1220 | 1192 | ||
1221 | /* ircomm_tty_do_softint will take care of the rest */ | 1193 | /* ircomm_tty_do_softint will take care of the rest */ |
1222 | schedule_work(&self->tqueue); | 1194 | schedule_work(&self->tqueue); |
@@ -1224,15 +1196,19 @@ static void ircomm_tty_flow_indication(void *instance, void *sap, | |||
1224 | default: /* If we get here, something is very wrong, better stop */ | 1196 | default: /* If we get here, something is very wrong, better stop */ |
1225 | case FLOW_STOP: | 1197 | case FLOW_STOP: |
1226 | IRDA_DEBUG(2, "%s(), hw stopped!\n", __func__ ); | 1198 | IRDA_DEBUG(2, "%s(), hw stopped!\n", __func__ ); |
1227 | tty->hw_stopped = 1; | 1199 | if (tty) |
1200 | tty->hw_stopped = 1; | ||
1228 | break; | 1201 | break; |
1229 | } | 1202 | } |
1203 | |||
1204 | tty_kref_put(tty); | ||
1230 | self->flow = cmd; | 1205 | self->flow = cmd; |
1231 | } | 1206 | } |
1232 | 1207 | ||
1233 | #ifdef CONFIG_PROC_FS | 1208 | #ifdef CONFIG_PROC_FS |
1234 | static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m) | 1209 | static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m) |
1235 | { | 1210 | { |
1211 | struct tty_struct *tty; | ||
1236 | char sep; | 1212 | char sep; |
1237 | 1213 | ||
1238 | seq_printf(m, "State: %s\n", ircomm_tty_state[self->state]); | 1214 | seq_printf(m, "State: %s\n", ircomm_tty_state[self->state]); |
@@ -1328,40 +1304,43 @@ static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m) | |||
1328 | 1304 | ||
1329 | seq_puts(m, "Flags:"); | 1305 | seq_puts(m, "Flags:"); |
1330 | sep = ' '; | 1306 | sep = ' '; |
1331 | if (self->flags & ASYNC_CTS_FLOW) { | 1307 | if (self->port.flags & ASYNC_CTS_FLOW) { |
1332 | seq_printf(m, "%cASYNC_CTS_FLOW", sep); | 1308 | seq_printf(m, "%cASYNC_CTS_FLOW", sep); |
1333 | sep = '|'; | 1309 | sep = '|'; |
1334 | } | 1310 | } |
1335 | if (self->flags & ASYNC_CHECK_CD) { | 1311 | if (self->port.flags & ASYNC_CHECK_CD) { |
1336 | seq_printf(m, "%cASYNC_CHECK_CD", sep); | 1312 | seq_printf(m, "%cASYNC_CHECK_CD", sep); |
1337 | sep = '|'; | 1313 | sep = '|'; |
1338 | } | 1314 | } |
1339 | if (self->flags & ASYNC_INITIALIZED) { | 1315 | if (self->port.flags & ASYNC_INITIALIZED) { |
1340 | seq_printf(m, "%cASYNC_INITIALIZED", sep); | 1316 | seq_printf(m, "%cASYNC_INITIALIZED", sep); |
1341 | sep = '|'; | 1317 | sep = '|'; |
1342 | } | 1318 | } |
1343 | if (self->flags & ASYNC_LOW_LATENCY) { | 1319 | if (self->port.flags & ASYNC_LOW_LATENCY) { |
1344 | seq_printf(m, "%cASYNC_LOW_LATENCY", sep); | 1320 | seq_printf(m, "%cASYNC_LOW_LATENCY", sep); |
1345 | sep = '|'; | 1321 | sep = '|'; |
1346 | } | 1322 | } |
1347 | if (self->flags & ASYNC_CLOSING) { | 1323 | if (self->port.flags & ASYNC_CLOSING) { |
1348 | seq_printf(m, "%cASYNC_CLOSING", sep); | 1324 | seq_printf(m, "%cASYNC_CLOSING", sep); |
1349 | sep = '|'; | 1325 | sep = '|'; |
1350 | } | 1326 | } |
1351 | if (self->flags & ASYNC_NORMAL_ACTIVE) { | 1327 | if (self->port.flags & ASYNC_NORMAL_ACTIVE) { |
1352 | seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep); | 1328 | seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep); |
1353 | sep = '|'; | 1329 | sep = '|'; |
1354 | } | 1330 | } |
1355 | seq_putc(m, '\n'); | 1331 | seq_putc(m, '\n'); |
1356 | 1332 | ||
1357 | seq_printf(m, "Role: %s\n", self->client ? "client" : "server"); | 1333 | seq_printf(m, "Role: %s\n", self->client ? "client" : "server"); |
1358 | seq_printf(m, "Open count: %d\n", self->open_count); | 1334 | seq_printf(m, "Open count: %d\n", self->port.count); |
1359 | seq_printf(m, "Max data size: %d\n", self->max_data_size); | 1335 | seq_printf(m, "Max data size: %d\n", self->max_data_size); |
1360 | seq_printf(m, "Max header size: %d\n", self->max_header_size); | 1336 | seq_printf(m, "Max header size: %d\n", self->max_header_size); |
1361 | 1337 | ||
1362 | if (self->tty) | 1338 | tty = tty_port_tty_get(&self->port); |
1339 | if (tty) { | ||
1363 | seq_printf(m, "Hardware: %s\n", | 1340 | seq_printf(m, "Hardware: %s\n", |
1364 | self->tty->hw_stopped ? "Stopped" : "Running"); | 1341 | tty->hw_stopped ? "Stopped" : "Running"); |
1342 | tty_kref_put(tty); | ||
1343 | } | ||
1365 | } | 1344 | } |
1366 | 1345 | ||
1367 | static int ircomm_tty_proc_show(struct seq_file *m, void *v) | 1346 | static int ircomm_tty_proc_show(struct seq_file *m, void *v) |
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c index b65d66e0d817..3ab70e7a0715 100644 --- a/net/irda/ircomm/ircomm_tty_attach.c +++ b/net/irda/ircomm/ircomm_tty_attach.c | |||
@@ -130,6 +130,8 @@ static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, | |||
130 | */ | 130 | */ |
131 | int ircomm_tty_attach_cable(struct ircomm_tty_cb *self) | 131 | int ircomm_tty_attach_cable(struct ircomm_tty_cb *self) |
132 | { | 132 | { |
133 | struct tty_struct *tty; | ||
134 | |||
133 | IRDA_DEBUG(0, "%s()\n", __func__ ); | 135 | IRDA_DEBUG(0, "%s()\n", __func__ ); |
134 | 136 | ||
135 | IRDA_ASSERT(self != NULL, return -1;); | 137 | IRDA_ASSERT(self != NULL, return -1;); |
@@ -142,7 +144,11 @@ int ircomm_tty_attach_cable(struct ircomm_tty_cb *self) | |||
142 | } | 144 | } |
143 | 145 | ||
144 | /* Make sure nobody tries to write before the link is up */ | 146 | /* Make sure nobody tries to write before the link is up */ |
145 | self->tty->hw_stopped = 1; | 147 | tty = tty_port_tty_get(&self->port); |
148 | if (tty) { | ||
149 | tty->hw_stopped = 1; | ||
150 | tty_kref_put(tty); | ||
151 | } | ||
146 | 152 | ||
147 | ircomm_tty_ias_register(self); | 153 | ircomm_tty_ias_register(self); |
148 | 154 | ||
@@ -398,23 +404,26 @@ void ircomm_tty_disconnect_indication(void *instance, void *sap, | |||
398 | struct sk_buff *skb) | 404 | struct sk_buff *skb) |
399 | { | 405 | { |
400 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; | 406 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; |
407 | struct tty_struct *tty; | ||
401 | 408 | ||
402 | IRDA_DEBUG(2, "%s()\n", __func__ ); | 409 | IRDA_DEBUG(2, "%s()\n", __func__ ); |
403 | 410 | ||
404 | IRDA_ASSERT(self != NULL, return;); | 411 | IRDA_ASSERT(self != NULL, return;); |
405 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); | 412 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); |
406 | 413 | ||
407 | if (!self->tty) | 414 | tty = tty_port_tty_get(&self->port); |
415 | if (!tty) | ||
408 | return; | 416 | return; |
409 | 417 | ||
410 | /* This will stop control data transfers */ | 418 | /* This will stop control data transfers */ |
411 | self->flow = FLOW_STOP; | 419 | self->flow = FLOW_STOP; |
412 | 420 | ||
413 | /* Stop data transfers */ | 421 | /* Stop data transfers */ |
414 | self->tty->hw_stopped = 1; | 422 | tty->hw_stopped = 1; |
415 | 423 | ||
416 | ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL, | 424 | ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL, |
417 | NULL); | 425 | NULL); |
426 | tty_kref_put(tty); | ||
418 | } | 427 | } |
419 | 428 | ||
420 | /* | 429 | /* |
@@ -550,12 +559,15 @@ void ircomm_tty_connect_indication(void *instance, void *sap, | |||
550 | */ | 559 | */ |
551 | void ircomm_tty_link_established(struct ircomm_tty_cb *self) | 560 | void ircomm_tty_link_established(struct ircomm_tty_cb *self) |
552 | { | 561 | { |
562 | struct tty_struct *tty; | ||
563 | |||
553 | IRDA_DEBUG(2, "%s()\n", __func__ ); | 564 | IRDA_DEBUG(2, "%s()\n", __func__ ); |
554 | 565 | ||
555 | IRDA_ASSERT(self != NULL, return;); | 566 | IRDA_ASSERT(self != NULL, return;); |
556 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); | 567 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); |
557 | 568 | ||
558 | if (!self->tty) | 569 | tty = tty_port_tty_get(&self->port); |
570 | if (!tty) | ||
559 | return; | 571 | return; |
560 | 572 | ||
561 | del_timer(&self->watchdog_timer); | 573 | del_timer(&self->watchdog_timer); |
@@ -566,19 +578,22 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self) | |||
566 | * will have to wait for the peer device (DCE) to raise the CTS | 578 | * will have to wait for the peer device (DCE) to raise the CTS |
567 | * line. | 579 | * line. |
568 | */ | 580 | */ |
569 | if ((self->flags & ASYNC_CTS_FLOW) && ((self->settings.dce & IRCOMM_CTS) == 0)) { | 581 | if ((self->port.flags & ASYNC_CTS_FLOW) && |
582 | ((self->settings.dce & IRCOMM_CTS) == 0)) { | ||
570 | IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ ); | 583 | IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ ); |
571 | return; | 584 | goto put; |
572 | } else { | 585 | } else { |
573 | IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ ); | 586 | IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ ); |
574 | 587 | ||
575 | self->tty->hw_stopped = 0; | 588 | tty->hw_stopped = 0; |
576 | 589 | ||
577 | /* Wake up processes blocked on open */ | 590 | /* Wake up processes blocked on open */ |
578 | wake_up_interruptible(&self->open_wait); | 591 | wake_up_interruptible(&self->port.open_wait); |
579 | } | 592 | } |
580 | 593 | ||
581 | schedule_work(&self->tqueue); | 594 | schedule_work(&self->tqueue); |
595 | put: | ||
596 | tty_kref_put(tty); | ||
582 | } | 597 | } |
583 | 598 | ||
584 | /* | 599 | /* |
@@ -977,14 +992,17 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, | |||
977 | ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); | 992 | ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); |
978 | ircomm_tty_start_watchdog_timer(self, 3*HZ); | 993 | ircomm_tty_start_watchdog_timer(self, 3*HZ); |
979 | 994 | ||
980 | if (self->flags & ASYNC_CHECK_CD) { | 995 | if (self->port.flags & ASYNC_CHECK_CD) { |
981 | /* Drop carrier */ | 996 | /* Drop carrier */ |
982 | self->settings.dce = IRCOMM_DELTA_CD; | 997 | self->settings.dce = IRCOMM_DELTA_CD; |
983 | ircomm_tty_check_modem_status(self); | 998 | ircomm_tty_check_modem_status(self); |
984 | } else { | 999 | } else { |
1000 | struct tty_struct *tty = tty_port_tty_get(&self->port); | ||
985 | IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ ); | 1001 | IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ ); |
986 | if (self->tty) | 1002 | if (tty) { |
987 | tty_hangup(self->tty); | 1003 | tty_hangup(tty); |
1004 | tty_kref_put(tty); | ||
1005 | } | ||
988 | } | 1006 | } |
989 | break; | 1007 | break; |
990 | default: | 1008 | default: |
diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c index d0667d68351d..b343f50dc8d7 100644 --- a/net/irda/ircomm/ircomm_tty_ioctl.c +++ b/net/irda/ircomm/ircomm_tty_ioctl.c | |||
@@ -52,17 +52,18 @@ | |||
52 | * Change speed of the driver. If the remote device is a DCE, then this | 52 | * Change speed of the driver. If the remote device is a DCE, then this |
53 | * should make it change the speed of its serial port | 53 | * should make it change the speed of its serial port |
54 | */ | 54 | */ |
55 | static void ircomm_tty_change_speed(struct ircomm_tty_cb *self) | 55 | static void ircomm_tty_change_speed(struct ircomm_tty_cb *self, |
56 | struct tty_struct *tty) | ||
56 | { | 57 | { |
57 | unsigned int cflag, cval; | 58 | unsigned int cflag, cval; |
58 | int baud; | 59 | int baud; |
59 | 60 | ||
60 | IRDA_DEBUG(2, "%s()\n", __func__ ); | 61 | IRDA_DEBUG(2, "%s()\n", __func__ ); |
61 | 62 | ||
62 | if (!self->tty || !self->tty->termios || !self->ircomm) | 63 | if (!self->ircomm) |
63 | return; | 64 | return; |
64 | 65 | ||
65 | cflag = self->tty->termios->c_cflag; | 66 | cflag = tty->termios.c_cflag; |
66 | 67 | ||
67 | /* byte size and parity */ | 68 | /* byte size and parity */ |
68 | switch (cflag & CSIZE) { | 69 | switch (cflag & CSIZE) { |
@@ -81,7 +82,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self) | |||
81 | cval |= IRCOMM_PARITY_EVEN; | 82 | cval |= IRCOMM_PARITY_EVEN; |
82 | 83 | ||
83 | /* Determine divisor based on baud rate */ | 84 | /* Determine divisor based on baud rate */ |
84 | baud = tty_get_baud_rate(self->tty); | 85 | baud = tty_get_baud_rate(tty); |
85 | if (!baud) | 86 | if (!baud) |
86 | baud = 9600; /* B0 transition handled in rs_set_termios */ | 87 | baud = 9600; /* B0 transition handled in rs_set_termios */ |
87 | 88 | ||
@@ -90,19 +91,19 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self) | |||
90 | 91 | ||
91 | /* CTS flow control flag and modem status interrupts */ | 92 | /* CTS flow control flag and modem status interrupts */ |
92 | if (cflag & CRTSCTS) { | 93 | if (cflag & CRTSCTS) { |
93 | self->flags |= ASYNC_CTS_FLOW; | 94 | self->port.flags |= ASYNC_CTS_FLOW; |
94 | self->settings.flow_control |= IRCOMM_RTS_CTS_IN; | 95 | self->settings.flow_control |= IRCOMM_RTS_CTS_IN; |
95 | /* This got me. Bummer. Jean II */ | 96 | /* This got me. Bummer. Jean II */ |
96 | if (self->service_type == IRCOMM_3_WIRE_RAW) | 97 | if (self->service_type == IRCOMM_3_WIRE_RAW) |
97 | IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__); | 98 | IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__); |
98 | } else { | 99 | } else { |
99 | self->flags &= ~ASYNC_CTS_FLOW; | 100 | self->port.flags &= ~ASYNC_CTS_FLOW; |
100 | self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN; | 101 | self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN; |
101 | } | 102 | } |
102 | if (cflag & CLOCAL) | 103 | if (cflag & CLOCAL) |
103 | self->flags &= ~ASYNC_CHECK_CD; | 104 | self->port.flags &= ~ASYNC_CHECK_CD; |
104 | else | 105 | else |
105 | self->flags |= ASYNC_CHECK_CD; | 106 | self->port.flags |= ASYNC_CHECK_CD; |
106 | #if 0 | 107 | #if 0 |
107 | /* | 108 | /* |
108 | * Set up parity check flag | 109 | * Set up parity check flag |
@@ -148,18 +149,18 @@ void ircomm_tty_set_termios(struct tty_struct *tty, | |||
148 | struct ktermios *old_termios) | 149 | struct ktermios *old_termios) |
149 | { | 150 | { |
150 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; | 151 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; |
151 | unsigned int cflag = tty->termios->c_cflag; | 152 | unsigned int cflag = tty->termios.c_cflag; |
152 | 153 | ||
153 | IRDA_DEBUG(2, "%s()\n", __func__ ); | 154 | IRDA_DEBUG(2, "%s()\n", __func__ ); |
154 | 155 | ||
155 | if ((cflag == old_termios->c_cflag) && | 156 | if ((cflag == old_termios->c_cflag) && |
156 | (RELEVANT_IFLAG(tty->termios->c_iflag) == | 157 | (RELEVANT_IFLAG(tty->termios.c_iflag) == |
157 | RELEVANT_IFLAG(old_termios->c_iflag))) | 158 | RELEVANT_IFLAG(old_termios->c_iflag))) |
158 | { | 159 | { |
159 | return; | 160 | return; |
160 | } | 161 | } |
161 | 162 | ||
162 | ircomm_tty_change_speed(self); | 163 | ircomm_tty_change_speed(self, tty); |
163 | 164 | ||
164 | /* Handle transition to B0 status */ | 165 | /* Handle transition to B0 status */ |
165 | if ((old_termios->c_cflag & CBAUD) && | 166 | if ((old_termios->c_cflag & CBAUD) && |
@@ -172,7 +173,7 @@ void ircomm_tty_set_termios(struct tty_struct *tty, | |||
172 | if (!(old_termios->c_cflag & CBAUD) && | 173 | if (!(old_termios->c_cflag & CBAUD) && |
173 | (cflag & CBAUD)) { | 174 | (cflag & CBAUD)) { |
174 | self->settings.dte |= IRCOMM_DTR; | 175 | self->settings.dte |= IRCOMM_DTR; |
175 | if (!(tty->termios->c_cflag & CRTSCTS) || | 176 | if (!(tty->termios.c_cflag & CRTSCTS) || |
176 | !test_bit(TTY_THROTTLED, &tty->flags)) { | 177 | !test_bit(TTY_THROTTLED, &tty->flags)) { |
177 | self->settings.dte |= IRCOMM_RTS; | 178 | self->settings.dte |= IRCOMM_RTS; |
178 | } | 179 | } |
@@ -181,7 +182,7 @@ void ircomm_tty_set_termios(struct tty_struct *tty, | |||
181 | 182 | ||
182 | /* Handle turning off CRTSCTS */ | 183 | /* Handle turning off CRTSCTS */ |
183 | if ((old_termios->c_cflag & CRTSCTS) && | 184 | if ((old_termios->c_cflag & CRTSCTS) && |
184 | !(tty->termios->c_cflag & CRTSCTS)) | 185 | !(tty->termios.c_cflag & CRTSCTS)) |
185 | { | 186 | { |
186 | tty->hw_stopped = 0; | 187 | tty->hw_stopped = 0; |
187 | ircomm_tty_start(tty); | 188 | ircomm_tty_start(tty); |
@@ -270,10 +271,10 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self, | |||
270 | 271 | ||
271 | memset(&info, 0, sizeof(info)); | 272 | memset(&info, 0, sizeof(info)); |
272 | info.line = self->line; | 273 | info.line = self->line; |
273 | info.flags = self->flags; | 274 | info.flags = self->port.flags; |
274 | info.baud_base = self->settings.data_rate; | 275 | info.baud_base = self->settings.data_rate; |
275 | info.close_delay = self->close_delay; | 276 | info.close_delay = self->port.close_delay; |
276 | info.closing_wait = self->closing_wait; | 277 | info.closing_wait = self->port.closing_wait; |
277 | 278 | ||
278 | /* For compatibility */ | 279 | /* For compatibility */ |
279 | info.type = PORT_16550A; | 280 | info.type = PORT_16550A; |