diff options
author | Kashyap, Desai <kashyap.desai@lsi.com> | 2010-03-18 09:43:10 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-04-11 10:24:04 -0400 |
commit | 7d757f18554070e917f61e7caedf395f940cf853 (patch) | |
tree | 5b77bd5276ee5c02959e4d680420a035eb3c6891 /drivers/message | |
parent | d0f698c46141e1d179fb3a86a0ae668d2fd12916 (diff) |
[SCSI] mptfusion: Updated SCSI IO IOCTL error handling.
Behavior changes only for IOCTLs that time out. Current behavior of
Bus Reset remains the same for RAID Passthru Timeouts Current behavior
of Diagnostic reset for any other type of IOCTL remains the same
CHANGE: For IOCTL SCSI IOs that timeout, a Target Reset TM is sent,
instead of Bus Reset. All error handing from that point is the same as
what the driver currently does, which is to say that if the Device
Reset TM fails it escalates do diagnostic reset.
Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/message')
-rw-r--r-- | drivers/message/fusion/mptctl.c | 161 |
1 files changed, 86 insertions, 75 deletions
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index e6d71e20fa09..e7fab5de16e7 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c | |||
@@ -128,7 +128,6 @@ static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags | |||
128 | struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc); | 128 | struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc); |
129 | static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, | 129 | static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, |
130 | struct buflist *buflist, MPT_ADAPTER *ioc); | 130 | struct buflist *buflist, MPT_ADAPTER *ioc); |
131 | static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function); | ||
132 | 131 | ||
133 | /* | 132 | /* |
134 | * Reset Handler cleanup function | 133 | * Reset Handler cleanup function |
@@ -275,45 +274,6 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) | |||
275 | return 1; | 274 | return 1; |
276 | } | 275 | } |
277 | 276 | ||
278 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
279 | /* mptctl_timeout_expired | ||
280 | * | ||
281 | * Expecting an interrupt, however timed out. | ||
282 | * | ||
283 | */ | ||
284 | static void | ||
285 | mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) | ||
286 | { | ||
287 | unsigned long flags; | ||
288 | |||
289 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n", | ||
290 | ioc->name, __func__)); | ||
291 | |||
292 | if (mpt_fwfault_debug) | ||
293 | mpt_halt_firmware(ioc); | ||
294 | |||
295 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
296 | if (ioc->ioc_reset_in_progress) { | ||
297 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
298 | CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status) | ||
299 | mpt_free_msg_frame(ioc, mf); | ||
300 | return; | ||
301 | } | ||
302 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
303 | |||
304 | |||
305 | if (!mptctl_bus_reset(ioc, mf->u.hdr.Function)) | ||
306 | return; | ||
307 | |||
308 | /* Issue a reset for this device. | ||
309 | * The IOC is not responding. | ||
310 | */ | ||
311 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n", | ||
312 | ioc->name)); | ||
313 | CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status) | ||
314 | mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); | ||
315 | mpt_free_msg_frame(ioc, mf); | ||
316 | } | ||
317 | 277 | ||
318 | static int | 278 | static int |
319 | mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | 279 | mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) |
@@ -343,12 +303,8 @@ mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
343 | return 0; | 303 | return 0; |
344 | } | 304 | } |
345 | 305 | ||
346 | /* mptctl_bus_reset | 306 | static int |
347 | * | 307 | mptctl_do_taskmgmt(MPT_ADAPTER *ioc, u8 tm_type, u8 bus_id, u8 target_id) |
348 | * Bus reset code. | ||
349 | * | ||
350 | */ | ||
351 | static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) | ||
352 | { | 308 | { |
353 | MPT_FRAME_HDR *mf; | 309 | MPT_FRAME_HDR *mf; |
354 | SCSITaskMgmt_t *pScsiTm; | 310 | SCSITaskMgmt_t *pScsiTm; |
@@ -359,13 +315,6 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) | |||
359 | unsigned long time_count; | 315 | unsigned long time_count; |
360 | u16 iocstatus; | 316 | u16 iocstatus; |
361 | 317 | ||
362 | /* bus reset is only good for SCSI IO, RAID PASSTHRU */ | ||
363 | if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || | ||
364 | function == MPI_FUNCTION_SCSI_IO_REQUEST)) { | ||
365 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT | ||
366 | "TaskMgmt, not SCSI_IO!!\n", ioc->name)); | ||
367 | return -EPERM; | ||
368 | } | ||
369 | 318 | ||
370 | mutex_lock(&ioc->taskmgmt_cmds.mutex); | 319 | mutex_lock(&ioc->taskmgmt_cmds.mutex); |
371 | if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { | 320 | if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { |
@@ -375,15 +324,14 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) | |||
375 | 324 | ||
376 | retval = 0; | 325 | retval = 0; |
377 | 326 | ||
378 | /* Send request | ||
379 | */ | ||
380 | mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc); | 327 | mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc); |
381 | if (mf == NULL) { | 328 | if (mf == NULL) { |
382 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT | 329 | dtmprintk(ioc, |
383 | "TaskMgmt, no msg frames!!\n", ioc->name)); | 330 | printk(MYIOC_s_WARN_FMT "TaskMgmt, no msg frames!!\n", |
331 | ioc->name)); | ||
384 | mpt_clear_taskmgmt_in_progress_flag(ioc); | 332 | mpt_clear_taskmgmt_in_progress_flag(ioc); |
385 | retval = -ENOMEM; | 333 | retval = -ENOMEM; |
386 | goto mptctl_bus_reset_done; | 334 | goto tm_done; |
387 | } | 335 | } |
388 | 336 | ||
389 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n", | 337 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n", |
@@ -392,10 +340,13 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) | |||
392 | pScsiTm = (SCSITaskMgmt_t *) mf; | 340 | pScsiTm = (SCSITaskMgmt_t *) mf; |
393 | memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t)); | 341 | memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t)); |
394 | pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; | 342 | pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; |
395 | pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; | 343 | pScsiTm->TaskType = tm_type; |
396 | pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; | 344 | if ((tm_type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && |
397 | pScsiTm->TargetID = 0; | 345 | (ioc->bus_type == FC)) |
398 | pScsiTm->Bus = 0; | 346 | pScsiTm->MsgFlags = |
347 | MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; | ||
348 | pScsiTm->TargetID = target_id; | ||
349 | pScsiTm->Bus = bus_id; | ||
399 | pScsiTm->ChainOffset = 0; | 350 | pScsiTm->ChainOffset = 0; |
400 | pScsiTm->Reserved = 0; | 351 | pScsiTm->Reserved = 0; |
401 | pScsiTm->Reserved1 = 0; | 352 | pScsiTm->Reserved1 = 0; |
@@ -413,17 +364,16 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) | |||
413 | timeout = 30; | 364 | timeout = 30; |
414 | break; | 365 | break; |
415 | case SPI: | 366 | case SPI: |
416 | default: | 367 | default: |
417 | timeout = 2; | 368 | timeout = 10; |
418 | break; | 369 | break; |
419 | } | 370 | } |
420 | 371 | ||
421 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 372 | dtmprintk(ioc, |
422 | "TaskMgmt type=%d timeout=%ld\n", | 373 | printk(MYIOC_s_DEBUG_FMT "TaskMgmt type=%d timeout=%ld\n", |
423 | ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout)); | 374 | ioc->name, tm_type, timeout)); |
424 | 375 | ||
425 | INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status) | 376 | INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status) |
426 | CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) | ||
427 | time_count = jiffies; | 377 | time_count = jiffies; |
428 | if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && | 378 | if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && |
429 | (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) | 379 | (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) |
@@ -432,17 +382,20 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) | |||
432 | retval = mpt_send_handshake_request(mptctl_taskmgmt_id, ioc, | 382 | retval = mpt_send_handshake_request(mptctl_taskmgmt_id, ioc, |
433 | sizeof(SCSITaskMgmt_t), (u32 *)pScsiTm, CAN_SLEEP); | 383 | sizeof(SCSITaskMgmt_t), (u32 *)pScsiTm, CAN_SLEEP); |
434 | if (retval != 0) { | 384 | if (retval != 0) { |
435 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT | 385 | dfailprintk(ioc, |
386 | printk(MYIOC_s_ERR_FMT | ||
436 | "TaskMgmt send_handshake FAILED!" | 387 | "TaskMgmt send_handshake FAILED!" |
437 | " (ioc %p, mf %p, rc=%d) \n", ioc->name, | 388 | " (ioc %p, mf %p, rc=%d) \n", ioc->name, |
438 | ioc, mf, retval)); | 389 | ioc, mf, retval)); |
390 | mpt_free_msg_frame(ioc, mf); | ||
439 | mpt_clear_taskmgmt_in_progress_flag(ioc); | 391 | mpt_clear_taskmgmt_in_progress_flag(ioc); |
440 | goto mptctl_bus_reset_done; | 392 | goto tm_done; |
441 | } | 393 | } |
442 | } | 394 | } |
443 | 395 | ||
444 | /* Now wait for the command to complete */ | 396 | /* Now wait for the command to complete */ |
445 | ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ); | 397 | ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ); |
398 | |||
446 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | 399 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { |
447 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 400 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
448 | "TaskMgmt failed\n", ioc->name)); | 401 | "TaskMgmt failed\n", ioc->name)); |
@@ -452,14 +405,14 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) | |||
452 | retval = 0; | 405 | retval = 0; |
453 | else | 406 | else |
454 | retval = -1; /* return failure */ | 407 | retval = -1; /* return failure */ |
455 | goto mptctl_bus_reset_done; | 408 | goto tm_done; |
456 | } | 409 | } |
457 | 410 | ||
458 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { | 411 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { |
459 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 412 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
460 | "TaskMgmt failed\n", ioc->name)); | 413 | "TaskMgmt failed\n", ioc->name)); |
461 | retval = -1; /* return failure */ | 414 | retval = -1; /* return failure */ |
462 | goto mptctl_bus_reset_done; | 415 | goto tm_done; |
463 | } | 416 | } |
464 | 417 | ||
465 | pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply; | 418 | pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply; |
@@ -467,7 +420,7 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) | |||
467 | "TaskMgmt fw_channel = %d, fw_id = %d, task_type=0x%02X, " | 420 | "TaskMgmt fw_channel = %d, fw_id = %d, task_type=0x%02X, " |
468 | "iocstatus=0x%04X\n\tloginfo=0x%08X, response_code=0x%02X, " | 421 | "iocstatus=0x%04X\n\tloginfo=0x%08X, response_code=0x%02X, " |
469 | "term_cmnds=%d\n", ioc->name, pScsiTmReply->Bus, | 422 | "term_cmnds=%d\n", ioc->name, pScsiTmReply->Bus, |
470 | pScsiTmReply->TargetID, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | 423 | pScsiTmReply->TargetID, tm_type, |
471 | le16_to_cpu(pScsiTmReply->IOCStatus), | 424 | le16_to_cpu(pScsiTmReply->IOCStatus), |
472 | le32_to_cpu(pScsiTmReply->IOCLogInfo), | 425 | le32_to_cpu(pScsiTmReply->IOCLogInfo), |
473 | pScsiTmReply->ResponseCode, | 426 | pScsiTmReply->ResponseCode, |
@@ -485,13 +438,71 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) | |||
485 | retval = -1; /* return failure */ | 438 | retval = -1; /* return failure */ |
486 | } | 439 | } |
487 | 440 | ||
488 | 441 | tm_done: | |
489 | mptctl_bus_reset_done: | ||
490 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | 442 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); |
491 | CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) | 443 | CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) |
492 | return retval; | 444 | return retval; |
493 | } | 445 | } |
494 | 446 | ||
447 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
448 | /* mptctl_timeout_expired | ||
449 | * | ||
450 | * Expecting an interrupt, however timed out. | ||
451 | * | ||
452 | */ | ||
453 | static void | ||
454 | mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) | ||
455 | { | ||
456 | unsigned long flags; | ||
457 | int ret_val = -1; | ||
458 | SCSIIORequest_t *scsi_req = (SCSIIORequest_t *) mf; | ||
459 | u8 function = mf->u.hdr.Function; | ||
460 | |||
461 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n", | ||
462 | ioc->name, __func__)); | ||
463 | |||
464 | if (mpt_fwfault_debug) | ||
465 | mpt_halt_firmware(ioc); | ||
466 | |||
467 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
468 | if (ioc->ioc_reset_in_progress) { | ||
469 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
470 | CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status) | ||
471 | mpt_free_msg_frame(ioc, mf); | ||
472 | return; | ||
473 | } | ||
474 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
475 | |||
476 | |||
477 | CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status) | ||
478 | |||
479 | if (ioc->bus_type == SAS) { | ||
480 | if (function == MPI_FUNCTION_SCSI_IO_REQUEST) | ||
481 | ret_val = mptctl_do_taskmgmt(ioc, | ||
482 | MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, | ||
483 | scsi_req->Bus, scsi_req->TargetID); | ||
484 | else if (function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) | ||
485 | ret_val = mptctl_do_taskmgmt(ioc, | ||
486 | MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | ||
487 | scsi_req->Bus, 0); | ||
488 | if (!ret_val) | ||
489 | return; | ||
490 | } else { | ||
491 | if ((function == MPI_FUNCTION_SCSI_IO_REQUEST) || | ||
492 | (function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) | ||
493 | ret_val = mptctl_do_taskmgmt(ioc, | ||
494 | MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | ||
495 | scsi_req->Bus, 0); | ||
496 | if (!ret_val) | ||
497 | return; | ||
498 | } | ||
499 | |||
500 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling Reset! \n", | ||
501 | ioc->name)); | ||
502 | mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); | ||
503 | mpt_free_msg_frame(ioc, mf); | ||
504 | } | ||
505 | |||
495 | 506 | ||
496 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 507 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
497 | /* mptctl_ioc_reset | 508 | /* mptctl_ioc_reset |