sata_promise: preliminary hotplug support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This crude but simple patch enables hotplugging of SATA
disks in the sata_promise driver. Tested successfully on
SATAII150 TX2plus, SATA300 TX2plus, and SATA300 TX4.
The TX4 is significant because of the port_nr-to-ata_nr
remapping that occurs for those chips, which affects
the hotplug status change check for a given port.

While this patch works for me, I consider it preliminary
because it duplicates code and open-codes stuff, so some
cleanups are certainly needed. Also I haven't been able
to test it on first-generation chips yet.

The hotplug checks are high up in the interrupt handling
path, not deep down in error_intr as in ahci/sata_sil24.
That's because the chip doesn't signal hotplug status changes
in the per-port status register: instead a global register
contains hotplug control and status flags for all ports.
I considered following the ahci/sata_sil24 structure, but
that would have required non-trivial changes to the interrupt
handling path, so I chose to keep the hotplug changes simple
and unobtrusive.

/Mikael

(not a formal patch submission, hence no signed-off line)

--- linux-2.6.22-rc5/drivers/ata/sata_promise.c.~1~	2007-06-17 22:03:46.000000000 +0200
+++ linux-2.6.22-rc5/drivers/ata/sata_promise.c	2007-06-17 23:43:51.000000000 +0200
@@ -709,6 +709,9 @@
 	unsigned int i, tmp;
 	unsigned int handled = 0;
 	void __iomem *mmio_base;
+	unsigned int hotplug_offset;
+	u32 hotplug_status;
+	int is_sataii_tx4;
 
 	VPRINTK("ENTER\n");
 
@@ -719,10 +722,22 @@
 
 	mmio_base = host->iomap[PDC_MMIO_BAR];
 
+	/* read and clear hotplug flags for all ports */
+	if (host->ports[0]->flags & PDC_FLAG_GEN_II)
+		hotplug_offset = PDC2_SATA_PLUG_CSR;
+	else
+		hotplug_offset = PDC_SATA_PLUG_CSR;
+	hotplug_status = readl(mmio_base + hotplug_offset);
+	if (hotplug_status & 0xff) {
+		writel(hotplug_status | 0xff, mmio_base + hotplug_offset);
+		printk("%s: hotplug_status %#x\n", __FUNCTION__, hotplug_status);
+	}
+	hotplug_status &= 0xff;	/* clear uninteresting bits */
+
 	/* reading should also clear interrupts */
 	mask = readl(mmio_base + PDC_INT_SEQMASK);
 
-	if (mask == 0xffffffff) {
+	if (mask == 0xffffffff && hotplug_status == 0) {
 		VPRINTK("QUICK EXIT 2\n");
 		return IRQ_NONE;
 	}
@@ -730,16 +745,39 @@
 	spin_lock(&host->lock);
 
 	mask &= 0xffff;		/* only 16 tags possible */
-	if (!mask) {
+	if (!mask && hotplug_status == 0) {
 		VPRINTK("QUICK EXIT 3\n");
 		goto done_irq;
 	}
 
 	writel(mask, mmio_base + PDC_INT_SEQMASK);
 
+	/* XXX: ugly ugly ugly */
+	is_sataii_tx4 = 0;
+	if ((host->ports[0]->flags & (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) ==
+	    (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS))
+		is_sataii_tx4 = 1;
+
 	for (i = 0; i < host->n_ports; i++) {
 		VPRINTK("port %u\n", i);
 		ap = host->ports[i];
+		{
+			static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
+			int ata_nr = i;
+
+			if (is_sataii_tx4)
+				ata_nr = sataii_tx4_port_remap[i];
+
+			if ((hotplug_status & (0x11 << ata_nr)) && ap &&
+			    !(ap->flags & ATA_FLAG_DISABLED)) {
+				struct ata_eh_info *ehi = &ap->eh_info;
+				ata_ehi_clear_desc(ehi);
+				ata_ehi_hotplugged(ehi);
+				ata_ehi_push_desc(ehi, "hotplug_status %#x", hotplug_status);
+				ata_port_freeze(ap);
+				continue;
+			}
+		}
 		tmp = mask & (1 << (i + 1));
 		if (tmp && ap &&
 		    !(ap->flags & ATA_FLAG_DISABLED)) {
@@ -897,9 +935,9 @@
 	tmp = readl(mmio + hotplug_offset);
 	writel(tmp | 0xff, mmio + hotplug_offset);
 
-	/* mask plug/unplug ints */
+	/* unmask plug/unplug ints */
 	tmp = readl(mmio + hotplug_offset);
-	writel(tmp | 0xff0000, mmio + hotplug_offset);
+	writel(tmp & ~0xff0000, mmio + hotplug_offset);
 
 	/* don't initialise TBG or SLEW on 2nd generation chips */
 	if (is_gen2)
-
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux