linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFT] sata_promise: decode and report error reasons
@ 2007-03-01  1:58 Mikael Pettersson
  2007-03-05  4:35 ` Tejun Heo
  0 siblings, 1 reply; 6+ messages in thread
From: Mikael Pettersson @ 2007-03-01  1:58 UTC (permalink / raw)
  To: linux-ide

This is a preliminary patch to add error reason decoding
and reporting to sata_promise. It's fairly simplistic but
should log all error info the controller is able to provide.

Works for me, but my test rig hardly ever throws any errors.
Testing by those that experience frequent errors would be
most welcome.

libata experts may want to check if my mapping to libata
error codes and eh actions is OK.

/Mikael

--- linux-2.6.21-rc2/drivers/ata/sata_promise.c.~1~	2007-02-28 13:32:46.000000000 +0100
+++ linux-2.6.21-rc2/drivers/ata/sata_promise.c	2007-03-01 01:52:35.000000000 +0100
@@ -70,8 +70,37 @@ enum {
 	PDC_TBG_MODE		= 0x41C, /* TBG mode (not SATAII) */
 	PDC_SLEW_CTL		= 0x470, /* slew rate control reg (not SATAII) */
 
-	PDC_ERR_MASK		= (1<<19) | (1<<20) | (1<<21) | (1<<22) |
-				  (1<<8) | (1<<9) | (1<<10),
+	/* PDC_GLOBAL_CTL bit definitions */
+	PDC_PH_ERR		= (1 << 8),
+	PDC_SH_ERR		= (1 << 9),
+	PDC_DH_ERR		= (1 << 10),
+	PDC2_HTO_ERR		= (1 << 12),
+	PDC2_ATA_HBA_ERR	= (1 << 13),
+	PDC2_ATA_DMA_CNT_ERR	= (1 << 14),
+	PDC_OVERRUN_ERR		= (1 << 19),
+	PDC_UNDERRUN_ERR	= (1 << 20),
+	PDC_DRIVE_ERR		= (1 << 21),
+	PDC_PCI_SYS_ERR		= (1 << 22),
+	PDC1_PCI_PARITY_ERR	= (1 << 23),	/* 1st gen only */
+	PDC1_ERR_MASK		= PDC1_PCI_PARITY_ERR,
+	PDC2_ERR_MASK		= PDC2_HTO_ERR | PDC2_ATA_HBA_ERR | PDC2_ATA_DMA_CNT_ERR,
+	PDC_ERR_MASK		= (PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | PDC_OVERRUN_ERR
+				   | PDC_UNDERRUN_ERR | PDC_DRIVE_ERR | PDC_PCI_SYS_ERR
+				   | PDC2_ERR_MASK | PDC1_ERR_MASK),
+
+	/* Promise-specific SError bit definitions */
+	PDC_SERR_COMWAKE	= (1 << 18),
+	PDC_SERR_10BTO8B	= (1 << 19),
+	PDC_SERR_DISPARITY	= (1 << 20),
+	PDC_SERR_CRC		= (1 << 21),
+	PDC_SERR_HANDSHAKE	= (1 << 22),
+	PDC_SERR_LINK_SEQ	= (1 << 23),
+	PDC2_SERR_STATE_TRANS	= (1 << 24),
+	PDC_SERR_FIS_TYPE	= (1 << 25),
+	PDC2_SERR_MASK		= PDC2_SERR_STATE_TRANS,
+	PDC_SERR_MASK		= (PDC_SERR_COMWAKE | PDC_SERR_10BTO8B | PDC_SERR_DISPARITY
+				   | PDC_SERR_CRC | PDC_SERR_HANDSHAKE | PDC_SERR_LINK_SEQ
+				   | PDC_SERR_FIS_TYPE | PDC2_SERR_MASK),
 
 	board_2037x		= 0,	/* FastTrak S150 TX2plus */
 	board_20319		= 1,	/* FastTrak S150 TX4 */
@@ -590,17 +619,67 @@ static void pdc_post_internal_cmd(struct
 		pdc_reset_port(ap);
 }
 
+static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc, u32 port_status)
+{
+	struct pdc_host_priv *hp = ap->host->private_data;
+	struct ata_eh_info *ehi = &ap->eh_info;
+	unsigned int err_mask = 0, action = 0;
+	u32 serror;
+
+	ata_ehi_clear_desc(ehi);
+
+	serror = 0;
+	if (sata_scr_valid(ap)) {
+		serror = pdc_sata_scr_read(ap, SCR_ERROR);
+		if (!(hp->flags & PDC_FLAG_GEN_II))
+			serror &= ~PDC2_SERR_MASK;
+	}
+
+	printk("%s: port_status 0x%08x serror 0x%08x\n", __FUNCTION__, port_status, serror);
+
+	ata_ehi_push_desc(ehi, "port_status 0x%08x", port_status);
+
+	if (serror & PDC_SERR_MASK) {
+		err_mask |= AC_ERR_ATA_BUS;
+		ata_ehi_push_desc(ehi, ", serror 0x%08x", serror);
+	}
+	if (port_status & PDC_DRIVE_ERR)
+		err_mask |= AC_ERR_DEV;
+	if (port_status & PDC2_HTO_ERR)
+		err_mask |= AC_ERR_TIMEOUT;
+	if (port_status & (PDC_UNDERRUN_ERR | PDC_OVERRUN_ERR | PDC2_ATA_DMA_CNT_ERR
+			   | PDC2_ATA_HBA_ERR))
+		err_mask |= AC_ERR_ATA_BUS;
+	if (port_status & (PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | PDC_PCI_SYS_ERR
+			   | PDC1_PCI_PARITY_ERR))
+		err_mask |= AC_ERR_HOST_BUS;
+
+	action |= ATA_EH_SOFTRESET;
+
+	ehi->serror |= serror;
+	ehi->action |= action;
+
+	qc->err_mask |= err_mask;
+
+	ata_port_freeze(ap);
+}
+
 static inline unsigned int pdc_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc)
 {
 	unsigned int handled = 0;
-	u32 tmp;
-	void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
+	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
+	struct pdc_host_priv *hp = ap->host->private_data;
+	u32 port_status;
 
-	tmp = readl(mmio);
-	if (tmp & PDC_ERR_MASK) {
-		qc->err_mask |= AC_ERR_DEV;
-		pdc_reset_port(ap);
+	port_status = readl(port_mmio + PDC_GLOBAL_CTL);
+	if (hp->flags & PDC_FLAG_GEN_II)
+		port_status &= ~PDC1_ERR_MASK;
+	else
+		port_status &= ~PDC2_ERR_MASK;
+	if (unlikely(port_status & PDC_ERR_MASK)) {
+		pdc_error_intr(ap, qc, port_status);
+		return 1;
 	}
 
 	switch (qc->tf.protocol) {

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-03-08 10:09 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-01  1:58 [RFT] sata_promise: decode and report error reasons Mikael Pettersson
2007-03-05  4:35 ` Tejun Heo
2007-03-07 19:53   ` Mikael Pettersson
2007-03-07 22:45     ` Jeff Garzik
2007-03-08 10:09       ` Mikael Pettersson
2007-03-08  2:44     ` Tejun Heo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).