aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorMark Lord <mlord@pobox.com>2009-02-25 15:19:20 -0500
committerJeff Garzik <jgarzik@redhat.com>2009-03-24 22:02:41 -0400
commit70f8b79cf3a2eb892a01271fdfbb1903c0c982a8 (patch)
treeca959654f45cf57760470a17742a530a0a1e21b6 /drivers/ata
parent1a660164c291f41b2aa853a7269b310933574ef9 (diff)
[libata] sata_mv: Implement direct FIS transmission via mv_qc_issue_fis().
This is initially needed to work around NCQ errata, whereby the READ_LOG_EXT command sometimes fails when issued in the traditional (sff) fashion. Portions of this code will likely be reused for implementation of the target mode feature later on. Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/sata_mv.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 542e244f37ab..8cad3b2fe554 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -1822,6 +1822,105 @@ static u8 mv_sff_check_status(struct ata_port *ap)
1822} 1822}
1823 1823
1824/** 1824/**
1825 * mv_send_fis - Send a FIS, using the "Vendor-Unique FIS" register
1826 * @fis: fis to be sent
1827 * @nwords: number of 32-bit words in the fis
1828 */
1829static unsigned int mv_send_fis(struct ata_port *ap, u32 *fis, int nwords)
1830{
1831 void __iomem *port_mmio = mv_ap_base(ap);
1832 u32 ifctl, old_ifctl, ifstat;
1833 int i, timeout = 200, final_word = nwords - 1;
1834
1835 /* Initiate FIS transmission mode */
1836 old_ifctl = readl(port_mmio + SATA_IFCTL_OFS);
1837 ifctl = 0x100 | (old_ifctl & 0xf);
1838 writelfl(ifctl, port_mmio + SATA_IFCTL_OFS);
1839
1840 /* Send all words of the FIS except for the final word */
1841 for (i = 0; i < final_word; ++i)
1842 writel(fis[i], port_mmio + VENDOR_UNIQUE_FIS_OFS);
1843
1844 /* Flag end-of-transmission, and then send the final word */
1845 writelfl(ifctl | 0x200, port_mmio + SATA_IFCTL_OFS);
1846 writelfl(fis[final_word], port_mmio + VENDOR_UNIQUE_FIS_OFS);
1847
1848 /*
1849 * Wait for FIS transmission to complete.
1850 * This typically takes just a single iteration.
1851 */
1852 do {
1853 ifstat = readl(port_mmio + SATA_IFSTAT_OFS);
1854 } while (!(ifstat & 0x1000) && --timeout);
1855
1856 /* Restore original port configuration */
1857 writelfl(old_ifctl, port_mmio + SATA_IFCTL_OFS);
1858
1859 /* See if it worked */
1860 if ((ifstat & 0x3000) != 0x1000) {
1861 ata_port_printk(ap, KERN_WARNING,
1862 "%s transmission error, ifstat=%08x\n",
1863 __func__, ifstat);
1864 return AC_ERR_OTHER;
1865 }
1866 return 0;
1867}
1868
1869/**
1870 * mv_qc_issue_fis - Issue a command directly as a FIS
1871 * @qc: queued command to start
1872 *
1873 * Note that the ATA shadow registers are not updated
1874 * after command issue, so the device will appear "READY"
1875 * if polled, even while it is BUSY processing the command.
1876 *
1877 * So we use a status hook to fake ATA_BUSY until the drive changes state.
1878 *
1879 * Note: we don't get updated shadow regs on *completion*
1880 * of non-data commands. So avoid sending them via this function,
1881 * as they will appear to have completed immediately.
1882 *
1883 * GEN_IIE has special registers that we could get the result tf from,
1884 * but earlier chipsets do not. For now, we ignore those registers.
1885 */
1886static unsigned int mv_qc_issue_fis(struct ata_queued_cmd *qc)
1887{
1888 struct ata_port *ap = qc->ap;
1889 struct mv_port_priv *pp = ap->private_data;
1890 struct ata_link *link = qc->dev->link;
1891 u32 fis[5];
1892 int err = 0;
1893
1894 ata_tf_to_fis(&qc->tf, link->pmp, 1, (void *)fis);
1895 err = mv_send_fis(ap, fis, sizeof(fis) / sizeof(fis[0]));
1896 if (err)
1897 return err;
1898
1899 switch (qc->tf.protocol) {
1900 case ATAPI_PROT_PIO:
1901 pp->pp_flags |= MV_PP_FLAG_FAKE_ATA_BUSY;
1902 /* fall through */
1903 case ATAPI_PROT_NODATA:
1904 ap->hsm_task_state = HSM_ST_FIRST;
1905 break;
1906 case ATA_PROT_PIO:
1907 pp->pp_flags |= MV_PP_FLAG_FAKE_ATA_BUSY;
1908 if (qc->tf.flags & ATA_TFLAG_WRITE)
1909 ap->hsm_task_state = HSM_ST_FIRST;
1910 else
1911 ap->hsm_task_state = HSM_ST;
1912 break;
1913 default:
1914 ap->hsm_task_state = HSM_ST_LAST;
1915 break;
1916 }
1917
1918 if (qc->tf.flags & ATA_TFLAG_POLLING)
1919 ata_pio_queue_task(ap, qc, 0);
1920 return 0;
1921}
1922
1923/**
1825 * mv_qc_issue - Initiate a command to the host 1924 * mv_qc_issue - Initiate a command to the host
1826 * @qc: queued command to start 1925 * @qc: queued command to start
1827 * 1926 *
@@ -1896,6 +1995,23 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
1896 mv_stop_edma(ap); 1995 mv_stop_edma(ap);
1897 mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); 1996 mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs);
1898 mv_pmp_select(ap, qc->dev->link->pmp); 1997 mv_pmp_select(ap, qc->dev->link->pmp);
1998
1999 if (qc->tf.command == ATA_CMD_READ_LOG_EXT) {
2000 struct mv_host_priv *hpriv = ap->host->private_data;
2001 /*
2002 * Workaround for 88SX60x1 FEr SATA#25 (part 2).
2003 *
2004 * After any NCQ error, the READ_LOG_EXT command
2005 * from libata-eh *must* use mv_qc_issue_fis().
2006 * Otherwise it might fail, due to chip errata.
2007 *
2008 * Rather than special-case it, we'll just *always*
2009 * use this method here for READ_LOG_EXT, making for
2010 * easier testing.
2011 */
2012 if (IS_GEN_II(hpriv))
2013 return mv_qc_issue_fis(qc);
2014 }
1899 return ata_sff_qc_issue(qc); 2015 return ata_sff_qc_issue(qc);
1900} 2016}
1901 2017