aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/sata_promise.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 2ad5872fe90c..d2fcb9a6bec2 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -45,7 +45,7 @@
45#include "sata_promise.h" 45#include "sata_promise.h"
46 46
47#define DRV_NAME "sata_promise" 47#define DRV_NAME "sata_promise"
48#define DRV_VERSION "2.08" 48#define DRV_VERSION "2.09"
49 49
50enum { 50enum {
51 PDC_MAX_PORTS = 4, 51 PDC_MAX_PORTS = 4,
@@ -716,6 +716,9 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
716 unsigned int i, tmp; 716 unsigned int i, tmp;
717 unsigned int handled = 0; 717 unsigned int handled = 0;
718 void __iomem *mmio_base; 718 void __iomem *mmio_base;
719 unsigned int hotplug_offset, ata_no;
720 u32 hotplug_status;
721 int is_sataii_tx4;
719 722
720 VPRINTK("ENTER\n"); 723 VPRINTK("ENTER\n");
721 724
@@ -726,10 +729,20 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
726 729
727 mmio_base = host->iomap[PDC_MMIO_BAR]; 730 mmio_base = host->iomap[PDC_MMIO_BAR];
728 731
732 /* read and clear hotplug flags for all ports */
733 if (host->ports[0]->flags & PDC_FLAG_GEN_II)
734 hotplug_offset = PDC2_SATA_PLUG_CSR;
735 else
736 hotplug_offset = PDC_SATA_PLUG_CSR;
737 hotplug_status = readl(mmio_base + hotplug_offset);
738 if (hotplug_status & 0xff)
739 writel(hotplug_status | 0xff, mmio_base + hotplug_offset);
740 hotplug_status &= 0xff; /* clear uninteresting bits */
741
729 /* reading should also clear interrupts */ 742 /* reading should also clear interrupts */
730 mask = readl(mmio_base + PDC_INT_SEQMASK); 743 mask = readl(mmio_base + PDC_INT_SEQMASK);
731 744
732 if (mask == 0xffffffff) { 745 if (mask == 0xffffffff && hotplug_status == 0) {
733 VPRINTK("QUICK EXIT 2\n"); 746 VPRINTK("QUICK EXIT 2\n");
734 return IRQ_NONE; 747 return IRQ_NONE;
735 } 748 }
@@ -737,16 +750,34 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
737 spin_lock(&host->lock); 750 spin_lock(&host->lock);
738 751
739 mask &= 0xffff; /* only 16 tags possible */ 752 mask &= 0xffff; /* only 16 tags possible */
740 if (!mask) { 753 if (mask == 0 && hotplug_status == 0) {
741 VPRINTK("QUICK EXIT 3\n"); 754 VPRINTK("QUICK EXIT 3\n");
742 goto done_irq; 755 goto done_irq;
743 } 756 }
744 757
745 writel(mask, mmio_base + PDC_INT_SEQMASK); 758 writel(mask, mmio_base + PDC_INT_SEQMASK);
746 759
760 is_sataii_tx4 = pdc_is_sataii_tx4(host->ports[0]->flags);
761
747 for (i = 0; i < host->n_ports; i++) { 762 for (i = 0; i < host->n_ports; i++) {
748 VPRINTK("port %u\n", i); 763 VPRINTK("port %u\n", i);
749 ap = host->ports[i]; 764 ap = host->ports[i];
765
766 /* check for a plug or unplug event */
767 ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
768 tmp = hotplug_status & (0x11 << ata_no);
769 if (tmp && ap &&
770 !(ap->flags & ATA_FLAG_DISABLED)) {
771 struct ata_eh_info *ehi = &ap->eh_info;
772 ata_ehi_clear_desc(ehi);
773 ata_ehi_hotplugged(ehi);
774 ata_ehi_push_desc(ehi, "hotplug_status %#x", tmp);
775 ata_port_freeze(ap);
776 ++handled;
777 continue;
778 }
779
780 /* check for a packet interrupt */
750 tmp = mask & (1 << (i + 1)); 781 tmp = mask & (1 << (i + 1));
751 if (tmp && ap && 782 if (tmp && ap &&
752 !(ap->flags & ATA_FLAG_DISABLED)) { 783 !(ap->flags & ATA_FLAG_DISABLED)) {
@@ -902,9 +933,9 @@ static void pdc_host_init(struct ata_host *host)
902 tmp = readl(mmio + hotplug_offset); 933 tmp = readl(mmio + hotplug_offset);
903 writel(tmp | 0xff, mmio + hotplug_offset); 934 writel(tmp | 0xff, mmio + hotplug_offset);
904 935
905 /* mask plug/unplug ints */ 936 /* unmask plug/unplug ints */
906 tmp = readl(mmio + hotplug_offset); 937 tmp = readl(mmio + hotplug_offset);
907 writel(tmp | 0xff0000, mmio + hotplug_offset); 938 writel(tmp & ~0xff0000, mmio + hotplug_offset);
908 939
909 /* don't initialise TBG or SLEW on 2nd generation chips */ 940 /* don't initialise TBG or SLEW on 2nd generation chips */
910 if (is_gen2) 941 if (is_gen2)