diff options
Diffstat (limited to 'drivers/message/fusion/mptscsih.c')
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 459 |
1 files changed, 164 insertions, 295 deletions
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 35173252e948..2463731ed355 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -92,20 +92,24 @@ static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, | |||
92 | SCSIIORequest_t *pReq, int req_idx); | 92 | SCSIIORequest_t *pReq, int req_idx); |
93 | static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); | 93 | static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); |
94 | static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); | 94 | static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); |
95 | static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); | ||
96 | static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); | ||
97 | 95 | ||
98 | static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); | 96 | int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, |
97 | int lun, int ctx2abort, ulong timeout); | ||
99 | 98 | ||
100 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); | 99 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); |
101 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); | 100 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); |
102 | 101 | ||
102 | static void | ||
103 | mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code); | ||
103 | static int mptscsih_get_completion_code(MPT_ADAPTER *ioc, | 104 | static int mptscsih_get_completion_code(MPT_ADAPTER *ioc, |
104 | MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); | 105 | MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); |
105 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); | 106 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); |
106 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); | 107 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); |
107 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); | 108 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); |
108 | 109 | ||
110 | static int | ||
111 | mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type, | ||
112 | SCSITaskMgmtReply_t *pScsiTmReply); | ||
109 | void mptscsih_remove(struct pci_dev *); | 113 | void mptscsih_remove(struct pci_dev *); |
110 | void mptscsih_shutdown(struct pci_dev *); | 114 | void mptscsih_shutdown(struct pci_dev *); |
111 | #ifdef CONFIG_PM | 115 | #ifdef CONFIG_PM |
@@ -1466,8 +1470,8 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) | |||
1466 | 1470 | ||
1467 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1471 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
1468 | /** | 1472 | /** |
1469 | * mptscsih_TMHandler - Generic handler for SCSI Task Management. | 1473 | * mptscsih_IssueTaskMgmt - Generic send Task Management function. |
1470 | * @hd: Pointer to MPT SCSI HOST structure | 1474 | * @hd: Pointer to MPT_SCSI_HOST structure |
1471 | * @type: Task Management type | 1475 | * @type: Task Management type |
1472 | * @channel: channel number for task management | 1476 | * @channel: channel number for task management |
1473 | * @id: Logical Target ID for reset (if appropriate) | 1477 | * @id: Logical Target ID for reset (if appropriate) |
@@ -1475,145 +1479,68 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) | |||
1475 | * @ctx2abort: Context for the task to be aborted (if appropriate) | 1479 | * @ctx2abort: Context for the task to be aborted (if appropriate) |
1476 | * @timeout: timeout for task management control | 1480 | * @timeout: timeout for task management control |
1477 | * | 1481 | * |
1478 | * Fall through to mpt_HardResetHandler if: not operational, too many | 1482 | * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) |
1479 | * failed TM requests or handshake failure. | 1483 | * or a non-interrupt thread. In the former, must not call schedule(). |
1480 | * | 1484 | * |
1481 | * Remark: Currently invoked from a non-interrupt thread (_bh). | 1485 | * Not all fields are meaningfull for all task types. |
1482 | * | 1486 | * |
1483 | * Note: With old EH code, at most 1 SCSI TaskMgmt function per IOC | 1487 | * Returns 0 for SUCCESS, or FAILED. |
1484 | * will be active. | ||
1485 | * | 1488 | * |
1486 | * Returns 0 for SUCCESS, or %FAILED. | ||
1487 | **/ | 1489 | **/ |
1488 | int | 1490 | int |
1489 | mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) | 1491 | mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, |
1492 | int ctx2abort, ulong timeout) | ||
1490 | { | 1493 | { |
1491 | MPT_ADAPTER *ioc; | 1494 | MPT_FRAME_HDR *mf; |
1492 | int rc = -1; | 1495 | SCSITaskMgmt_t *pScsiTm; |
1496 | int ii; | ||
1497 | int retval; | ||
1498 | MPT_ADAPTER *ioc = hd->ioc; | ||
1499 | unsigned long timeleft; | ||
1500 | u8 issue_hard_reset; | ||
1493 | u32 ioc_raw_state; | 1501 | u32 ioc_raw_state; |
1494 | unsigned long flags; | 1502 | unsigned long time_count; |
1495 | |||
1496 | ioc = hd->ioc; | ||
1497 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler Entered!\n", ioc->name)); | ||
1498 | |||
1499 | // SJR - CHECKME - Can we avoid this here? | ||
1500 | // (mpt_HardResetHandler has this check...) | ||
1501 | spin_lock_irqsave(&ioc->diagLock, flags); | ||
1502 | if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) { | ||
1503 | spin_unlock_irqrestore(&ioc->diagLock, flags); | ||
1504 | return FAILED; | ||
1505 | } | ||
1506 | spin_unlock_irqrestore(&ioc->diagLock, flags); | ||
1507 | |||
1508 | /* Wait a fixed amount of time for the TM pending flag to be cleared. | ||
1509 | * If we time out and not bus reset, then we return a FAILED status | ||
1510 | * to the caller. | ||
1511 | * The call to mptscsih_tm_pending_wait() will set the pending flag | ||
1512 | * if we are | ||
1513 | * successful. Otherwise, reload the FW. | ||
1514 | */ | ||
1515 | if (mptscsih_tm_pending_wait(hd) == FAILED) { | ||
1516 | if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { | ||
1517 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler abort: " | ||
1518 | "Timed out waiting for last TM (%d) to complete! \n", | ||
1519 | ioc->name, hd->tmPending)); | ||
1520 | return FAILED; | ||
1521 | } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { | ||
1522 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler target " | ||
1523 | "reset: Timed out waiting for last TM (%d) " | ||
1524 | "to complete! \n", ioc->name, | ||
1525 | hd->tmPending)); | ||
1526 | return FAILED; | ||
1527 | } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { | ||
1528 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler bus reset: " | ||
1529 | "Timed out waiting for last TM (%d) to complete! \n", | ||
1530 | ioc->name, hd->tmPending)); | ||
1531 | return FAILED; | ||
1532 | } | ||
1533 | } else { | ||
1534 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
1535 | hd->tmPending |= (1 << type); | ||
1536 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
1537 | } | ||
1538 | 1503 | ||
1504 | issue_hard_reset = 0; | ||
1539 | ioc_raw_state = mpt_GetIocState(ioc, 0); | 1505 | ioc_raw_state = mpt_GetIocState(ioc, 0); |
1540 | 1506 | ||
1541 | if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { | 1507 | if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { |
1542 | printk(MYIOC_s_WARN_FMT | 1508 | printk(MYIOC_s_WARN_FMT |
1543 | "TM Handler for type=%x: IOC Not operational (0x%x)!\n", | 1509 | "TaskMgmt type=%x: IOC Not operational (0x%x)!\n", |
1544 | ioc->name, type, ioc_raw_state); | 1510 | ioc->name, type, ioc_raw_state); |
1545 | printk(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name); | 1511 | printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n", |
1512 | ioc->name, __func__); | ||
1546 | if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) | 1513 | if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) |
1547 | printk(MYIOC_s_WARN_FMT "TMHandler: HardReset " | 1514 | printk(MYIOC_s_WARN_FMT "TaskMgmt HardReset " |
1548 | "FAILED!!\n", ioc->name); | 1515 | "FAILED!!\n", ioc->name); |
1549 | return FAILED; | 1516 | return 0; |
1550 | } | 1517 | } |
1551 | 1518 | ||
1552 | if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { | 1519 | if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { |
1553 | printk(MYIOC_s_WARN_FMT | 1520 | printk(MYIOC_s_WARN_FMT |
1554 | "TM Handler for type=%x: ioc_state: " | 1521 | "TaskMgmt type=%x: ioc_state: " |
1555 | "DOORBELL_ACTIVE (0x%x)!\n", | 1522 | "DOORBELL_ACTIVE (0x%x)!\n", |
1556 | ioc->name, type, ioc_raw_state); | 1523 | ioc->name, type, ioc_raw_state); |
1557 | return FAILED; | 1524 | return FAILED; |
1558 | } | 1525 | } |
1559 | 1526 | ||
1560 | /* Isse the Task Mgmt request. | 1527 | mutex_lock(&ioc->taskmgmt_cmds.mutex); |
1561 | */ | 1528 | if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { |
1562 | if (hd->hard_resets < -1) | 1529 | mf = NULL; |
1563 | hd->hard_resets++; | 1530 | retval = FAILED; |
1564 | 1531 | goto out; | |
1565 | rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, | 1532 | } |
1566 | ctx2abort, timeout); | ||
1567 | if (rc) | ||
1568 | printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", | ||
1569 | ioc->name); | ||
1570 | else | ||
1571 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n", | ||
1572 | ioc->name)); | ||
1573 | |||
1574 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
1575 | "TMHandler rc = %d!\n", ioc->name, rc)); | ||
1576 | |||
1577 | return rc; | ||
1578 | } | ||
1579 | |||
1580 | |||
1581 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
1582 | /** | ||
1583 | * mptscsih_IssueTaskMgmt - Generic send Task Management function. | ||
1584 | * @hd: Pointer to MPT_SCSI_HOST structure | ||
1585 | * @type: Task Management type | ||
1586 | * @channel: channel number for task management | ||
1587 | * @id: Logical Target ID for reset (if appropriate) | ||
1588 | * @lun: Logical Unit for reset (if appropriate) | ||
1589 | * @ctx2abort: Context for the task to be aborted (if appropriate) | ||
1590 | * @timeout: timeout for task management control | ||
1591 | * | ||
1592 | * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) | ||
1593 | * or a non-interrupt thread. In the former, must not call schedule(). | ||
1594 | * | ||
1595 | * Not all fields are meaningfull for all task types. | ||
1596 | * | ||
1597 | * Returns 0 for SUCCESS, or FAILED. | ||
1598 | * | ||
1599 | **/ | ||
1600 | static int | ||
1601 | mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) | ||
1602 | { | ||
1603 | MPT_FRAME_HDR *mf; | ||
1604 | SCSITaskMgmt_t *pScsiTm; | ||
1605 | int ii; | ||
1606 | int retval; | ||
1607 | MPT_ADAPTER *ioc = hd->ioc; | ||
1608 | 1533 | ||
1609 | /* Return Fail to calling function if no message frames available. | 1534 | /* Return Fail to calling function if no message frames available. |
1610 | */ | 1535 | */ |
1611 | if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { | 1536 | if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { |
1612 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n", | 1537 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
1613 | ioc->name)); | 1538 | "TaskMgmt no msg frames!!\n", ioc->name)); |
1614 | return FAILED; | 1539 | retval = FAILED; |
1540 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
1541 | goto out; | ||
1615 | } | 1542 | } |
1616 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n", | 1543 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n", |
1617 | ioc->name, mf)); | 1544 | ioc->name, mf)); |
1618 | 1545 | ||
1619 | /* Format the Request | 1546 | /* Format the Request |
@@ -1637,11 +1564,14 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i | |||
1637 | 1564 | ||
1638 | pScsiTm->TaskMsgContext = ctx2abort; | 1565 | pScsiTm->TaskMsgContext = ctx2abort; |
1639 | 1566 | ||
1640 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " | 1567 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt: ctx2abort (0x%08x) " |
1641 | "type=%d\n", ioc->name, ctx2abort, type)); | 1568 | "task_type = 0x%02X, timeout = %ld\n", ioc->name, ctx2abort, |
1569 | type, timeout)); | ||
1642 | 1570 | ||
1643 | DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm); | 1571 | DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm); |
1644 | 1572 | ||
1573 | INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status) | ||
1574 | time_count = jiffies; | ||
1645 | if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && | 1575 | if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && |
1646 | (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) | 1576 | (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) |
1647 | mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); | 1577 | mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); |
@@ -1649,47 +1579,50 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i | |||
1649 | retval = mpt_send_handshake_request(ioc->TaskCtx, ioc, | 1579 | retval = mpt_send_handshake_request(ioc->TaskCtx, ioc, |
1650 | sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); | 1580 | sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); |
1651 | if (retval) { | 1581 | if (retval) { |
1652 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!" | 1582 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
1653 | " (hd %p, ioc %p, mf %p, rc=%d) \n", ioc->name, hd, | 1583 | "TaskMgmt handshake FAILED!(mf=%p, rc=%d) \n", |
1654 | ioc, mf, retval)); | 1584 | ioc->name, mf, retval)); |
1655 | goto fail_out; | 1585 | mpt_free_msg_frame(ioc, mf); |
1586 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
1587 | goto out; | ||
1656 | } | 1588 | } |
1657 | } | 1589 | } |
1658 | 1590 | ||
1659 | if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { | 1591 | timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, |
1660 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!" | 1592 | timeout*HZ); |
1661 | " (hd %p, ioc %p, mf %p) \n", ioc->name, hd, | 1593 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { |
1662 | ioc, mf)); | 1594 | retval = FAILED; |
1663 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n", | 1595 | dtmprintk(ioc, printk(MYIOC_s_ERR_FMT |
1664 | ioc->name)); | 1596 | "TaskMgmt TIMED OUT!(mf=%p)\n", ioc->name, mf)); |
1665 | retval = mpt_HardResetHandler(ioc, CAN_SLEEP); | 1597 | mpt_clear_taskmgmt_in_progress_flag(ioc); |
1666 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n", | 1598 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) |
1667 | ioc->name, retval)); | 1599 | goto out; |
1668 | goto fail_out; | 1600 | issue_hard_reset = 1; |
1601 | goto out; | ||
1669 | } | 1602 | } |
1670 | 1603 | ||
1671 | /* | 1604 | retval = mptscsih_taskmgmt_reply(ioc, type, |
1672 | * Handle success case, see if theres a non-zero ioc_status. | 1605 | (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply); |
1673 | */ | ||
1674 | if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS || | ||
1675 | hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || | ||
1676 | hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) | ||
1677 | retval = 0; | ||
1678 | else | ||
1679 | retval = FAILED; | ||
1680 | 1606 | ||
1681 | return retval; | 1607 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
1608 | "TaskMgmt completed (%d seconds)\n", | ||
1609 | ioc->name, jiffies_to_msecs(jiffies - time_count)/1000)); | ||
1682 | 1610 | ||
1683 | fail_out: | 1611 | out: |
1684 | 1612 | ||
1685 | /* | 1613 | CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) |
1686 | * Free task management mf, and corresponding tm flags | 1614 | if (issue_hard_reset) { |
1687 | */ | 1615 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", |
1688 | mpt_free_msg_frame(ioc, mf); | 1616 | ioc->name, __func__); |
1689 | hd->tmPending = 0; | 1617 | retval = mpt_HardResetHandler(ioc, CAN_SLEEP); |
1690 | hd->tmState = TM_STATE_NONE; | 1618 | mpt_free_msg_frame(ioc, mf); |
1691 | return FAILED; | 1619 | } |
1620 | |||
1621 | retval = (retval == 0) ? 0 : FAILED; | ||
1622 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | ||
1623 | return retval; | ||
1692 | } | 1624 | } |
1625 | EXPORT_SYMBOL(mptscsih_IssueTaskMgmt); | ||
1693 | 1626 | ||
1694 | static int | 1627 | static int |
1695 | mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) | 1628 | mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) |
@@ -1799,9 +1732,11 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
1799 | 1732 | ||
1800 | hd->abortSCpnt = SCpnt; | 1733 | hd->abortSCpnt = SCpnt; |
1801 | 1734 | ||
1802 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, | 1735 | retval = mptscsih_IssueTaskMgmt(hd, |
1803 | vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, | 1736 | MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, |
1804 | ctx2abort, mptscsih_get_tm_timeout(ioc)); | 1737 | vdevice->vtarget->channel, |
1738 | vdevice->vtarget->id, vdevice->lun, | ||
1739 | ctx2abort, mptscsih_get_tm_timeout(ioc)); | ||
1805 | 1740 | ||
1806 | if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx && | 1741 | if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx && |
1807 | SCpnt->serial_number == sn) | 1742 | SCpnt->serial_number == sn) |
@@ -1865,9 +1800,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | |||
1865 | goto out; | 1800 | goto out; |
1866 | } | 1801 | } |
1867 | 1802 | ||
1868 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, | 1803 | retval = mptscsih_IssueTaskMgmt(hd, |
1869 | vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0, | 1804 | MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, |
1870 | mptscsih_get_tm_timeout(ioc)); | 1805 | vdevice->vtarget->channel, |
1806 | vdevice->vtarget->id, 0, 0, | ||
1807 | mptscsih_get_tm_timeout(ioc)); | ||
1871 | 1808 | ||
1872 | out: | 1809 | out: |
1873 | printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n", | 1810 | printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n", |
@@ -1914,8 +1851,10 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) | |||
1914 | hd->timeouts++; | 1851 | hd->timeouts++; |
1915 | 1852 | ||
1916 | vdevice = SCpnt->device->hostdata; | 1853 | vdevice = SCpnt->device->hostdata; |
1917 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | 1854 | retval = mptscsih_IssueTaskMgmt(hd, |
1918 | vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc)); | 1855 | MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, |
1856 | vdevice->vtarget->channel, 0, 0, 0, | ||
1857 | mptscsih_get_tm_timeout(ioc)); | ||
1919 | 1858 | ||
1920 | printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n", | 1859 | printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n", |
1921 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); | 1860 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); |
@@ -1976,65 +1915,55 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) | |||
1976 | return retval; | 1915 | return retval; |
1977 | } | 1916 | } |
1978 | 1917 | ||
1979 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
1980 | /** | ||
1981 | * mptscsih_tm_pending_wait - wait for pending task management request to complete | ||
1982 | * @hd: Pointer to MPT host structure. | ||
1983 | * | ||
1984 | * Returns {SUCCESS,FAILED}. | ||
1985 | */ | ||
1986 | static int | 1918 | static int |
1987 | mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) | 1919 | mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type, |
1920 | SCSITaskMgmtReply_t *pScsiTmReply) | ||
1988 | { | 1921 | { |
1989 | unsigned long flags; | 1922 | u16 iocstatus; |
1990 | int loop_count = 4 * 10; /* Wait 10 seconds */ | 1923 | u32 termination_count; |
1991 | int status = FAILED; | 1924 | int retval; |
1992 | MPT_ADAPTER *ioc = hd->ioc; | ||
1993 | 1925 | ||
1994 | do { | 1926 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { |
1995 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 1927 | retval = FAILED; |
1996 | if (hd->tmState == TM_STATE_NONE) { | 1928 | goto out; |
1997 | hd->tmState = TM_STATE_IN_PROGRESS; | 1929 | } |
1998 | hd->tmPending = 1; | ||
1999 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
2000 | status = SUCCESS; | ||
2001 | break; | ||
2002 | } | ||
2003 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
2004 | msleep(250); | ||
2005 | } while (--loop_count); | ||
2006 | 1930 | ||
2007 | return status; | 1931 | DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply); |
2008 | } | ||
2009 | 1932 | ||
2010 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1933 | iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; |
2011 | /** | 1934 | termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); |
2012 | * mptscsih_tm_wait_for_completion - wait for completion of TM task | ||
2013 | * @hd: Pointer to MPT host structure. | ||
2014 | * @timeout: timeout value | ||
2015 | * | ||
2016 | * Returns {SUCCESS,FAILED}. | ||
2017 | */ | ||
2018 | static int | ||
2019 | mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ) | ||
2020 | { | ||
2021 | unsigned long flags; | ||
2022 | int loop_count = 4 * timeout; | ||
2023 | int status = FAILED; | ||
2024 | MPT_ADAPTER *ioc = hd->ioc; | ||
2025 | 1935 | ||
2026 | do { | 1936 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2027 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 1937 | "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n" |
2028 | if(hd->tmPending == 0) { | 1938 | "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n" |
2029 | status = SUCCESS; | 1939 | "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus, |
2030 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 1940 | pScsiTmReply->TargetID, type, le16_to_cpu(pScsiTmReply->IOCStatus), |
2031 | break; | 1941 | le32_to_cpu(pScsiTmReply->IOCLogInfo), pScsiTmReply->ResponseCode, |
2032 | } | 1942 | termination_count)); |
2033 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 1943 | |
2034 | msleep(250); | 1944 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && |
2035 | } while (--loop_count); | 1945 | pScsiTmReply->ResponseCode) |
1946 | mptscsih_taskmgmt_response_code(ioc, | ||
1947 | pScsiTmReply->ResponseCode); | ||
2036 | 1948 | ||
2037 | return status; | 1949 | if (iocstatus == MPI_IOCSTATUS_SUCCESS) { |
1950 | retval = 0; | ||
1951 | goto out; | ||
1952 | } | ||
1953 | |||
1954 | retval = FAILED; | ||
1955 | if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { | ||
1956 | if (termination_count == 1) | ||
1957 | retval = 0; | ||
1958 | goto out; | ||
1959 | } | ||
1960 | |||
1961 | if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || | ||
1962 | iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) | ||
1963 | retval = 0; | ||
1964 | |||
1965 | out: | ||
1966 | return retval; | ||
2038 | } | 1967 | } |
2039 | 1968 | ||
2040 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1969 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -2088,97 +2017,28 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) | |||
2088 | * Returns 1 indicating alloc'd request frame ptr should be freed. | 2017 | * Returns 1 indicating alloc'd request frame ptr should be freed. |
2089 | **/ | 2018 | **/ |
2090 | int | 2019 | int |
2091 | mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | 2020 | mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, |
2021 | MPT_FRAME_HDR *mr) | ||
2092 | { | 2022 | { |
2093 | SCSITaskMgmtReply_t *pScsiTmReply; | 2023 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2094 | SCSITaskMgmt_t *pScsiTmReq; | 2024 | "TaskMgmt completed (mf=%p, mr=%p)\n", ioc->name, mf, mr)); |
2095 | MPT_SCSI_HOST *hd; | ||
2096 | unsigned long flags; | ||
2097 | u16 iocstatus; | ||
2098 | u8 tmType; | ||
2099 | u32 termination_count; | ||
2100 | |||
2101 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", | ||
2102 | ioc->name, mf, mr)); | ||
2103 | if (!ioc->sh) { | ||
2104 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT | ||
2105 | "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); | ||
2106 | return 1; | ||
2107 | } | ||
2108 | |||
2109 | if (mr == NULL) { | ||
2110 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT | ||
2111 | "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf)); | ||
2112 | return 1; | ||
2113 | } | ||
2114 | |||
2115 | hd = shost_priv(ioc->sh); | ||
2116 | pScsiTmReply = (SCSITaskMgmtReply_t*)mr; | ||
2117 | pScsiTmReq = (SCSITaskMgmt_t*)mf; | ||
2118 | tmType = pScsiTmReq->TaskType; | ||
2119 | iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
2120 | termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); | ||
2121 | 2025 | ||
2122 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && | 2026 | ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; |
2123 | pScsiTmReply->ResponseCode) | ||
2124 | mptscsih_taskmgmt_response_code(ioc, | ||
2125 | pScsiTmReply->ResponseCode); | ||
2126 | DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply); | ||
2127 | 2027 | ||
2128 | #ifdef CONFIG_FUSION_LOGGING | 2028 | if (!mr) |
2129 | if ((ioc->debug_level & MPT_DEBUG_REPLY) || | ||
2130 | (ioc->debug_level & MPT_DEBUG_TM )) | ||
2131 | printk("%s: ha=%d [%d:%d:0] task_type=0x%02X " | ||
2132 | "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X " | ||
2133 | "term_cmnds=%d\n", __func__, ioc->id, pScsiTmReply->Bus, | ||
2134 | pScsiTmReply->TargetID, pScsiTmReq->TaskType, | ||
2135 | le16_to_cpu(pScsiTmReply->IOCStatus), | ||
2136 | le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode, | ||
2137 | le32_to_cpu(pScsiTmReply->TerminationCount)); | ||
2138 | #endif | ||
2139 | if (!iocstatus) { | ||
2140 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name)); | ||
2141 | hd->abortSCpnt = NULL; | ||
2142 | goto out; | 2029 | goto out; |
2143 | } | ||
2144 | |||
2145 | /* Error? (anything non-zero?) */ | ||
2146 | |||
2147 | /* clear flags and continue. | ||
2148 | */ | ||
2149 | switch (tmType) { | ||
2150 | |||
2151 | case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK: | ||
2152 | if (termination_count == 1) | ||
2153 | iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED; | ||
2154 | hd->abortSCpnt = NULL; | ||
2155 | break; | ||
2156 | |||
2157 | case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS: | ||
2158 | |||
2159 | /* If an internal command is present | ||
2160 | * or the TM failed - reload the FW. | ||
2161 | * FC FW may respond FAILED to an ABORT | ||
2162 | */ | ||
2163 | if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED || | ||
2164 | hd->cmdPtr) | ||
2165 | if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) | ||
2166 | printk(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name); | ||
2167 | break; | ||
2168 | |||
2169 | case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: | ||
2170 | default: | ||
2171 | break; | ||
2172 | } | ||
2173 | 2030 | ||
2031 | ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID; | ||
2032 | memcpy(ioc->taskmgmt_cmds.reply, mr, | ||
2033 | min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength)); | ||
2174 | out: | 2034 | out: |
2175 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 2035 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) { |
2176 | hd->tmPending = 0; | 2036 | mpt_clear_taskmgmt_in_progress_flag(ioc); |
2177 | hd->tmState = TM_STATE_NONE; | 2037 | ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING; |
2178 | hd->tm_iocstatus = iocstatus; | 2038 | complete(&ioc->taskmgmt_cmds.done); |
2179 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 2039 | return 1; |
2180 | 2040 | } | |
2181 | return 1; | 2041 | return 0; |
2182 | } | 2042 | } |
2183 | 2043 | ||
2184 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2044 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -2901,6 +2761,16 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
2901 | unsigned long timeleft; | 2761 | unsigned long timeleft; |
2902 | unsigned long flags; | 2762 | unsigned long flags; |
2903 | 2763 | ||
2764 | /* don't send internal command during diag reset */ | ||
2765 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
2766 | if (ioc->ioc_reset_in_progress) { | ||
2767 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
2768 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
2769 | "%s: busy with host reset\n", ioc->name, __func__)); | ||
2770 | return MPT_SCANDV_BUSY; | ||
2771 | } | ||
2772 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
2773 | |||
2904 | mutex_lock(&ioc->internal_cmds.mutex); | 2774 | mutex_lock(&ioc->internal_cmds.mutex); |
2905 | 2775 | ||
2906 | /* Set command specific information | 2776 | /* Set command specific information |
@@ -3360,6 +3230,5 @@ EXPORT_SYMBOL(mptscsih_event_process); | |||
3360 | EXPORT_SYMBOL(mptscsih_ioc_reset); | 3230 | EXPORT_SYMBOL(mptscsih_ioc_reset); |
3361 | EXPORT_SYMBOL(mptscsih_change_queue_depth); | 3231 | EXPORT_SYMBOL(mptscsih_change_queue_depth); |
3362 | EXPORT_SYMBOL(mptscsih_timer_expired); | 3232 | EXPORT_SYMBOL(mptscsih_timer_expired); |
3363 | EXPORT_SYMBOL(mptscsih_TMHandler); | ||
3364 | 3233 | ||
3365 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3234 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |