|
@@ -489,23 +489,26 @@ static unsigned int scc_devchk (struct ata_port *ap,
|
|
|
* Note: Original code is ata_bus_post_reset().
|
|
|
*/
|
|
|
|
|
|
-static void scc_bus_post_reset (struct ata_port *ap, unsigned int devmask)
|
|
|
+static int scc_bus_post_reset(struct ata_port *ap, unsigned int devmask,
|
|
|
+ unsigned long deadline)
|
|
|
{
|
|
|
struct ata_ioports *ioaddr = &ap->ioaddr;
|
|
|
unsigned int dev0 = devmask & (1 << 0);
|
|
|
unsigned int dev1 = devmask & (1 << 1);
|
|
|
- unsigned long timeout;
|
|
|
+ int rc;
|
|
|
|
|
|
/* if device 0 was found in ata_devchk, wait for its
|
|
|
* BSY bit to clear
|
|
|
*/
|
|
|
- if (dev0)
|
|
|
- ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
|
|
|
+ if (dev0) {
|
|
|
+ rc = ata_wait_ready(ap, deadline);
|
|
|
+ if (rc && rc != -ENODEV)
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
|
|
|
/* if device 1 was found in ata_devchk, wait for
|
|
|
* register access, then wait for BSY to clear
|
|
|
*/
|
|
|
- timeout = jiffies + ATA_TMOUT_BOOT;
|
|
|
while (dev1) {
|
|
|
u8 nsect, lbal;
|
|
|
|
|
@@ -514,14 +517,15 @@ static void scc_bus_post_reset (struct ata_port *ap, unsigned int devmask)
|
|
|
lbal = in_be32(ioaddr->lbal_addr);
|
|
|
if ((nsect == 1) && (lbal == 1))
|
|
|
break;
|
|
|
- if (time_after(jiffies, timeout)) {
|
|
|
- dev1 = 0;
|
|
|
- break;
|
|
|
- }
|
|
|
+ if (time_after(jiffies, deadline))
|
|
|
+ return -EBUSY;
|
|
|
msleep(50); /* give drive a breather */
|
|
|
}
|
|
|
- if (dev1)
|
|
|
- ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
|
|
|
+ if (dev1) {
|
|
|
+ rc = ata_wait_ready(ap, deadline);
|
|
|
+ if (rc && rc != -ENODEV)
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
|
|
|
/* is all this really necessary? */
|
|
|
ap->ops->dev_select(ap, 0);
|
|
@@ -529,6 +533,8 @@ static void scc_bus_post_reset (struct ata_port *ap, unsigned int devmask)
|
|
|
ap->ops->dev_select(ap, 1);
|
|
|
if (dev0)
|
|
|
ap->ops->dev_select(ap, 0);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -537,8 +543,8 @@ static void scc_bus_post_reset (struct ata_port *ap, unsigned int devmask)
|
|
|
* Note: Original code is ata_bus_softreset().
|
|
|
*/
|
|
|
|
|
|
-static unsigned int scc_bus_softreset (struct ata_port *ap,
|
|
|
- unsigned int devmask)
|
|
|
+static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
|
|
|
+ unsigned long deadline)
|
|
|
{
|
|
|
struct ata_ioports *ioaddr = &ap->ioaddr;
|
|
|
|
|
@@ -570,7 +576,7 @@ static unsigned int scc_bus_softreset (struct ata_port *ap,
|
|
|
if (scc_check_status(ap) == 0xFF)
|
|
|
return 0;
|
|
|
|
|
|
- scc_bus_post_reset(ap, devmask);
|
|
|
+ scc_bus_post_reset(ap, devmask, deadline);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -579,11 +585,13 @@ static unsigned int scc_bus_softreset (struct ata_port *ap,
|
|
|
* scc_std_softreset - reset host port via ATA SRST
|
|
|
* @ap: port to reset
|
|
|
* @classes: resulting classes of attached devices
|
|
|
+ * @deadline: deadline jiffies for the operation
|
|
|
*
|
|
|
* Note: Original code is ata_std_softreset().
|
|
|
*/
|
|
|
|
|
|
-static int scc_std_softreset (struct ata_port *ap, unsigned int *classes)
|
|
|
+static int scc_std_softreset (struct ata_port *ap, unsigned int *classes,
|
|
|
+ unsigned long deadline)
|
|
|
{
|
|
|
unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
|
|
|
unsigned int devmask = 0, err_mask;
|
|
@@ -607,7 +615,7 @@ static int scc_std_softreset (struct ata_port *ap, unsigned int *classes)
|
|
|
|
|
|
/* issue bus reset */
|
|
|
DPRINTK("about to softreset, devmask=%x\n", devmask);
|
|
|
- err_mask = scc_bus_softreset(ap, devmask);
|
|
|
+ err_mask = scc_bus_softreset(ap, devmask, deadline);
|
|
|
if (err_mask) {
|
|
|
ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
|
|
|
err_mask);
|
|
@@ -676,10 +684,11 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc)
|
|
|
|
|
|
if (reg & INTSTS_BMSINT) {
|
|
|
unsigned int classes;
|
|
|
+ unsigned long deadline = jiffies + ATA_TMOUT_BOOT;
|
|
|
printk(KERN_WARNING "%s: Internal Bus Error\n", DRV_NAME);
|
|
|
out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMSINT);
|
|
|
/* TBD: SW reset */
|
|
|
- scc_std_softreset(ap, &classes);
|
|
|
+ scc_std_softreset(ap, &classes, deadline);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -862,9 +871,10 @@ static void scc_bmdma_freeze (struct ata_port *ap)
|
|
|
/**
|
|
|
* scc_pata_prereset - prepare for reset
|
|
|
* @ap: ATA port to be reset
|
|
|
+ * @deadline: deadline jiffies for the operation
|
|
|
*/
|
|
|
|
|
|
-static int scc_pata_prereset (struct ata_port *ap, unsigned long deadline)
|
|
|
+static int scc_pata_prereset(struct ata_port *ap, unsigned long deadline)
|
|
|
{
|
|
|
ap->cbl = ATA_CBL_PATA80;
|
|
|
return ata_std_prereset(ap, deadline);
|