diff options
author | Ryan Bradetich <rbradetich@gmail.com> | 2006-11-04 20:21:44 -0500 |
---|---|---|
committer | Kyle McMartin <kyle@ubuntu.com> | 2006-12-08 00:34:21 -0500 |
commit | c380f057269686e17db74d360c923663889ac702 (patch) | |
tree | f9f063b72dbabc17777d11099a166f292b5be071 /drivers | |
parent | 9c6416ce6a9829ede1594403d19b22d23cf54e2e (diff) |
[PARISC] [MUX] Make the Serial Mux driver work as module
The following updates are based off a patch from willy:
* Removal of the mux_card list.
* Add the mux_remove function.
Other updates:
* Re-organize the driver structure a bit to make the
mux_init and mux_exit functions more symmetrical.
* Added the del_timer.
* Unregistered the console.
At this point I can insmod, rmmod, and re-insmod the
mux without any failures.
Signed-off-by: Ryan Bradetich <rbrad@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/serial/mux.c | 135 |
1 files changed, 57 insertions, 78 deletions
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index f21faf163955..5ff7e05a1526 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c | |||
@@ -66,13 +66,6 @@ static struct uart_driver mux_driver = { | |||
66 | .nr = MUX_NR, | 66 | .nr = MUX_NR, |
67 | }; | 67 | }; |
68 | 68 | ||
69 | struct mux_card { | ||
70 | int port_count; | ||
71 | struct parisc_device *dev; | ||
72 | struct mux_card *next; | ||
73 | }; | ||
74 | |||
75 | static struct mux_card *mux_card_head; | ||
76 | static struct timer_list mux_timer; | 69 | static struct timer_list mux_timer; |
77 | 70 | ||
78 | #define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET) | 71 | #define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET) |
@@ -441,37 +434,6 @@ static struct uart_ops mux_pops = { | |||
441 | }; | 434 | }; |
442 | 435 | ||
443 | /** | 436 | /** |
444 | * get_new_mux_card - Allocate and return a new mux card. | ||
445 | * | ||
446 | * This function is used to allocate and return a new mux card. | ||
447 | */ | ||
448 | static struct mux_card * __init get_new_mux_card(void) | ||
449 | { | ||
450 | struct mux_card *card = mux_card_head; | ||
451 | |||
452 | if(card == NULL) { | ||
453 | mux_card_head = kzalloc(sizeof(struct mux_card), GFP_KERNEL); | ||
454 | if(!mux_card_head) { | ||
455 | printk(KERN_ERR "MUX: Unable to allocate memory.\n"); | ||
456 | return NULL; | ||
457 | } | ||
458 | return mux_card_head; | ||
459 | } | ||
460 | |||
461 | while(card->next) { | ||
462 | card = card->next; | ||
463 | } | ||
464 | |||
465 | card->next = kzalloc(sizeof(struct mux_card), GFP_KERNEL); | ||
466 | if(!card->next) { | ||
467 | printk(KERN_ERR "MUX: Unable to allocate memory.\n"); | ||
468 | return NULL; | ||
469 | } | ||
470 | |||
471 | return card->next; | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * mux_probe - Determine if the Serial Mux should claim this device. | 437 | * mux_probe - Determine if the Serial Mux should claim this device. |
476 | * @dev: The parisc device. | 438 | * @dev: The parisc device. |
477 | * | 439 | * |
@@ -480,11 +442,9 @@ static struct mux_card * __init get_new_mux_card(void) | |||
480 | */ | 442 | */ |
481 | static int __init mux_probe(struct parisc_device *dev) | 443 | static int __init mux_probe(struct parisc_device *dev) |
482 | { | 444 | { |
483 | int i, status, ports; | 445 | int i, status, port_count; |
484 | u8 iodc_data[32]; | 446 | u8 iodc_data[32]; |
485 | unsigned long bytecnt; | 447 | unsigned long bytecnt; |
486 | struct uart_port *port; | ||
487 | struct mux_card *card; | ||
488 | 448 | ||
489 | status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); | 449 | status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); |
490 | if(status != PDC_OK) { | 450 | if(status != PDC_OK) { |
@@ -492,17 +452,12 @@ static int __init mux_probe(struct parisc_device *dev) | |||
492 | return 1; | 452 | return 1; |
493 | } | 453 | } |
494 | 454 | ||
495 | ports = GET_MUX_PORTS(iodc_data); | 455 | port_count = GET_MUX_PORTS(iodc_data); |
496 | printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.4\n", ports); | 456 | printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.5\n", port_count); |
497 | 457 | ||
498 | card = get_new_mux_card(); | 458 | dev_set_drvdata(&dev->dev, (void *)(long)port_count); |
499 | if(card == NULL) | 459 | request_mem_region(dev->hpa.start + MUX_OFFSET, |
500 | return 1; | 460 | port_count * MUX_LINE_OFFSET, "Mux"); |
501 | |||
502 | card->dev = dev; | ||
503 | card->port_count = ports; | ||
504 | request_mem_region(card->dev->hpa.start + MUX_OFFSET, | ||
505 | card->port_count * MUX_LINE_OFFSET, "Mux"); | ||
506 | 461 | ||
507 | if(!port_cnt) { | 462 | if(!port_cnt) { |
508 | mux_driver.cons = MUX_CONSOLE; | 463 | mux_driver.cons = MUX_CONSOLE; |
@@ -512,13 +467,10 @@ static int __init mux_probe(struct parisc_device *dev) | |||
512 | printk(KERN_ERR "Serial mux: Unable to register driver.\n"); | 467 | printk(KERN_ERR "Serial mux: Unable to register driver.\n"); |
513 | return 1; | 468 | return 1; |
514 | } | 469 | } |
515 | |||
516 | init_timer(&mux_timer); | ||
517 | mux_timer.function = mux_poll; | ||
518 | } | 470 | } |
519 | 471 | ||
520 | for(i = 0; i < ports; ++i, ++port_cnt) { | 472 | for(i = 0; i < port_count; ++i, ++port_cnt) { |
521 | port = &mux_ports[port_cnt].port; | 473 | struct uart_port *port = &mux_ports[port_cnt].port; |
522 | port->iobase = 0; | 474 | port->iobase = 0; |
523 | port->mapbase = dev->hpa.start + MUX_OFFSET + | 475 | port->mapbase = dev->hpa.start + MUX_OFFSET + |
524 | (i * MUX_LINE_OFFSET); | 476 | (i * MUX_LINE_OFFSET); |
@@ -543,11 +495,34 @@ static int __init mux_probe(struct parisc_device *dev) | |||
543 | BUG_ON(status); | 495 | BUG_ON(status); |
544 | } | 496 | } |
545 | 497 | ||
546 | #ifdef CONFIG_SERIAL_MUX_CONSOLE | 498 | return 0; |
547 | register_console(&mux_console); | 499 | } |
548 | #endif | ||
549 | mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); | ||
550 | 500 | ||
501 | static int __devexit mux_remove(struct parisc_device *dev) | ||
502 | { | ||
503 | int i; | ||
504 | int port_count = (long)dev_get_drvdata(&dev->dev); | ||
505 | |||
506 | /* Delete the Mux timer. */ | ||
507 | del_timer(&mux_timer); | ||
508 | |||
509 | /* Find Port 0 for this card in the mux_ports list. */ | ||
510 | for(i = 0; i < port_cnt; ++i) { | ||
511 | if(mux_ports[i].port.mapbase == dev->hpa.start + MUX_OFFSET) | ||
512 | break; | ||
513 | } | ||
514 | BUG_ON(i + port_count > port_cnt); | ||
515 | |||
516 | /* Release the resources associated with each port on the device. */ | ||
517 | for(; i < port_count; ++i) { | ||
518 | struct uart_port *port = &mux_ports[i].port; | ||
519 | |||
520 | uart_remove_one_port(&mux_driver, port); | ||
521 | if(port->membase) | ||
522 | iounmap(port->membase); | ||
523 | } | ||
524 | |||
525 | release_mem_region(dev->hpa.start + MUX_OFFSET, port_count * MUX_LINE_OFFSET); | ||
551 | return 0; | 526 | return 0; |
552 | } | 527 | } |
553 | 528 | ||
@@ -562,6 +537,7 @@ static struct parisc_driver serial_mux_driver = { | |||
562 | .name = "serial_mux", | 537 | .name = "serial_mux", |
563 | .id_table = mux_tbl, | 538 | .id_table = mux_tbl, |
564 | .probe = mux_probe, | 539 | .probe = mux_probe, |
540 | .remove = __devexit_p(mux_remove), | ||
565 | }; | 541 | }; |
566 | 542 | ||
567 | /** | 543 | /** |
@@ -571,7 +547,20 @@ static struct parisc_driver serial_mux_driver = { | |||
571 | */ | 547 | */ |
572 | static int __init mux_init(void) | 548 | static int __init mux_init(void) |
573 | { | 549 | { |
574 | return register_parisc_driver(&serial_mux_driver); | 550 | int status = register_parisc_driver(&serial_mux_driver); |
551 | |||
552 | if(port_cnt > 0) { | ||
553 | /* Start the Mux timer */ | ||
554 | init_timer(&mux_timer); | ||
555 | mux_timer.function = mux_poll; | ||
556 | mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); | ||
557 | |||
558 | #ifdef CONFIG_SERIAL_MUX_CONSOLE | ||
559 | register_console(&mux_console); | ||
560 | #endif | ||
561 | } | ||
562 | |||
563 | return status; | ||
575 | } | 564 | } |
576 | 565 | ||
577 | /** | 566 | /** |
@@ -581,25 +570,15 @@ static int __init mux_init(void) | |||
581 | */ | 570 | */ |
582 | static void __exit mux_exit(void) | 571 | static void __exit mux_exit(void) |
583 | { | 572 | { |
584 | int i; | 573 | /* Delete the Mux timer. */ |
585 | struct mux_card *next; | 574 | if(port_cnt > 0) { |
586 | struct mux_card *card = mux_card_head; | 575 | del_timer(&mux_timer); |
587 | 576 | #ifdef CONFIG_SERIAL_MUX_CONSOLE | |
588 | for (i = 0; i < port_cnt; i++) { | 577 | unregister_console(&mux_console); |
589 | uart_remove_one_port(&mux_driver, &mux_ports[i].port); | 578 | #endif |
590 | if (mux_ports[i].port.membase) | ||
591 | iounmap(mux_ports[i].port.membase); | ||
592 | } | ||
593 | |||
594 | while(card != NULL) { | ||
595 | release_mem_region(card->dev->hpa.start + MUX_OFFSET, | ||
596 | card->port_count * MUX_LINE_OFFSET); | ||
597 | |||
598 | next = card->next; | ||
599 | kfree(card); | ||
600 | card = next; | ||
601 | } | 579 | } |
602 | 580 | ||
581 | unregister_parisc_driver(&serial_mux_driver); | ||
603 | uart_unregister_driver(&mux_driver); | 582 | uart_unregister_driver(&mux_driver); |
604 | } | 583 | } |
605 | 584 | ||