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