aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libata-eh.c11
-rw-r--r--include/linux/libata.h40
2 files changed, 50 insertions, 1 deletions
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 71ad18b7cff..1968f2d140f 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -229,9 +229,15 @@ void ata_scsi_error(struct Scsi_Host *host)
229 repeat: 229 repeat:
230 /* invoke error handler */ 230 /* invoke error handler */
231 if (ap->ops->error_handler) { 231 if (ap->ops->error_handler) {
232 /* clear EH pending */ 232 /* fetch & clear EH info */
233 spin_lock_irqsave(hs_lock, flags); 233 spin_lock_irqsave(hs_lock, flags);
234
235 memset(&ap->eh_context, 0, sizeof(ap->eh_context));
236 ap->eh_context.i = ap->eh_info;
237 memset(&ap->eh_info, 0, sizeof(ap->eh_info));
238
234 ap->flags &= ~ATA_FLAG_EH_PENDING; 239 ap->flags &= ~ATA_FLAG_EH_PENDING;
240
235 spin_unlock_irqrestore(hs_lock, flags); 241 spin_unlock_irqrestore(hs_lock, flags);
236 242
237 /* invoke EH */ 243 /* invoke EH */
@@ -255,6 +261,9 @@ void ata_scsi_error(struct Scsi_Host *host)
255 "tries, giving up\n", ATA_EH_MAX_REPEAT); 261 "tries, giving up\n", ATA_EH_MAX_REPEAT);
256 } 262 }
257 263
264 /* this run is complete, make sure EH info is clear */
265 memset(&ap->eh_info, 0, sizeof(ap->eh_info));
266
258 /* Clear host_eh_scheduled while holding hs_lock such 267 /* Clear host_eh_scheduled while holding hs_lock such
259 * that if exception occurs after this point but 268 * that if exception occurs after this point but
260 * before EH completion, SCSI midlayer will 269 * before EH completion, SCSI midlayer will
diff --git a/include/linux/libata.h b/include/linux/libata.h
index f5cea13599c..298f9918e37 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -229,6 +229,9 @@ enum {
229 /* ering size */ 229 /* ering size */
230 ATA_ERING_SIZE = 32, 230 ATA_ERING_SIZE = 32,
231 231
232 /* desc_len for ata_eh_info and context */
233 ATA_EH_DESC_LEN = 80,
234
232 /* reset / recovery action types */ 235 /* reset / recovery action types */
233 ATA_EH_REVALIDATE = (1 << 0), 236 ATA_EH_REVALIDATE = (1 << 0),
234 ATA_EH_SOFTRESET = (1 << 1), 237 ATA_EH_SOFTRESET = (1 << 1),
@@ -236,6 +239,9 @@ enum {
236 239
237 ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, 240 ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
238 241
242 /* ata_eh_info->flags */
243 ATA_EHI_DID_RESET = (1 << 0), /* already reset this port */
244
239 /* max repeat if error condition is still set after ->error_handler */ 245 /* max repeat if error condition is still set after ->error_handler */
240 ATA_EH_MAX_REPEAT = 5, 246 ATA_EH_MAX_REPEAT = 5,
241 247
@@ -420,6 +426,21 @@ struct ata_device {
420 struct ata_ering ering; 426 struct ata_ering ering;
421}; 427};
422 428
429struct ata_eh_info {
430 struct ata_device *dev; /* offending device */
431 u32 serror; /* SError from LLDD */
432 unsigned int err_mask; /* port-wide err_mask */
433 unsigned int action; /* ATA_EH_* action mask */
434 unsigned int flags; /* ATA_EHI_* flags */
435 char desc[ATA_EH_DESC_LEN];
436 int desc_len;
437};
438
439struct ata_eh_context {
440 struct ata_eh_info i;
441 int tries[ATA_MAX_DEVICES];
442};
443
423struct ata_port { 444struct ata_port {
424 struct Scsi_Host *host; /* our co-allocated scsi host */ 445 struct Scsi_Host *host; /* our co-allocated scsi host */
425 const struct ata_port_operations *ops; 446 const struct ata_port_operations *ops;
@@ -444,6 +465,11 @@ struct ata_port {
444 unsigned int cbl; /* cable type; ATA_CBL_xxx */ 465 unsigned int cbl; /* cable type; ATA_CBL_xxx */
445 unsigned int sata_spd_limit; /* SATA PHY speed limit */ 466 unsigned int sata_spd_limit; /* SATA PHY speed limit */
446 467
468 /* record runtime error info, protected by host_set lock */
469 struct ata_eh_info eh_info;
470 /* EH context owned by EH */
471 struct ata_eh_context eh_context;
472
447 struct ata_device device[ATA_MAX_DEVICES]; 473 struct ata_device device[ATA_MAX_DEVICES];
448 474
449 struct ata_queued_cmd qcmd[ATA_MAX_QUEUE]; 475 struct ata_queued_cmd qcmd[ATA_MAX_QUEUE];
@@ -711,6 +737,20 @@ extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
711 printk(lv"ata%u.%02u: "fmt, (dev)->ap->id, (dev)->devno , ##args) 737 printk(lv"ata%u.%02u: "fmt, (dev)->ap->id, (dev)->devno , ##args)
712 738
713/* 739/*
740 * ata_eh_info helpers
741 */
742#define ata_ehi_push_desc(ehi, fmt, args...) do { \
743 (ehi)->desc_len += scnprintf((ehi)->desc + (ehi)->desc_len, \
744 ATA_EH_DESC_LEN - (ehi)->desc_len, \
745 fmt , ##args); \
746} while (0)
747
748#define ata_ehi_clear_desc(ehi) do { \
749 (ehi)->desc[0] = '\0'; \
750 (ehi)->desc_len = 0; \
751} while (0)
752
753/*
714 * qc helpers 754 * qc helpers
715 */ 755 */
716static inline int 756static inline int