aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-05-15 07:58:21 -0400
committerTejun Heo <htejun@gmail.com>2006-05-15 07:58:21 -0400
commitf3e81b19aac23c0e8c55d5961324ef7de44c23bb (patch)
tree9ea0bf3c5ecabb855a78623236d07e7bc2976ca3 /drivers/scsi
parent0c247c559cd70f85ba9f0764ce13ae00e20fcad8 (diff)
[PATCH] libata-eh: implement ata_eh_info and ata_eh_context
struct ata_eh_info serves as the communication channel between execution path and EH. Execution path describes detected error condition in ap->eh_info and EH recovers the port using it. To avoid missing error conditions detected during EH, EH makes its own copy of eh_info and clears it on entry allowing error info to accumulate during EH. Most EH states including EH's copy of eh_info are stored in ap->eh_context (struct ata_eh_context) which is owned by EH and thus doesn't require any synchronization to access and alter. This standardized context makes it easy to integrate various parts of EH and extend EH to handle multiple links (for PM). Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libata-eh.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 71ad18b7cff6..1968f2d140f3 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