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 | |
| 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>
| -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 | ||
