aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/mac_esp.c81
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};
56static struct platform_device *internal_esp, *external_esp; 56static struct platform_device *internal_pdev, *external_pdev;
57static 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
447static 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
446static struct esp_driver_ops mac_esp_ops = { 473static 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
571fail_free_irq: 604fail_free_irq:
572 free_irq(host->irq, esp); 605 if (esp_chips[!dev->id] == NULL)
606 free_irq(host->irq, esp);
573fail_free_priv: 607fail_free_priv:
574 kfree(mep); 608 kfree(mep);
575fail_free_command_block: 609fail_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