summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2005-09-13 04:21:29 (GMT)
committerJeff Garzik <jgarzik@pobox.com>2005-09-14 12:19:27 (GMT)
commit923f122573851d18a3832ca808269fa2d5046fb1 (patch)
tree41f30af97a513387389429ad45037651e08d513d
parent905ec87e93bc9e01b15c60035cd6a50c636cbaef (diff)
downloadlinux-923f122573851d18a3832ca808269fa2d5046fb1.tar.xz
[PATCH] sil24: initialization fix
sil24 0.20 didn't use to perform (what seems to be) port multiplier initialization and controller reset 0.10 driver does. This makes some sil24 controllers malfunction. This patch adds PM initialization and controller resetting to initilization and bumps version to 0.21. Please refer to the following thread for more information. http://marc.theaimsgroup.com/?l=linux-ide&m=112582819830324&w=2 http://marc.theaimsgroup.com/?l=linux-ide&m=112636045531060&w=2 Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r--drivers/scsi/sata_sil24.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index cb91894..d8a2f5f 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -41,7 +41,7 @@
#include <asm/io.h>
#define DRV_NAME "sata_sil24"
-#define DRV_VERSION "0.20" /* Silicon Image's preview driver was 0.10 */
+#define DRV_VERSION "0.21" /* Silicon Image's preview driver was 0.10 */
#define NR_PORTS 4
@@ -426,15 +426,11 @@ static void sil24_irq_clear(struct ata_port *ap)
/* unused */
}
-static void sil24_reset_controller(struct ata_port *ap)
+static int __sil24_reset_controller(void *port)
{
- void *port = (void *)ap->ioaddr.cmd_addr;
int cnt;
u32 tmp;
- printk(KERN_NOTICE DRV_NAME
- " ata%u: resetting controller...\n", ap->id);
-
/* Reset controller state. Is this correct? */
writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
readl(port + PORT_CTRL_STAT); /* sync */
@@ -446,9 +442,19 @@ static void sil24_reset_controller(struct ata_port *ap)
if (!(tmp & PORT_CS_DEV_RST))
break;
}
+
if (tmp & PORT_CS_DEV_RST)
- printk(KERN_ERR DRV_NAME
- " ata%u: failed to reset controller\n", ap->id);
+ return -1;
+ return 0;
+}
+
+static void sil24_reset_controller(struct ata_port *ap)
+{
+ printk(KERN_NOTICE DRV_NAME
+ " ata%u: resetting controller...\n", ap->id);
+ if (__sil24_reset_controller((void *)ap->ioaddr.cmd_addr))
+ printk(KERN_ERR DRV_NAME
+ " ata%u: failed to reset controller\n", ap->id);
}
static void sil24_eng_timeout(struct ata_port *ap)
@@ -740,6 +746,15 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Clear interrupts */
writel(0x0fff0fff, port + PORT_IRQ_STAT);
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
+
+ /* Clear port multiplier enable and resume bits */
+ writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
+
+ /* Reset itself */
+ if (__sil24_reset_controller(port))
+ printk(KERN_ERR DRV_NAME
+ "(%s): failed to reset controller\n",
+ pci_name(pdev));
}
/* Turn on interrupts */