diff options
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r-- | drivers/ata/libata-eh.c | 146 |
1 files changed, 139 insertions, 7 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 79711b64054b..a04488f0de88 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <scsi/scsi_eh.h> | 40 | #include <scsi/scsi_eh.h> |
41 | #include <scsi/scsi_device.h> | 41 | #include <scsi/scsi_device.h> |
42 | #include <scsi/scsi_cmnd.h> | 42 | #include <scsi/scsi_cmnd.h> |
43 | #include <scsi/scsi_dbg.h> | ||
43 | #include "../scsi/scsi_transport_api.h" | 44 | #include "../scsi/scsi_transport_api.h" |
44 | 45 | ||
45 | #include <linux/libata.h> | 46 | #include <linux/libata.h> |
@@ -999,7 +1000,9 @@ static void __ata_port_freeze(struct ata_port *ap) | |||
999 | * ata_port_freeze - abort & freeze port | 1000 | * ata_port_freeze - abort & freeze port |
1000 | * @ap: ATA port to freeze | 1001 | * @ap: ATA port to freeze |
1001 | * | 1002 | * |
1002 | * Abort and freeze @ap. | 1003 | * Abort and freeze @ap. The freeze operation must be called |
1004 | * first, because some hardware requires special operations | ||
1005 | * before the taskfile registers are accessible. | ||
1003 | * | 1006 | * |
1004 | * LOCKING: | 1007 | * LOCKING: |
1005 | * spin_lock_irqsave(host lock) | 1008 | * spin_lock_irqsave(host lock) |
@@ -1013,8 +1016,8 @@ int ata_port_freeze(struct ata_port *ap) | |||
1013 | 1016 | ||
1014 | WARN_ON(!ap->ops->error_handler); | 1017 | WARN_ON(!ap->ops->error_handler); |
1015 | 1018 | ||
1016 | nr_aborted = ata_port_abort(ap); | ||
1017 | __ata_port_freeze(ap); | 1019 | __ata_port_freeze(ap); |
1020 | nr_aborted = ata_port_abort(ap); | ||
1018 | 1021 | ||
1019 | return nr_aborted; | 1022 | return nr_aborted; |
1020 | } | 1023 | } |
@@ -2110,6 +2113,116 @@ void ata_eh_autopsy(struct ata_port *ap) | |||
2110 | } | 2113 | } |
2111 | 2114 | ||
2112 | /** | 2115 | /** |
2116 | * ata_get_cmd_descript - get description for ATA command | ||
2117 | * @command: ATA command code to get description for | ||
2118 | * | ||
2119 | * Return a textual description of the given command, or NULL if the | ||
2120 | * command is not known. | ||
2121 | * | ||
2122 | * LOCKING: | ||
2123 | * None | ||
2124 | */ | ||
2125 | const char *ata_get_cmd_descript(u8 command) | ||
2126 | { | ||
2127 | #ifdef CONFIG_ATA_VERBOSE_ERROR | ||
2128 | static const struct | ||
2129 | { | ||
2130 | u8 command; | ||
2131 | const char *text; | ||
2132 | } cmd_descr[] = { | ||
2133 | { ATA_CMD_DEV_RESET, "DEVICE RESET" }, | ||
2134 | { ATA_CMD_CHK_POWER, "CHECK POWER MODE" }, | ||
2135 | { ATA_CMD_STANDBY, "STANDBY" }, | ||
2136 | { ATA_CMD_IDLE, "IDLE" }, | ||
2137 | { ATA_CMD_EDD, "EXECUTE DEVICE DIAGNOSTIC" }, | ||
2138 | { ATA_CMD_DOWNLOAD_MICRO, "DOWNLOAD MICROCODE" }, | ||
2139 | { ATA_CMD_NOP, "NOP" }, | ||
2140 | { ATA_CMD_FLUSH, "FLUSH CACHE" }, | ||
2141 | { ATA_CMD_FLUSH_EXT, "FLUSH CACHE EXT" }, | ||
2142 | { ATA_CMD_ID_ATA, "IDENTIFY DEVICE" }, | ||
2143 | { ATA_CMD_ID_ATAPI, "IDENTIFY PACKET DEVICE" }, | ||
2144 | { ATA_CMD_SERVICE, "SERVICE" }, | ||
2145 | { ATA_CMD_READ, "READ DMA" }, | ||
2146 | { ATA_CMD_READ_EXT, "READ DMA EXT" }, | ||
2147 | { ATA_CMD_READ_QUEUED, "READ DMA QUEUED" }, | ||
2148 | { ATA_CMD_READ_STREAM_EXT, "READ STREAM EXT" }, | ||
2149 | { ATA_CMD_READ_STREAM_DMA_EXT, "READ STREAM DMA EXT" }, | ||
2150 | { ATA_CMD_WRITE, "WRITE DMA" }, | ||
2151 | { ATA_CMD_WRITE_EXT, "WRITE DMA EXT" }, | ||
2152 | { ATA_CMD_WRITE_QUEUED, "WRITE DMA QUEUED EXT" }, | ||
2153 | { ATA_CMD_WRITE_STREAM_EXT, "WRITE STREAM EXT" }, | ||
2154 | { ATA_CMD_WRITE_STREAM_DMA_EXT, "WRITE STREAM DMA EXT" }, | ||
2155 | { ATA_CMD_WRITE_FUA_EXT, "WRITE DMA FUA EXT" }, | ||
2156 | { ATA_CMD_WRITE_QUEUED_FUA_EXT, "WRITE DMA QUEUED FUA EXT" }, | ||
2157 | { ATA_CMD_FPDMA_READ, "READ FPDMA QUEUED" }, | ||
2158 | { ATA_CMD_FPDMA_WRITE, "WRITE FPDMA QUEUED" }, | ||
2159 | { ATA_CMD_PIO_READ, "READ SECTOR(S)" }, | ||
2160 | { ATA_CMD_PIO_READ_EXT, "READ SECTOR(S) EXT" }, | ||
2161 | { ATA_CMD_PIO_WRITE, "WRITE SECTOR(S)" }, | ||
2162 | { ATA_CMD_PIO_WRITE_EXT, "WRITE SECTOR(S) EXT" }, | ||
2163 | { ATA_CMD_READ_MULTI, "READ MULTIPLE" }, | ||
2164 | { ATA_CMD_READ_MULTI_EXT, "READ MULTIPLE EXT" }, | ||
2165 | { ATA_CMD_WRITE_MULTI, "WRITE MULTIPLE" }, | ||
2166 | { ATA_CMD_WRITE_MULTI_EXT, "WRITE MULTIPLE EXT" }, | ||
2167 | { ATA_CMD_WRITE_MULTI_FUA_EXT, "WRITE MULTIPLE FUA EXT" }, | ||
2168 | { ATA_CMD_SET_FEATURES, "SET FEATURES" }, | ||
2169 | { ATA_CMD_SET_MULTI, "SET MULTIPLE MODE" }, | ||
2170 | { ATA_CMD_VERIFY, "READ VERIFY SECTOR(S)" }, | ||
2171 | { ATA_CMD_VERIFY_EXT, "READ VERIFY SECTOR(S) EXT" }, | ||
2172 | { ATA_CMD_WRITE_UNCORR_EXT, "WRITE UNCORRECTABLE EXT" }, | ||
2173 | { ATA_CMD_STANDBYNOW1, "STANDBY IMMEDIATE" }, | ||
2174 | { ATA_CMD_IDLEIMMEDIATE, "IDLE IMMEDIATE" }, | ||
2175 | { ATA_CMD_SLEEP, "SLEEP" }, | ||
2176 | { ATA_CMD_INIT_DEV_PARAMS, "INITIALIZE DEVICE PARAMETERS" }, | ||
2177 | { ATA_CMD_READ_NATIVE_MAX, "READ NATIVE MAX ADDRESS" }, | ||
2178 | { ATA_CMD_READ_NATIVE_MAX_EXT, "READ NATIVE MAX ADDRESS EXT" }, | ||
2179 | { ATA_CMD_SET_MAX, "SET MAX ADDRESS" }, | ||
2180 | { ATA_CMD_SET_MAX_EXT, "SET MAX ADDRESS EXT" }, | ||
2181 | { ATA_CMD_READ_LOG_EXT, "READ LOG EXT" }, | ||
2182 | { ATA_CMD_WRITE_LOG_EXT, "WRITE LOG EXT" }, | ||
2183 | { ATA_CMD_READ_LOG_DMA_EXT, "READ LOG DMA EXT" }, | ||
2184 | { ATA_CMD_WRITE_LOG_DMA_EXT, "WRITE LOG DMA EXT" }, | ||
2185 | { ATA_CMD_TRUSTED_RCV, "TRUSTED RECEIVE" }, | ||
2186 | { ATA_CMD_TRUSTED_RCV_DMA, "TRUSTED RECEIVE DMA" }, | ||
2187 | { ATA_CMD_TRUSTED_SND, "TRUSTED SEND" }, | ||
2188 | { ATA_CMD_TRUSTED_SND_DMA, "TRUSTED SEND DMA" }, | ||
2189 | { ATA_CMD_PMP_READ, "READ BUFFER" }, | ||
2190 | { ATA_CMD_PMP_WRITE, "WRITE BUFFER" }, | ||
2191 | { ATA_CMD_CONF_OVERLAY, "DEVICE CONFIGURATION OVERLAY" }, | ||
2192 | { ATA_CMD_SEC_SET_PASS, "SECURITY SET PASSWORD" }, | ||
2193 | { ATA_CMD_SEC_UNLOCK, "SECURITY UNLOCK" }, | ||
2194 | { ATA_CMD_SEC_ERASE_PREP, "SECURITY ERASE PREPARE" }, | ||
2195 | { ATA_CMD_SEC_ERASE_UNIT, "SECURITY ERASE UNIT" }, | ||
2196 | { ATA_CMD_SEC_FREEZE_LOCK, "SECURITY FREEZE LOCK" }, | ||
2197 | { ATA_CMD_SEC_DISABLE_PASS, "SECURITY DISABLE PASSWORD" }, | ||
2198 | { ATA_CMD_CONFIG_STREAM, "CONFIGURE STREAM" }, | ||
2199 | { ATA_CMD_SMART, "SMART" }, | ||
2200 | { ATA_CMD_MEDIA_LOCK, "DOOR LOCK" }, | ||
2201 | { ATA_CMD_MEDIA_UNLOCK, "DOOR UNLOCK" }, | ||
2202 | { ATA_CMD_CHK_MED_CRD_TYP, "CHECK MEDIA CARD TYPE" }, | ||
2203 | { ATA_CMD_CFA_REQ_EXT_ERR, "CFA REQUEST EXTENDED ERROR" }, | ||
2204 | { ATA_CMD_CFA_WRITE_NE, "CFA WRITE SECTORS WITHOUT ERASE" }, | ||
2205 | { ATA_CMD_CFA_TRANS_SECT, "CFA TRANSLATE SECTOR" }, | ||
2206 | { ATA_CMD_CFA_ERASE, "CFA ERASE SECTORS" }, | ||
2207 | { ATA_CMD_CFA_WRITE_MULT_NE, "CFA WRITE MULTIPLE WITHOUT ERASE" }, | ||
2208 | { ATA_CMD_READ_LONG, "READ LONG (with retries)" }, | ||
2209 | { ATA_CMD_READ_LONG_ONCE, "READ LONG (without retries)" }, | ||
2210 | { ATA_CMD_WRITE_LONG, "WRITE LONG (with retries)" }, | ||
2211 | { ATA_CMD_WRITE_LONG_ONCE, "WRITE LONG (without retries)" }, | ||
2212 | { ATA_CMD_RESTORE, "RECALIBRATE" }, | ||
2213 | { 0, NULL } /* terminate list */ | ||
2214 | }; | ||
2215 | |||
2216 | unsigned int i; | ||
2217 | for (i = 0; cmd_descr[i].text; i++) | ||
2218 | if (cmd_descr[i].command == command) | ||
2219 | return cmd_descr[i].text; | ||
2220 | #endif | ||
2221 | |||
2222 | return NULL; | ||
2223 | } | ||
2224 | |||
2225 | /** | ||
2113 | * ata_eh_link_report - report error handling to user | 2226 | * ata_eh_link_report - report error handling to user |
2114 | * @link: ATA link EH is going on | 2227 | * @link: ATA link EH is going on |
2115 | * | 2228 | * |
@@ -2175,6 +2288,7 @@ static void ata_eh_link_report(struct ata_link *link) | |||
2175 | ata_link_printk(link, KERN_ERR, "%s\n", desc); | 2288 | ata_link_printk(link, KERN_ERR, "%s\n", desc); |
2176 | } | 2289 | } |
2177 | 2290 | ||
2291 | #ifdef CONFIG_ATA_VERBOSE_ERROR | ||
2178 | if (ehc->i.serror) | 2292 | if (ehc->i.serror) |
2179 | ata_link_printk(link, KERN_ERR, | 2293 | ata_link_printk(link, KERN_ERR, |
2180 | "SError: { %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n", | 2294 | "SError: { %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n", |
@@ -2195,6 +2309,7 @@ static void ata_eh_link_report(struct ata_link *link) | |||
2195 | ehc->i.serror & SERR_TRANS_ST_ERROR ? "TrStaTrns " : "", | 2309 | ehc->i.serror & SERR_TRANS_ST_ERROR ? "TrStaTrns " : "", |
2196 | ehc->i.serror & SERR_UNRECOG_FIS ? "UnrecFIS " : "", | 2310 | ehc->i.serror & SERR_UNRECOG_FIS ? "UnrecFIS " : "", |
2197 | ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : ""); | 2311 | ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : ""); |
2312 | #endif | ||
2198 | 2313 | ||
2199 | for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { | 2314 | for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { |
2200 | struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); | 2315 | struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); |
@@ -2226,14 +2341,23 @@ static void ata_eh_link_report(struct ata_link *link) | |||
2226 | dma_str[qc->dma_dir]); | 2341 | dma_str[qc->dma_dir]); |
2227 | } | 2342 | } |
2228 | 2343 | ||
2229 | if (ata_is_atapi(qc->tf.protocol)) | 2344 | if (ata_is_atapi(qc->tf.protocol)) { |
2230 | snprintf(cdb_buf, sizeof(cdb_buf), | 2345 | if (qc->scsicmd) |
2346 | scsi_print_command(qc->scsicmd); | ||
2347 | else | ||
2348 | snprintf(cdb_buf, sizeof(cdb_buf), | ||
2231 | "cdb %02x %02x %02x %02x %02x %02x %02x %02x " | 2349 | "cdb %02x %02x %02x %02x %02x %02x %02x %02x " |
2232 | "%02x %02x %02x %02x %02x %02x %02x %02x\n ", | 2350 | "%02x %02x %02x %02x %02x %02x %02x %02x\n ", |
2233 | cdb[0], cdb[1], cdb[2], cdb[3], | 2351 | cdb[0], cdb[1], cdb[2], cdb[3], |
2234 | cdb[4], cdb[5], cdb[6], cdb[7], | 2352 | cdb[4], cdb[5], cdb[6], cdb[7], |
2235 | cdb[8], cdb[9], cdb[10], cdb[11], | 2353 | cdb[8], cdb[9], cdb[10], cdb[11], |
2236 | cdb[12], cdb[13], cdb[14], cdb[15]); | 2354 | cdb[12], cdb[13], cdb[14], cdb[15]); |
2355 | } else { | ||
2356 | const char *descr = ata_get_cmd_descript(cmd->command); | ||
2357 | if (descr) | ||
2358 | ata_dev_printk(qc->dev, KERN_ERR, | ||
2359 | "failed command: %s\n", descr); | ||
2360 | } | ||
2237 | 2361 | ||
2238 | ata_dev_printk(qc->dev, KERN_ERR, | 2362 | ata_dev_printk(qc->dev, KERN_ERR, |
2239 | "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " | 2363 | "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " |
@@ -2252,6 +2376,7 @@ static void ata_eh_link_report(struct ata_link *link) | |||
2252 | res->device, qc->err_mask, ata_err_string(qc->err_mask), | 2376 | res->device, qc->err_mask, ata_err_string(qc->err_mask), |
2253 | qc->err_mask & AC_ERR_NCQ ? " <F>" : ""); | 2377 | qc->err_mask & AC_ERR_NCQ ? " <F>" : ""); |
2254 | 2378 | ||
2379 | #ifdef CONFIG_ATA_VERBOSE_ERROR | ||
2255 | if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | | 2380 | if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | |
2256 | ATA_ERR)) { | 2381 | ATA_ERR)) { |
2257 | if (res->command & ATA_BUSY) | 2382 | if (res->command & ATA_BUSY) |
@@ -2275,6 +2400,7 @@ static void ata_eh_link_report(struct ata_link *link) | |||
2275 | res->feature & ATA_UNC ? "UNC " : "", | 2400 | res->feature & ATA_UNC ? "UNC " : "", |
2276 | res->feature & ATA_IDNF ? "IDNF " : "", | 2401 | res->feature & ATA_IDNF ? "IDNF " : "", |
2277 | res->feature & ATA_ABORTED ? "ABRT " : ""); | 2402 | res->feature & ATA_ABORTED ? "ABRT " : ""); |
2403 | #endif | ||
2278 | } | 2404 | } |
2279 | } | 2405 | } |
2280 | 2406 | ||
@@ -2574,11 +2700,17 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
2574 | postreset(slave, classes); | 2700 | postreset(slave, classes); |
2575 | } | 2701 | } |
2576 | 2702 | ||
2577 | /* clear cached SError */ | 2703 | /* |
2704 | * Some controllers can't be frozen very well and may set | ||
2705 | * spuruious error conditions during reset. Clear accumulated | ||
2706 | * error information. As reset is the final recovery action, | ||
2707 | * nothing is lost by doing this. | ||
2708 | */ | ||
2578 | spin_lock_irqsave(link->ap->lock, flags); | 2709 | spin_lock_irqsave(link->ap->lock, flags); |
2579 | link->eh_info.serror = 0; | 2710 | memset(&link->eh_info, 0, sizeof(link->eh_info)); |
2580 | if (slave) | 2711 | if (slave) |
2581 | slave->eh_info.serror = 0; | 2712 | memset(&slave->eh_info, 0, sizeof(link->eh_info)); |
2713 | ap->pflags &= ~ATA_PFLAG_EH_PENDING; | ||
2582 | spin_unlock_irqrestore(link->ap->lock, flags); | 2714 | spin_unlock_irqrestore(link->ap->lock, flags); |
2583 | 2715 | ||
2584 | /* Make sure onlineness and classification result correspond. | 2716 | /* Make sure onlineness and classification result correspond. |