diff options
-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 |