sil24 doesn't have single TF image. Result TF is bound to each command. As libata now allows TF-less implementation, kill ops->tf_read and use ata_std_noop_check_status() for check_status callbacks. Result TF is loaded directly from LRAM into qc->result_tf if necessary. This patch also makes sil24_hardreset() to request followup SRST as that's the only way to wait for !BSY. Note that the original implementation never worked - if the cached status was !BSY, ata_busy_sleep() finished immediately; otherwise, it timed out regardless of the actual device status. Signed-off-by: Tejun Heo <htejun@xxxxxxxxx> --- drivers/scsi/sata_sil24.c | 58 +++++++++++++++------------------------------ 1 files changed, 19 insertions(+), 39 deletions(-) 38e62fb359d3447790ceb43f47ab8c473894f05f diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 89d5d70..def1378 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -311,7 +311,6 @@ static struct sil24_cerr_info { struct sil24_port_priv { union sil24_cmd_block *cmd_block; /* 32 cmd blocks */ dma_addr_t cmd_block_dma; /* DMA base addr for them */ - struct ata_taskfile tf; /* Cached taskfile registers */ }; /* ap->host_set->private_data */ @@ -321,10 +320,8 @@ struct sil24_host_priv { }; static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev); -static u8 sil24_check_status(struct ata_port *ap); static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); -static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes); static void sil24_qc_prep(struct ata_queued_cmd *qc); static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); @@ -378,12 +375,10 @@ static const struct ata_port_operations .dev_config = sil24_dev_config, - .check_status = sil24_check_status, - .check_altstatus = sil24_check_status, + .check_status = ata_noop_check_status, + .check_altstatus = ata_noop_check_status, .dev_select = ata_noop_dev_select, - .tf_read = sil24_tf_read, - .probe_reset = sil24_probe_reset, .qc_prep = sil24_qc_prep, @@ -460,21 +455,15 @@ static void sil24_dev_config(struct ata_ writel(PORT_CS_CDB16, port + PORT_CTRL_CLR); } -static inline void sil24_update_tf(struct ata_port *ap) +static void sil24_read_tf(struct ata_port *ap, int tag, struct ata_taskfile *tf) { - struct sil24_port_priv *pp = ap->private_data; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; - struct sil24_prb __iomem *prb = port; + struct sil24_prb __iomem *prb; u8 fis[6 * 4]; - memcpy_fromio(fis, prb->fis, 6 * 4); - ata_tf_from_fis(fis, &pp->tf); -} - -static u8 sil24_check_status(struct ata_port *ap) -{ - struct sil24_port_priv *pp = ap->private_data; - return pp->tf.command; + prb = port + PORT_LRAM + tag * PORT_LRAM_SLOT_SZ; + memcpy_fromio(fis, prb->fis, sizeof(fis)); + ata_tf_from_fis(fis, tf); } static int sil24_scr_map[] = { @@ -505,12 +494,6 @@ static void sil24_scr_write(struct ata_p } } -static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) -{ - struct sil24_port_priv *pp = ap->private_data; - *tf = pp->tf; -} - static int sil24_init_port(struct ata_port *ap) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; @@ -533,6 +516,7 @@ static int sil24_softreset(struct ata_po struct sil24_port_priv *pp = ap->private_data; struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; dma_addr_t paddr = pp->cmd_block_dma; + struct ata_taskfile tf; u32 mask, irq_stat; const char *reason; @@ -572,8 +556,8 @@ static int sil24_softreset(struct ata_po goto err; } - sil24_update_tf(ap); - *class = ata_dev_classify(&pp->tf); + sil24_read_tf(ap, 0, &tf); + *class = ata_dev_classify(&tf); if (*class == ATA_DEV_UNKNOWN) *class = ATA_DEV_NONE; @@ -608,7 +592,7 @@ static int sil24_hardreset(struct ata_po /* SStatus oscillates between zero and valid status after * DEV_RST, debounce it. */ - rc = sata_phy_debounce(ap, sata_deb_timing_eh); + rc = sata_phy_debounce(ap, sata_deb_timing_before_fsrst); if (rc) { reason = "PHY debouncing failed"; goto err; @@ -621,15 +605,13 @@ static int sil24_hardreset(struct ata_po goto err; } - if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - reason = "device not ready"; - goto err; - } - - /* sil24 doesn't report device class code after hardreset, - * leave *class alone. + /* Sil24 doesn't store signature FIS after hardreset, so we + * can't wait for BSY to clear. Some devices take a long time + * to get ready and those devices will choke if we don't wait + * for BSY clearance here. Tell libata to perform follow-up + * softreset. */ - return 0; + return -EAGAIN; err: ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason); @@ -816,7 +798,7 @@ static void sil24_error_intr(struct ata_ /* record error info */ qc = ata_qc_from_tag(ap, ap->active_tag); if (qc) { - sil24_update_tf(ap); + sil24_read_tf(ap, sil24_tag(qc->tag), &qc->result_tf); qc->err_mask |= err_mask; } else ehi->err_mask |= err_mask; @@ -834,7 +816,7 @@ static void sil24_error_intr(struct ata_ static void sil24_finish_qc(struct ata_queued_cmd *qc) { if (qc->flags & ATA_QCFLAG_RESULT_TF) - sil24_update_tf(qc->ap); + sil24_read_tf(qc->ap, sil24_tag(qc->tag), &qc->result_tf); } static inline void sil24_host_intr(struct ata_port *ap) @@ -954,8 +936,6 @@ static int sil24_port_start(struct ata_p if (!pp) goto err_out; - pp->tf.command = ATA_DRDY; - cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL); if (!cb) goto err_out_pp; -- 1.3.2 - : send the line "unsubscribe linux-ide" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html