[PATCH 2.6.15-rc7-git3 3/3] sata_promise: a hotswap implementation using the new hotswap API

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

 



This patch uses the hotswap API in patch 02 to grant the Promise
SATA(II)150 Tx4/Tx2 Plus controllers hotswapping powers.  Also, some
silly integers which should have been unsigned in patch 01 now are.

Signed-off-by:  Luke Kosewski <[email protected]>

Luke Kosewski
29.12.05    Luke Kosewski   <[email protected]>

	* A patch which uses the API in patch 02 in this series to give the
	  Promise SATA150 Tx4/Tx2 Plus and SATAII150 Tx4/Tx2 Plus controllers
	  drive hotswap.
	* Since I noticed a few places where unsigned and signed integers were
	  being cast around, this patch also changed all the signed integers in
	  question into unsigned ones.

	Signed-off-by:  Luke Kosewski <[email protected]>

--- linux-2.6.15-rc7/drivers/scsi/sata_promise.c.old	2005-12-28 23:40:06.000000000 -0500
+++ linux-2.6.15-rc7/drivers/scsi/sata_promise.c	2005-12-29 16:21:55.000000000 -0500
@@ -85,7 +85,7 @@ struct pdc_port_priv {
 };
 
 struct pdc_host_priv {
-	int			hotplug_offset;
+	unsigned int		hotplug_offset;
 };
 
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
@@ -346,10 +346,36 @@ static void pdc_reset_port(struct ata_po
 	readl(mmio);	/* flush */
 }
 
+/* Mask/unmask hotplug interrupts for one channel (ap) */
+static void pdc_chan_hot_status(struct ata_port *ap, int enable)
+{
+	struct pdc_host_priv *hp = ap->host_set->private_data;
+	void *mmio = ap->host_set->mmio_base + hp->hotplug_offset;
+	u8 maskflags;
+
+	if (enable) {
+		/* Clear channel hotplug interrupts */
+		maskflags = readb(mmio);
+		maskflags |= (0x11 << ap->hard_port_no);
+		writeb(maskflags, mmio);
+	}
+
+	maskflags = readb(mmio + 2);
+	if (enable) /* Unmask channel hotplug interrupts */
+		maskflags &= ~(0x11 << ap->hard_port_no);
+	else /* Mask */
+		maskflags |= (0x11 << ap->hard_port_no);
+
+	writeb(maskflags, mmio + 2);
+}
+
 static void pdc_sata_phy_reset(struct ata_port *ap)
 {
 	pdc_reset_port(ap);
+
+	pdc_chan_hot_status(ap, 0);
 	sata_phy_reset(ap);
+	pdc_chan_hot_status(ap, 1);
 }
 
 static void pdc_pata_phy_reset(struct ata_port *ap)
@@ -497,11 +523,13 @@ static void pdc_irq_clear(struct ata_por
 static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct ata_host_set *host_set = dev_instance;
+	struct pdc_host_priv *hp = host_set->private_data;
 	struct ata_port *ap;
 	u32 mask = 0;
 	unsigned int i, tmp;
-	unsigned int handled = 0;
+	unsigned int handled = 0, hotplug_offset = hp->hotplug_offset;
 	void __iomem *mmio_base;
+	u8 plugdata, maskflags;
 
 	VPRINTK("ENTER\n");
 
@@ -525,7 +553,7 @@ static irqreturn_t pdc_interrupt (int ir
 	mask &= 0xffff;		/* only 16 tags possible */
 	if (!mask) {
 		VPRINTK("QUICK EXIT 3\n");
-		goto done_irq;
+		goto try_hotplug;
 	}
 
 	writel(mask, mmio_base + PDC_INT_SEQMASK);
@@ -544,9 +572,27 @@ static irqreturn_t pdc_interrupt (int ir
 		}
 	}
 
-	VPRINTK("EXIT\n");
+try_hotplug:
+	plugdata = readb(mmio_base + hotplug_offset);
+	maskflags = readb(mmio_base + hotplug_offset + 2);
+	plugdata &= ~maskflags;
+	if (plugdata) {
+		writeb(plugdata, mmio_base + hotplug_offset);
+		for (i = 0; i < host_set->n_ports; ++i) {
+			ap = host_set->ports[i];
+			if (!(ap->flags & ATA_FLAG_SATA))
+				continue; /* No PATA support here... continue */
+			if (plugdata & 0x1) /* Check unplug flag */
+				sata_hot_unplug(ap);
+			if ((plugdata >> 4) & 0x1) /* Check plug flag */
+				sata_hot_plug(ap);
+			plugdata >>= 1;
+		}
+		handled = 1;
+	}
+
+	VPRINTK("EXIT 4\n");
 
-done_irq:
 	spin_unlock(&host_set->lock);
 	return IRQ_RETVAL(handled);
 }
@@ -626,7 +672,7 @@ static void pdc_host_init(unsigned int c
 {
 	void __iomem *mmio = pe->mmio_base;
 	struct pdc_host_priv *hp = pe->private_data;
-	int hotplug_offset = hp->hotplug_offset;
+	unsigned int hotplug_offset = hp->hotplug_offset;
 	u32 tmp;
 
 	/*
@@ -644,9 +690,9 @@ static void pdc_host_init(unsigned int c
 	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);
 
 	/* reduce TBG clock to 133 Mhz. */
 	tmp = readl(mmio + PDC_TBG_MODE);


[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux