diff options
-rw-r--r-- | drivers/scsi/mac_esp.c | 81 |
1 files changed, 58 insertions, 23 deletions
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index a99f9ce6be55..c24e86f07804 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c | |||
@@ -53,7 +53,8 @@ struct mac_esp_priv { | |||
53 | void __iomem *pdma_io; | 53 | void __iomem *pdma_io; |
54 | int error; | 54 | int error; |
55 | }; | 55 | }; |
56 | static struct platform_device *internal_esp, *external_esp; | 56 | static struct platform_device *internal_pdev, *external_pdev; |
57 | static struct esp *esp_chips[2]; | ||
57 | 58 | ||
58 | #define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \ | 59 | #define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \ |
59 | platform_get_drvdata((struct platform_device *) \ | 60 | platform_get_drvdata((struct platform_device *) \ |
@@ -443,6 +444,32 @@ static u32 mac_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len) | |||
443 | return dma_len > 0xFFFF ? 0xFFFF : dma_len; | 444 | return dma_len > 0xFFFF ? 0xFFFF : dma_len; |
444 | } | 445 | } |
445 | 446 | ||
447 | static irqreturn_t mac_scsi_esp_intr(int irq, void *dev_id) | ||
448 | { | ||
449 | int got_intr; | ||
450 | |||
451 | /* | ||
452 | * This is an edge triggered IRQ, so we have to be careful to | ||
453 | * avoid missing a transition when it is shared by two ESP devices. | ||
454 | */ | ||
455 | |||
456 | do { | ||
457 | got_intr = 0; | ||
458 | if (esp_chips[0] && | ||
459 | (mac_esp_read8(esp_chips[0], ESP_STATUS) & ESP_STAT_INTR)) { | ||
460 | (void)scsi_esp_intr(irq, esp_chips[0]); | ||
461 | got_intr = 1; | ||
462 | } | ||
463 | if (esp_chips[1] && | ||
464 | (mac_esp_read8(esp_chips[1], ESP_STATUS) & ESP_STAT_INTR)) { | ||
465 | (void)scsi_esp_intr(irq, esp_chips[1]); | ||
466 | got_intr = 1; | ||
467 | } | ||
468 | } while (got_intr); | ||
469 | |||
470 | return IRQ_HANDLED; | ||
471 | } | ||
472 | |||
446 | static struct esp_driver_ops mac_esp_ops = { | 473 | static struct esp_driver_ops mac_esp_ops = { |
447 | .esp_write8 = mac_esp_write8, | 474 | .esp_write8 = mac_esp_write8, |
448 | .esp_read8 = mac_esp_read8, | 475 | .esp_read8 = mac_esp_read8, |
@@ -557,10 +584,16 @@ static int __devinit esp_mac_probe(struct platform_device *dev) | |||
557 | } | 584 | } |
558 | 585 | ||
559 | host->irq = IRQ_MAC_SCSI; | 586 | host->irq = IRQ_MAC_SCSI; |
560 | err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "Mac ESP", | 587 | esp_chips[dev->id] = esp; |
561 | esp); | 588 | mb(); |
562 | if (err < 0) | 589 | if (esp_chips[!dev->id] == NULL) { |
563 | goto fail_free_priv; | 590 | err = request_irq(host->irq, mac_scsi_esp_intr, 0, |
591 | "Mac ESP", NULL); | ||
592 | if (err < 0) { | ||
593 | esp_chips[dev->id] = NULL; | ||
594 | goto fail_free_priv; | ||
595 | } | ||
596 | } | ||
564 | 597 | ||
565 | err = scsi_esp_register(esp, &dev->dev); | 598 | err = scsi_esp_register(esp, &dev->dev); |
566 | if (err) | 599 | if (err) |
@@ -569,7 +602,8 @@ static int __devinit esp_mac_probe(struct platform_device *dev) | |||
569 | return 0; | 602 | return 0; |
570 | 603 | ||
571 | fail_free_irq: | 604 | fail_free_irq: |
572 | free_irq(host->irq, esp); | 605 | if (esp_chips[!dev->id] == NULL) |
606 | free_irq(host->irq, esp); | ||
573 | fail_free_priv: | 607 | fail_free_priv: |
574 | kfree(mep); | 608 | kfree(mep); |
575 | fail_free_command_block: | 609 | fail_free_command_block: |
@@ -588,7 +622,9 @@ static int __devexit esp_mac_remove(struct platform_device *dev) | |||
588 | 622 | ||
589 | scsi_esp_unregister(esp); | 623 | scsi_esp_unregister(esp); |
590 | 624 | ||
591 | free_irq(irq, esp); | 625 | esp_chips[dev->id] = NULL; |
626 | if (!(esp_chips[0] || esp_chips[1])) | ||
627 | free_irq(irq, NULL); | ||
592 | 628 | ||
593 | kfree(mep); | 629 | kfree(mep); |
594 | 630 | ||
@@ -615,19 +651,18 @@ static int __init mac_esp_init(void) | |||
615 | if (err) | 651 | if (err) |
616 | return err; | 652 | return err; |
617 | 653 | ||
618 | internal_esp = platform_device_alloc(DRV_MODULE_NAME, 0); | 654 | internal_pdev = platform_device_alloc(DRV_MODULE_NAME, 0); |
619 | if (internal_esp && platform_device_add(internal_esp)) { | 655 | if (internal_pdev && platform_device_add(internal_pdev)) { |
620 | platform_device_put(internal_esp); | 656 | platform_device_put(internal_pdev); |
621 | internal_esp = NULL; | 657 | internal_pdev = NULL; |
622 | } | 658 | } |
623 | 659 | external_pdev = platform_device_alloc(DRV_MODULE_NAME, 1); | |
624 | external_esp = platform_device_alloc(DRV_MODULE_NAME, 1); | 660 | if (external_pdev && platform_device_add(external_pdev)) { |
625 | if (external_esp && platform_device_add(external_esp)) { | 661 | platform_device_put(external_pdev); |
626 | platform_device_put(external_esp); | 662 | external_pdev = NULL; |
627 | external_esp = NULL; | ||
628 | } | 663 | } |
629 | 664 | ||
630 | if (internal_esp || external_esp) { | 665 | if (internal_pdev || external_pdev) { |
631 | return 0; | 666 | return 0; |
632 | } else { | 667 | } else { |
633 | platform_driver_unregister(&esp_mac_driver); | 668 | platform_driver_unregister(&esp_mac_driver); |
@@ -639,13 +674,13 @@ static void __exit mac_esp_exit(void) | |||
639 | { | 674 | { |
640 | platform_driver_unregister(&esp_mac_driver); | 675 | platform_driver_unregister(&esp_mac_driver); |
641 | 676 | ||
642 | if (internal_esp) { | 677 | if (internal_pdev) { |
643 | platform_device_unregister(internal_esp); | 678 | platform_device_unregister(internal_pdev); |
644 | internal_esp = NULL; | 679 | internal_pdev = NULL; |
645 | } | 680 | } |
646 | if (external_esp) { | 681 | if (external_pdev) { |
647 | platform_device_unregister(external_esp); | 682 | platform_device_unregister(external_pdev); |
648 | external_esp = NULL; | 683 | external_pdev = NULL; |
649 | } | 684 | } |
650 | } | 685 | } |
651 | 686 | ||