Commit da244654c66e78e03668863974ec74c981934c38

Authored by Finn Thain
Committed by James Bottomley
1 parent 09e13e9167

[SCSI] mac_esp: fix for quadras with two esp chips

On the Quadra 900 and 950 there are two ESP chips sharing one IRQ. Because
the shared IRQ is edge-triggered, we must make sure that an IRQ transition
from one chip doesn't go unnoticed when the shared IRQ is already active
due to the other. This patch prevents interrupts getting lost so that both
SCSI busses may be used simultaneously.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

Showing 1 changed file with 58 additions and 23 deletions Side-by-side Diff

drivers/scsi/mac_esp.c
... ... @@ -53,7 +53,8 @@
53 53 void __iomem *pdma_io;
54 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 59 #define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
59 60 platform_get_drvdata((struct platform_device *) \
... ... @@ -443,6 +444,32 @@
443 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 473 static struct esp_driver_ops mac_esp_ops = {
447 474 .esp_write8 = mac_esp_write8,
448 475 .esp_read8 = mac_esp_read8,
... ... @@ -557,10 +584,16 @@
557 584 }
558 585  
559 586 host->irq = IRQ_MAC_SCSI;
560   - err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "Mac ESP",
561   - esp);
562   - if (err < 0)
563   - goto fail_free_priv;
  587 + esp_chips[dev->id] = esp;
  588 + mb();
  589 + if (esp_chips[!dev->id] == NULL) {
  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 598 err = scsi_esp_register(esp, &dev->dev);
566 599 if (err)
... ... @@ -569,7 +602,8 @@
569 602 return 0;
570 603  
571 604 fail_free_irq:
572   - free_irq(host->irq, esp);
  605 + if (esp_chips[!dev->id] == NULL)
  606 + free_irq(host->irq, esp);
573 607 fail_free_priv:
574 608 kfree(mep);
575 609 fail_free_command_block:
... ... @@ -588,7 +622,9 @@
588 622  
589 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 629 kfree(mep);
594 630  
595 631  
596 632  
... ... @@ -615,19 +651,18 @@
615 651 if (err)
616 652 return err;
617 653  
618   - internal_esp = platform_device_alloc(DRV_MODULE_NAME, 0);
619   - if (internal_esp && platform_device_add(internal_esp)) {
620   - platform_device_put(internal_esp);
621   - internal_esp = NULL;
  654 + internal_pdev = platform_device_alloc(DRV_MODULE_NAME, 0);
  655 + if (internal_pdev && platform_device_add(internal_pdev)) {
  656 + platform_device_put(internal_pdev);
  657 + internal_pdev = NULL;
622 658 }
623   -
624   - external_esp = platform_device_alloc(DRV_MODULE_NAME, 1);
625   - if (external_esp && platform_device_add(external_esp)) {
626   - platform_device_put(external_esp);
627   - external_esp = NULL;
  659 + external_pdev = platform_device_alloc(DRV_MODULE_NAME, 1);
  660 + if (external_pdev && platform_device_add(external_pdev)) {
  661 + platform_device_put(external_pdev);
  662 + external_pdev = NULL;
628 663 }
629 664  
630   - if (internal_esp || external_esp) {
  665 + if (internal_pdev || external_pdev) {
631 666 return 0;
632 667 } else {
633 668 platform_driver_unregister(&esp_mac_driver);
634 669  
... ... @@ -639,13 +674,13 @@
639 674 {
640 675 platform_driver_unregister(&esp_mac_driver);
641 676  
642   - if (internal_esp) {
643   - platform_device_unregister(internal_esp);
644   - internal_esp = NULL;
  677 + if (internal_pdev) {
  678 + platform_device_unregister(internal_pdev);
  679 + internal_pdev = NULL;
645 680 }
646   - if (external_esp) {
647   - platform_device_unregister(external_esp);
648   - external_esp = NULL;
  681 + if (external_pdev) {
  682 + platform_device_unregister(external_pdev);
  683 + external_pdev = NULL;
649 684 }
650 685 }
651 686