diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/Kconfig | 11 | ||||
-rw-r--r-- | drivers/ata/libata-acpi.c | 7 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c | 128 | ||||
-rw-r--r-- | drivers/ata/libata.h | 1 |
4 files changed, 143 insertions, 4 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index b17c57f85032..8e64d3c81d53 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
@@ -26,6 +26,17 @@ config ATA_NONSTANDARD | |||
26 | bool | 26 | bool |
27 | default n | 27 | default n |
28 | 28 | ||
29 | config ATA_VERBOSE_ERROR | ||
30 | bool "Verbose ATA error reporting" | ||
31 | default y | ||
32 | help | ||
33 | This option adds parsing of ATA command descriptions and error bits | ||
34 | in libata kernel output, making it easier to interpret. | ||
35 | This option will enlarge the kernel by approx. 6KB. Disable it only | ||
36 | if kernel size is more important than ease of debugging. | ||
37 | |||
38 | If unsure, say Y. | ||
39 | |||
29 | config ATA_ACPI | 40 | config ATA_ACPI |
30 | bool "ATA ACPI Support" | 41 | bool "ATA ACPI Support" |
31 | depends on ACPI && PCI | 42 | depends on ACPI && PCI |
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index ac176da1f94e..01964b6e6f6b 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -689,6 +689,7 @@ static int ata_acpi_run_tf(struct ata_device *dev, | |||
689 | struct ata_taskfile tf, ptf, rtf; | 689 | struct ata_taskfile tf, ptf, rtf; |
690 | unsigned int err_mask; | 690 | unsigned int err_mask; |
691 | const char *level; | 691 | const char *level; |
692 | const char *descr; | ||
692 | char msg[60]; | 693 | char msg[60]; |
693 | int rc; | 694 | int rc; |
694 | 695 | ||
@@ -736,11 +737,13 @@ static int ata_acpi_run_tf(struct ata_device *dev, | |||
736 | snprintf(msg, sizeof(msg), "filtered out"); | 737 | snprintf(msg, sizeof(msg), "filtered out"); |
737 | rc = 0; | 738 | rc = 0; |
738 | } | 739 | } |
740 | descr = ata_get_cmd_descript(tf.command); | ||
739 | 741 | ||
740 | ata_dev_printk(dev, level, | 742 | ata_dev_printk(dev, level, |
741 | "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x %s\n", | 743 | "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x (%s) %s\n", |
742 | tf.command, tf.feature, tf.nsect, tf.lbal, | 744 | tf.command, tf.feature, tf.nsect, tf.lbal, |
743 | tf.lbam, tf.lbah, tf.device, msg); | 745 | tf.lbam, tf.lbah, tf.device, |
746 | (descr ? descr : "unknown"), msg); | ||
744 | 747 | ||
745 | return rc; | 748 | return rc; |
746 | } | 749 | } |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 2c34de841e11..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> |
@@ -2112,6 +2113,116 @@ void ata_eh_autopsy(struct ata_port *ap) | |||
2112 | } | 2113 | } |
2113 | 2114 | ||
2114 | /** | 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 | /** | ||
2115 | * ata_eh_link_report - report error handling to user | 2226 | * ata_eh_link_report - report error handling to user |
2116 | * @link: ATA link EH is going on | 2227 | * @link: ATA link EH is going on |
2117 | * | 2228 | * |
@@ -2177,6 +2288,7 @@ static void ata_eh_link_report(struct ata_link *link) | |||
2177 | ata_link_printk(link, KERN_ERR, "%s\n", desc); | 2288 | ata_link_printk(link, KERN_ERR, "%s\n", desc); |
2178 | } | 2289 | } |
2179 | 2290 | ||
2291 | #ifdef CONFIG_ATA_VERBOSE_ERROR | ||
2180 | if (ehc->i.serror) | 2292 | if (ehc->i.serror) |
2181 | ata_link_printk(link, KERN_ERR, | 2293 | ata_link_printk(link, KERN_ERR, |
2182 | "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", |
@@ -2197,6 +2309,7 @@ static void ata_eh_link_report(struct ata_link *link) | |||
2197 | ehc->i.serror & SERR_TRANS_ST_ERROR ? "TrStaTrns " : "", | 2309 | ehc->i.serror & SERR_TRANS_ST_ERROR ? "TrStaTrns " : "", |
2198 | ehc->i.serror & SERR_UNRECOG_FIS ? "UnrecFIS " : "", | 2310 | ehc->i.serror & SERR_UNRECOG_FIS ? "UnrecFIS " : "", |
2199 | ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : ""); | 2311 | ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : ""); |
2312 | #endif | ||
2200 | 2313 | ||
2201 | for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { | 2314 | for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { |
2202 | struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); | 2315 | struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); |
@@ -2228,14 +2341,23 @@ static void ata_eh_link_report(struct ata_link *link) | |||
2228 | dma_str[qc->dma_dir]); | 2341 | dma_str[qc->dma_dir]); |
2229 | } | 2342 | } |
2230 | 2343 | ||
2231 | if (ata_is_atapi(qc->tf.protocol)) | 2344 | if (ata_is_atapi(qc->tf.protocol)) { |
2232 | 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), | ||
2233 | "cdb %02x %02x %02x %02x %02x %02x %02x %02x " | 2349 | "cdb %02x %02x %02x %02x %02x %02x %02x %02x " |
2234 | "%02x %02x %02x %02x %02x %02x %02x %02x\n ", | 2350 | "%02x %02x %02x %02x %02x %02x %02x %02x\n ", |
2235 | cdb[0], cdb[1], cdb[2], cdb[3], | 2351 | cdb[0], cdb[1], cdb[2], cdb[3], |
2236 | cdb[4], cdb[5], cdb[6], cdb[7], | 2352 | cdb[4], cdb[5], cdb[6], cdb[7], |
2237 | cdb[8], cdb[9], cdb[10], cdb[11], | 2353 | cdb[8], cdb[9], cdb[10], cdb[11], |
2238 | 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 | } | ||
2239 | 2361 | ||
2240 | ata_dev_printk(qc->dev, KERN_ERR, | 2362 | ata_dev_printk(qc->dev, KERN_ERR, |
2241 | "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 " |
@@ -2254,6 +2376,7 @@ static void ata_eh_link_report(struct ata_link *link) | |||
2254 | res->device, qc->err_mask, ata_err_string(qc->err_mask), | 2376 | res->device, qc->err_mask, ata_err_string(qc->err_mask), |
2255 | qc->err_mask & AC_ERR_NCQ ? " <F>" : ""); | 2377 | qc->err_mask & AC_ERR_NCQ ? " <F>" : ""); |
2256 | 2378 | ||
2379 | #ifdef CONFIG_ATA_VERBOSE_ERROR | ||
2257 | if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | | 2380 | if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | |
2258 | ATA_ERR)) { | 2381 | ATA_ERR)) { |
2259 | if (res->command & ATA_BUSY) | 2382 | if (res->command & ATA_BUSY) |
@@ -2277,6 +2400,7 @@ static void ata_eh_link_report(struct ata_link *link) | |||
2277 | res->feature & ATA_UNC ? "UNC " : "", | 2400 | res->feature & ATA_UNC ? "UNC " : "", |
2278 | res->feature & ATA_IDNF ? "IDNF " : "", | 2401 | res->feature & ATA_IDNF ? "IDNF " : "", |
2279 | res->feature & ATA_ABORTED ? "ABRT " : ""); | 2402 | res->feature & ATA_ABORTED ? "ABRT " : ""); |
2403 | #endif | ||
2280 | } | 2404 | } |
2281 | } | 2405 | } |
2282 | 2406 | ||
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 89a1e0018e71..be8e2628f82c 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h | |||
@@ -164,6 +164,7 @@ extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev, | |||
164 | extern void ata_eh_done(struct ata_link *link, struct ata_device *dev, | 164 | extern void ata_eh_done(struct ata_link *link, struct ata_device *dev, |
165 | unsigned int action); | 165 | unsigned int action); |
166 | extern void ata_eh_autopsy(struct ata_port *ap); | 166 | extern void ata_eh_autopsy(struct ata_port *ap); |
167 | const char *ata_get_cmd_descript(u8 command); | ||
167 | extern void ata_eh_report(struct ata_port *ap); | 168 | extern void ata_eh_report(struct ata_port *ap); |
168 | extern int ata_eh_reset(struct ata_link *link, int classify, | 169 | extern int ata_eh_reset(struct ata_link *link, int classify, |
169 | ata_prereset_fn_t prereset, ata_reset_fn_t softreset, | 170 | ata_prereset_fn_t prereset, ata_reset_fn_t softreset, |