aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-09-23 00:14:12 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-12 14:55:41 -0400
commitae791c05694d7391ee9261a0450a50f7e95aedfd (patch)
tree73e3fbcd6cdfe667b5dcc512daaec7fb5941a132
parentda917d69d0ea63f5390716cba6e77f490ce96df9 (diff)
libata-pmp-prep: implement ATA_LFLAG_NO_SRST, ASSUME_ATA and ASSUME_SEMB
Some links on some PMPs locks up on SRST and/or report incorrect device signature. Implement ATA_LFLAG_NO_SRST, ASSUME_ATA and ASSUME_SEMB to handle these quirky links. NO_SRST makes EH avoid SRST. ASSUME_ATA and SEMB forces class code to ATA and SEMB_UNSUP respectively. Note that SEMB isn't currently supported yet so the _UNSUP variant is used. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/libata-eh.c42
-rw-r--r--include/linux/libata.h4
2 files changed, 36 insertions, 10 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 5244723952c2..7be04bd30bfe 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1906,14 +1906,18 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
1906 return 0; 1906 return 0;
1907} 1907}
1908 1908
1909static int ata_eh_followup_srst_needed(int rc, int classify, 1909static int ata_eh_followup_srst_needed(struct ata_link *link,
1910 int rc, int classify,
1910 const unsigned int *classes) 1911 const unsigned int *classes)
1911{ 1912{
1913 if (link->flags & ATA_LFLAG_NO_SRST)
1914 return 0;
1912 if (rc == -EAGAIN) 1915 if (rc == -EAGAIN)
1913 return 1; 1916 return 1;
1914 if (rc != 0) 1917 if (rc != 0)
1915 return 0; 1918 return 0;
1916 if (classify && classes[0] == ATA_DEV_UNKNOWN) 1919 if (classify && !(link->flags & ATA_LFLAG_ASSUME_CLASS) &&
1920 classes[0] == ATA_DEV_UNKNOWN)
1917 return 1; 1921 return 1;
1918 return 0; 1922 return 0;
1919} 1923}
@@ -1940,7 +1944,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
1940 */ 1944 */
1941 action = ehc->i.action; 1945 action = ehc->i.action;
1942 ehc->i.action &= ~ATA_EH_RESET_MASK; 1946 ehc->i.action &= ~ATA_EH_RESET_MASK;
1943 if (softreset && (!hardreset || (!sata_set_spd_needed(link) && 1947 if (softreset && (!hardreset || (!(link->flags & ATA_LFLAG_NO_SRST) &&
1948 !sata_set_spd_needed(link) &&
1944 !(action & ATA_EH_HARDRESET)))) 1949 !(action & ATA_EH_HARDRESET))))
1945 ehc->i.action |= ATA_EH_SOFTRESET; 1950 ehc->i.action |= ATA_EH_SOFTRESET;
1946 else 1951 else
@@ -2003,7 +2008,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
2003 rc = ata_do_reset(link, reset, classes, deadline); 2008 rc = ata_do_reset(link, reset, classes, deadline);
2004 2009
2005 if (reset == hardreset && 2010 if (reset == hardreset &&
2006 ata_eh_followup_srst_needed(rc, classify, classes)) { 2011 ata_eh_followup_srst_needed(link, rc, classify, classes)) {
2007 /* okay, let's do follow-up softreset */ 2012 /* okay, let's do follow-up softreset */
2008 reset = softreset; 2013 reset = softreset;
2009 2014
@@ -2018,8 +2023,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
2018 ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK); 2023 ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK);
2019 rc = ata_do_reset(link, reset, classes, deadline); 2024 rc = ata_do_reset(link, reset, classes, deadline);
2020 2025
2021 if (rc == 0 && classify && 2026 if (rc == 0 && classify && classes[0] == ATA_DEV_UNKNOWN &&
2022 classes[0] == ATA_DEV_UNKNOWN) { 2027 !(link->flags & ATA_LFLAG_ASSUME_CLASS)) {
2023 ata_link_printk(link, KERN_ERR, 2028 ata_link_printk(link, KERN_ERR,
2024 "classification failed\n"); 2029 "classification failed\n");
2025 rc = -EINVAL; 2030 rc = -EINVAL;
@@ -2027,6 +2032,10 @@ int ata_eh_reset(struct ata_link *link, int classify,
2027 } 2032 }
2028 } 2033 }
2029 2034
2035 /* if we skipped follow-up srst, clear rc */
2036 if (rc == -EAGAIN)
2037 rc = 0;
2038
2030 if (rc && try < ARRAY_SIZE(ata_eh_reset_timeouts)) { 2039 if (rc && try < ARRAY_SIZE(ata_eh_reset_timeouts)) {
2031 unsigned long now = jiffies; 2040 unsigned long now = jiffies;
2032 2041
@@ -2051,12 +2060,25 @@ int ata_eh_reset(struct ata_link *link, int classify,
2051 if (rc == 0) { 2060 if (rc == 0) {
2052 u32 sstatus; 2061 u32 sstatus;
2053 2062
2054 /* After the reset, the device state is PIO 0 and the 2063 ata_link_for_each_dev(dev, link) {
2055 * controller state is undefined. Record the mode. 2064 /* After the reset, the device state is PIO 0
2056 */ 2065 * and the controller state is undefined.
2057 ata_link_for_each_dev(dev, link) 2066 * Record the mode.
2067 */
2058 dev->pio_mode = XFER_PIO_0; 2068 dev->pio_mode = XFER_PIO_0;
2059 2069
2070 if (ata_link_offline(link))
2071 continue;
2072
2073 /* apply class override and convert UNKNOWN to NONE */
2074 if (link->flags & ATA_LFLAG_ASSUME_ATA)
2075 classes[dev->devno] = ATA_DEV_ATA;
2076 else if (link->flags & ATA_LFLAG_ASSUME_SEMB)
2077 classes[dev->devno] = ATA_DEV_SEMB_UNSUP; /* not yet */
2078 else if (classes[dev->devno] == ATA_DEV_UNKNOWN)
2079 classes[dev->devno] = ATA_DEV_NONE;
2080 }
2081
2060 /* record current link speed */ 2082 /* record current link speed */
2061 if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0) 2083 if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0)
2062 link->sata_spd = (sstatus >> 4) & 0xf; 2084 link->sata_spd = (sstatus >> 4) & 0xf;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index f9f81fd93293..6266fffb0eb3 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -165,6 +165,10 @@ enum {
165 ATA_LFLAG_HRST_TO_RESUME = (1 << 0), /* hardreset to resume link */ 165 ATA_LFLAG_HRST_TO_RESUME = (1 << 0), /* hardreset to resume link */
166 ATA_LFLAG_SKIP_D2H_BSY = (1 << 1), /* can't wait for the first D2H 166 ATA_LFLAG_SKIP_D2H_BSY = (1 << 1), /* can't wait for the first D2H
167 * Register FIS clearing BSY */ 167 * Register FIS clearing BSY */
168 ATA_LFLAG_NO_SRST = (1 << 2), /* avoid softreset */
169 ATA_LFLAG_ASSUME_ATA = (1 << 3), /* assume ATA class */
170 ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */
171 ATA_LFLAG_ASSUME_CLASS = ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB,
168 172
169 /* struct ata_port flags */ 173 /* struct ata_port flags */
170 ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ 174 ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */