Skip to content

Commit

Permalink
[PATCH] sil24: add sil24_restart_controller
Browse files Browse the repository at this point in the history
When an error condition is raised by device via D2H FIS or SDB.  sil24
controller should be restarted by setting PORT_CS_INIT and waiting
until PORT_CS_RDY is asserted instead of resetting the controller.
This patch implements sil24_restart_controller for those cases.  This
patch also makes sure that PORT_CS_RDY is asserted on
sil24_reset_controller completion.

Signed-off-by: Tejun Heo <htejun@gmail.com>

--

Jeff, delay is reduced to 1us and cnt increased to 10k.  My sil3124
turns on PORT_CS_RDY on the second iteration even without any delay.
I think 10k * 1us should be more than enough.

I tried to convert both restart and reset to use msleep's with work
queue, but if we do that, host_set lock should be released after
initiating restart or reset, leading to race condition among
reset/restart, other interrupts and timeout.  Implementing
synchronization among those in low-level driver doesn't seem right.
Well, reduced timeout should work for the time being.

Thanks.
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
  • Loading branch information
Tejun Heo authored and Jeff Garzik committed Nov 18, 2005
1 parent fc71fe4 commit 7d1ce68
Showing 1 changed file with 32 additions and 3 deletions.
35 changes: 32 additions & 3 deletions drivers/scsi/sata_sil24.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,31 @@ static void sil24_irq_clear(struct ata_port *ap)
/* unused */
}

static int __sil24_restart_controller(void __iomem *port)
{
u32 tmp;
int cnt;

writel(PORT_CS_INIT, port + PORT_CTRL_STAT);

/* Max ~10ms */
for (cnt = 0; cnt < 10000; cnt++) {
tmp = readl(port + PORT_CTRL_STAT);
if (tmp & PORT_CS_RDY)
return 0;
udelay(1);
}

return -1;
}

static void sil24_restart_controller(struct ata_port *ap)
{
if (__sil24_restart_controller((void __iomem *)ap->ioaddr.cmd_addr))
printk(KERN_ERR DRV_NAME
" ata%u: failed to restart controller\n", ap->id);
}

static int __sil24_reset_controller(void __iomem *port)
{
int cnt;
Expand All @@ -505,7 +530,11 @@ static int __sil24_reset_controller(void __iomem *port)

if (tmp & PORT_CS_DEV_RST)
return -1;
return 0;

if (tmp & PORT_CS_RDY)
return 0;

return __sil24_restart_controller(port);
}

static void sil24_reset_controller(struct ata_port *ap)
Expand Down Expand Up @@ -577,19 +606,19 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
*/
sil24_update_tf(ap);
err_mask = ac_err_mask(pp->tf.command);
sil24_restart_controller(ap);
} else {
/*
* Other errors. libata currently doesn't have any
* mechanism to report these errors. Just turn on
* ATA_ERR.
*/
err_mask = AC_ERR_OTHER;
sil24_reset_controller(ap);
}

if (qc)
ata_qc_complete(qc, err_mask);

sil24_reset_controller(ap);
}

static inline void sil24_host_intr(struct ata_port *ap)
Expand Down

0 comments on commit 7d1ce68

Please sign in to comment.